pax_global_header00006660000000000000000000000064141570171430014515gustar00rootroot0000000000000052 comment=d57c3309d28247f19870886eed01436094b1c4f6 vdr-plugin-osdteletext-2.3.1/000077500000000000000000000000001415701714300161515ustar00rootroot00000000000000vdr-plugin-osdteletext-2.3.1/.gitignore000066400000000000000000000000421415701714300201350ustar00rootroot00000000000000.dependencies *.o *.so *.mo *.pot vdr-plugin-osdteletext-2.3.1/COPYING000066400000000000000000000431031415701714300172050ustar00rootroot00000000000000 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 Lesser 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. Copyright (C) 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. , 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 Lesser General Public License instead of this License. vdr-plugin-osdteletext-2.3.1/HISTORY000066400000000000000000000502131415701714300172360ustar00rootroot00000000000000VDR Plugin 'osdteletext' Revision History ----------------------------------------- 2021-12-16: version 2.3.1 - [pbiering] DrawMessage: use scaled font and border to avoid exceeding current TT-OSD size 2021-12-15: - [pbiering] ChannelSwitch: fix bug related to live channel hint in case of current channel has no Teletext 2021-12-12: - [pbiering] ChannelSwitch: add hint about Top40 channels with Teletext - [pbiering] DrawMessage: avoid transparent background on message boxes 2021-12-10: - [pbiering] naming: replace "Line 24" with "Footer Line" and improve text representations 2021-12-09: version 2.3.0 - [pbiering] add support for half bright standard colors and ETSI colors 16-31 - [pbiering] extend 24-Line-Toggle with a 3rd option to display hint lines for standard keys - [pbiering] long option fix "key-levels", add-missing "osd-preset" - [pbiering] limit DrawMessage box to maximum box size 2021-08-06: version 2.2.1 - [pbiering] fix frame in case reaching OSD limits - [pbiering] honor frame value in case of 100% width or height 2021-05-30: version 2.2.0 - [pbiering] adjust range check for "jump to page" 2021-05-22: - [pbiering] fix range check bug related to Hotkey "jump to page" config - [pbiering] fix not working Hotkey level feature in case only 2 levels are active 2021-05-12: - [pbiering] fix in setup changed but not applied to current background transparency 2021-05-11: - [pbiering] fix in OSD config changed but not remembered background transparency 2021-04-22: - [pbiering] remove obsolete setup options suspendReceiving, inactivityTimeout - [pbiering] drop setup option configuredClrBackground and change to "BackTrans" (with multi-preset support) and proper 0-255 logic (not inverted as before) 2021-04-18: - [pbiering] implement optional OSD Hotkey level feature (max. 9 levels with limiter) - [pbiering] implement optional OSD Preset feature (max. 9 presets with limiter) - [pbiering] rework dynamic menu creation related to 'jump to' to fix 'not working on last config entry' issue 2021-04-27: version 2.1.1 - [pbiering] release receiver on live channel switch earlier in sequence to use even on 2-tuner systems by default only one tuner - [pbiering] release device on non-live -> non-live channel switch earlier to avoid locking on 2-tuner systems 2021-04-19: version 2.1.0 - [pbiering] catch case where in tuned mode channel switch is triggered on selected device and switch into cached mode 2021-04-15: - [pbiering] finally catch and handle proper switching from tuned to live channel by outside trigger (e.g. RCU) 2021-04-14: - [pbiering] replace all sleeps related to messages with a delay method, review/catch cases when a channel switch message should be displayed - [pbiering] include channel number in 'invalid channel' message - [pbiering] ChannelSwitch now supports receiving other channels from same transponder or even other transponder (aka "tuned" mode) - [pbiering] various cosmetic fixes 2021-04-11: version 2.0.2 - [pbiering] fixes/cleanup translations of key assignment setup menu 2021-04-11: version 2.0.1 - [pbiering] fix warnings reported by clang - [pbiering] display channel switch message only in case OSD is active - [pbiering] fix G0 character without diacritical mark - [pbiering] bring storage system "packed" back to default 2021-04-11: version 2.0.0 - [pbiering] additional fixes found during regression tests related to translations and others 2021-04-09: - [pbiering] clear teletext page on channel switch 2021-04-08: - [pbiering] many fixes found during regression tests related to MessageBox, too often CleanDisplay calls, ... - [pbiering] display PageId always in case OSD was restarted (useful e.g. for subtitle pages) - [pbiering] selected background color kept on OSD restart 2021-04-07: - [pbiering] cached pages of non-live channel: display page IDs in different color and a 'c' mark, do not trigger useless 'Pause' - [pbiering] channel switch: display message, on empty OK return to live channel - [pbiering] draw bi-colored message frame, increase frame on high resolution, change font on high resolution 2021-04-06: - [pbiering] stop updating clock and blink in case of page update was stopped - [pbiering] display sender name in case page is not found - [pbiering] blacklist Italic and Oblique fonts from being selectable (which causes anyhow issues on displaying because of kerning) - [pbiering] improve font scaling 2021-04-04: - [pbiering] add "Text Font" option to OSD config 2021-04-03: - [pbiering] add support for "G0 character with diacritical mark" by implementation related support of X/26 - [pbiering] introduce new page cache storage format VTXV5 to cover X/25-28 and M/29 extension - [pbiering] fix not working selection of cache-system 'legacy' 2021-03-28: version 1.1.1 - [pbiering] fix missing implementation of graphics char 0x7f (filled rectangle) - [pbiering] implement 'Paused' toggle 2021-03-27: - [pbiering] add backgorund transparency to OSD config mode - [pbiering] remember background color when toggling through 'Half' mode 2021-03-25: - [pbiering] fix/enable toggle support for concealed chars and hint after page number if concealed chars exist, do not display concealed chars by default 2021-03-25: version 1.1.0 - [pbiering] fix related to boxed chars in case page is not boxed itself 2021-03-24: - [pbiering] add 24-line-mode as optional key action toggle 2021-03-23: - [pbiering] implement OSD config mode 2021-03-22: - [pbiering] implement optional black frame - [pbiering] extend half mode with top instead bottom placement - [pbiering] replace bottom black line by button hint line 2021-03-21: - [pbiering] fix broken support of 'blink' - [pbiering] hide clock on boxed pages - [pbiering] show PageId only until 1st update on boxed pages 2021-03-20: - [pbiering] extend README with hints to reference pages (hint from https://www.vdr-portal.de/forum/index.php?thread/134254-osdteletext-1-0-0-released/&postID=1338016#post1338016) 2021-03-12: version 1.0.7 - [pbiering] decrease thread priority to "low" - [pbiering] add info log for thread start/stop (incl. some statistics) - [pbiering] add optional debug log for cTxtReceiver::DecodeTXT 2021-02-28: - [pbiering] align plugin prefix in log, cleanup some EOL code - [pbiering] fix OSD background rectangle size - [pbiering] fix char rectangle size 2021-02-28: version 1.0.6 - [pbiering] fix for 'half' and 'zoom' mode in combination with 24-line mode 2021-02-27: version 1.0.5 - [pbiering] some fixes related to 24-line mode option and double call of CleanDisplay 2021-02-27: version 1.0.4 - [pbiering] add 24-line mode option 2021-02-26: version 1.0.3 - [pbiering] fix 'half' mode 2021-02-25: version 1.0.2 - [pbiering] replace percent based vertical/horizontal center option by top/left (re-add dropped feature) 2021-02-25: version 1.0.1 - [pbiering] add percent based vertical/horizontal center option 2021-02-23: version 1.0.0 - [pbiering] replace OSD sizing options by percent values and always-centric - [pbiering] scale "Text Vertical Offset" according to reduced size 2021-02-19: version 0.9.9 - [pbiering] add fallback to 8 bpp in case OSD is not supporting TrueColor 2021-02-04: - [pbiering] fix obsolete use of readdir_r (credits to ua0lnj) https://github.com/vdr-projects/vdr-plugin-osdteletext/issues/5 2021-02-01: version 0.9.8 - [pbiering] introduce setup option "Text Vertical Offset" ("5" looks good on softhddevice) - [pbiering] fix out-of-bounds message by using new way to calculated x/y position for ClearMessage - [pbiering] merge fix for issues found with OpenGL https://www.vdr-portal.de/forum/index.php?thread/133952-softhddevice-bug-in-opengl-osd-bug-mit-osdteletext/ - [pbiering] merge fix for annoying blank lines in graphics characters https://www.vdr-portal.de/index.php?attachment/41771-osdteletext-0-9-7-patch/ https://www.vdr-portal.de/forum/index.php?thread/131627-gel%C3%B6st-vdr-plugin-osdteletxt-0-9-7/&postID=1303329#post1303329 - [pbiering] add configurable 4bpp color mode base on hardcoded patch: https://www.vdr-portal.de/index.php?attachment/41884-osdteletext-4bpp-diff/ https://www.vdr-portal.de/forum/index.php?thread/131627-gel%C3%B6st-vdr-plugin-osdteletxt-0-9-7/&postID=1304681#post1304681 2018-02-24: version 0.9.7 - Added teletext2.ttf - Cyrillic support added 2018-01-28: version 0.9.6 - Merged the changes from Rolf Ahrenbergs fork pon GitHub (https://github.com/rofafor/vdr-plugin-osdteletext): - VDR 2.3.1 compatibility (patch by 'kandakruemel') - Fixed character drawing - Fixed character conversion table for Finnish/Swedish 2015-02-13: version 0.9.5 - Avoid pkg-config warnings - Improved cleanup when closing OSDTeletext (Thx to Ville Skyttä and Rolf Ahrenberg) 2013-03-10: version 0.9.4 - Allow to override the CXXFLAGS - Fixed CZ font and added CZ-SK subset - patch provided Marek Hajduk (Closes #1134) - Dropped backwards compatibility for VDR 1.6.0 (Closes #944) - Using new standard plugin Makefile from VDR 1.7.39 2012-04-03: version 0.9.3 - VDR 1.7.27 compatibility (Closes #919), Credit goes to nox and gda fro vdrportal.de - Instead of doing mixed drawing to cOsd and cBitmap only draw to cBitmap (Closes #899, this should fixe the issues with the TT6400) 2012-03-25: version 0.9.2 - Some code refactorings (Thx to Ville Skyttä) - FF card transfer mode on channel switch with VDR >= 1.7.25 (Closes: #9) (Thx to Udo Richter) - VDR 1.7.26 compatibility (Thx to Ville Skyttä) - Better live view channel switch detection 2011-08-20: version 0.9.1 - Updated Italian translation provided by Diego Pierotto (Closes #450) - Added Slovak translation provided by Milan Hrala (Closes #558) 2010-11-06: version 0.9.0 - Updated Italian translation provided by Diego Pierotto (Closes #151) - Fix valid page number check in TeletextBrowser::ExecuteAction (Closes #154) - Fixed possible segfault (Closes #179) - (Thx to Manuel Reimer) - Added setup option to disable main menu entry (Closes #149) (Thx to Manuel Reimer!) - Added command line option to enable storing TopText pages, which is now disabled by default (References #177) (Thx to Andreas Brachold!) - Makefile adjustments for VDR 1.7.13. - Don't care if the current channel really changed, if we get a channel switch on the primary device (Thx to Sören Moch) 2009-06-02: version 0.8.3 - Updated Ukrainian translation provided by Yarema P. aka Knedlyk (Closes #133) 2009-05-25: version 0.8.2 - More refactoring of the TxtStatus class (Thx to Sören Moch!) - Install plug-in to lib dir with --remove-destination as suggested by Christian Wieninger (Closes #57) - If background is configured to completely black or transparent, toggle between black and transparent only. - Updated Italian translation provided by Diego Pierotto (Closes #60) - Fixed problems with VDR >= 1.7.3 (not all teletext pages accessible, 4 GByte VTX files) - Removed unnecessary DVBDIR from Makefile 2009-01-10: version 0.8.1 - Small bugfix in channel switching code 2009-01-10: version 0.8.0 - Added Portuguese translation provided by Chris Silva - Updated Italian translation by Davide Cavalca - Removed the "OSD" from the main menu entry as suggested by Davide Cavalca - Added Ukrainian translation provided by Yarema P. aka Knedlyk - Removed obsolete options -R and -r - Remove remnants of VDR < 1.6 support - Updated Russian translation provided by Oleg Roitburd (Closes #46) - Improved error handling - Background toggling now allows to switch between black, the configured background transparency and full transparency as suggested by Walter K. (Closes #41) - Removed the OSDTELETEXT_REINSERTION_PATCH (dead code) - Removed timingdebug code - Merged class ChannelStatus into cTxtStatus and changed the code that detects, if the current live channel has been changed and the OsdTeletext receiver needs to switch to the new channel as well - Updated French translation provided by Nival Michaël (Closes #56) 2008-12-19: version 0.7.0 - switched completely to VDR 1.6's I18N system and removed the old crap - no more support for older VDR versions! (thx to Rolf Ahrenberg) - proper translation of the key bindings (thx to Rolf Ahrenberg) - Partially updated Italian translation by Davide Cavalca 2008-12-02: version 0.6.0 - Moved installation of README and manpage from all to install target - Updated code for VDR 1.6.0 - Changed default location of vtx cache to /var/cache/vdr/vtx - Fixed problems with switching channels on FF+Budget systems See: http://www.vdr-portal.de/board/thread.php?postid=728192#post728192 2005-08-16: version 0.5.1 - show page if it was initially not found but is received later (suggested by Luca Olivetti) - added timeout for user inactivity after which the plugin is closed. Without timeout the plugin would prevent VDR's auto-shutdown mechanism if it remains open. The value is the same as VDR's min user inactivity setup option. (suggested by Peter Bieringer) - fixed gcc4 warnings (thanks to Ville Skyttä) - updated Finnish translation (thanks to Rolf Ahrenberg) - added command line parameter documentation to READMEs - added /var/cache/vdr/osdteletext to the list of recommended cache directories (suggested by Ville Skyttä) 2005-04-21: version 0.5 Udo Richter: - font subsystem now supports Teletext level 1. Fonts are provided for English, German, French, Italian, Spanish, Portuguese, Swedish and Finnish. The correct font is chosen automatically. - support for "boxed mode" (newstickers, subtitles): in 4Bpp mode the area not covered by the box will be completely transparent - OSD can now be aligned on screen: - in horizontal alignment mode, 0 means on the left, 50 in the center and 100 on the right - in vertical alignment mode, 0 means at the top, 50 in the center and 100 at the bottom - default is central alignment - changed palette system, no longer depending on order of indexing - fixed compilation failure with gcc 2.95 - changed OSD minimum size from 480x324 to 320x250 - some bugfixes and comments in txtrecv.c Marcel Wiesweg: - avoid crash and improve behavior when an invalid channel number is entered 2005-03-30: version 0.5-pre1 Udo Richter: - extensive rewrite of display code - removed display.*, txtbitmap.*, colormapping.h - added txtrender.*, displaybase.*, display.* - menu.c adapted to new display engine - speed improvements by incremental drawing - strict adherence to standard 2005-03-21: version 0.4.9-inofficial - rewrite of scaling and drawing code, better scaling algorithm, removed inefficient double painting. Increases speed by a factor of 4. (Udo Richter) - minor fixes for pagenumber, channel number and clock fields to minimize overdrawing (Rolf Ahrenberg) - fix for graphical errors if normal characters are introduced after double high ones (Rolf Ahrenberg) - fix in receiving code to make osdteletext work with some Swedish channels (thanks to Magnus Andersson) - pseudo target in Makefile allows a simple "make". Previously, this would fail and you needed "make all" 2005-03-03: version 0.4.2 - fixes for double-high characters, scaling and localization (thanks to Rolf Ahrenberg for his patch edition) - adapted to VDR API >= 1.3.18, reentrancy fixes - added Spanish and Catalan translation (thanks to Luca Olivetti) - create stored files with 644 permissions (suggested by Andreas Brachold) 2004-09-21: version 0.4.1 - fixed problem with undefined file permissions of created files (thanks to whoever created the patch) - fixed hexadecimal/decimal misinterpretation for "Jump to" key bindings (thanks to Peter Bieringer for pointing this out) - cosmetic change: key Left when entering channel number now resets the cursor by one position, other keys stop entering of page number 2004-06-18: version 0.4 - ported to VDR 1.3/1.4 series (>=1.3.8 now required) This mostly involved changes in the OSD graphics code, - now supports OSDs with color depth of 3 (thanks to Sascha Volkenandt) - rewrote the storage system: - cache directory is now configurable (option -d) Default value is still /vtx to allow seamless migration, but /tmp/vtx is recommended (conforms to LSB etc.) - changed the default file format: Now more than one page is stored in one file. On filesystems that depend on a blocksize the increases storage efficiency. For tmpfs the improvement factor is approx. 4. - The old system is still available via a command line option (though it now uses a slightly different naming) - when no more space is available on disk or a specified number of harddisk space is exceeded (option -n) the folder least recently modified will be deleted. On exit, all files will be deleted, i.e. (!) on exit, all files with suffix .vtx below the storage directory will be deleted - the option -r is now obsolete (will be ignored) option -R/--no-receive is deprecated - code cleanups, removed broken or unused code - fixed quite a few bugs - Added Russian translation (thanks to Vyacheslav Dikonov) 2003-12-2: version 0.3.2 - receiver now uses a ring buffer and a thread to reduce time spent in Receive() function, thus delaying VDR's receiver thread (several people reported problems with bitstreamout - thanks to Christian Jacobsen and Dr. Werner Fink) - fixed and improved the newly introduced receiver thread (thanks to Dr. Werner Fink) - fixed a bug that if there is a double high title on a page, the last line on that page will be missing (fixed by Rolf Ahrenberg) - fixed Finnish translation (thanks to Rolf Ahrenberg) - added Italian translation (thanks to "kikko77") - fixed bug that you could not enter 0 when switching channel (thanks to Dietmar Hilbrich) 2003-04-28: version 0.3.1 - added support for DXR3 systems. Patches contributed by Kai Moeller and Sascha Volkenandt, thanks to them. - the "0" if pressed as first digit now switches between current and last page (as VDR does it with channels) - fixed autosuspend thread 2003-04-03: version 0.3 - fixed two serious memory leaks, thanks to Martin Pley - added feature to automatically update the page if it changed. - moved color definitions to colormapping.h - made width and height configurable, independent from, but with the same mechanism as VDR - made setup menu items dynamic, i.e. the "Page Number" entries are hidden when "Jump to..." is not selected - Experimental: added option to suspend the receiving automatically for 5min after 30s. This may enable you to use your TV set's teletext decoder if you like to. (patch to VDR needed) - Experimental: added an action to immediately suspend receiving, respectively reenable it - added an action to switch the background color between the value you configured in the setup and black - improved color handling when foreground and background color are the same, thanks to Martin Pley - fixed small bug in ChangePageRelative, thanks to Martin Pley - improvements in page switching, thanks to Martin Pley - rewrote parts of the README - added a German README.DE - several fixes and code clean-ups 2003-02-26: version 0.2.1 - fixed two compiling problems with gcc versions other than 3.2 (asprintf, ) - included Finnish translations, thanks to Lauri Tischler - improved Makefile, now uses install instead of mkdir/cp 2003-02-15: version 0.2 - Copied code to receive and save teletext data from original teletext plugin. (appreciating Peter Seyringer's great work) - added command line option to enable the receiving code - added setup options to make key bindings fully configurable. For each key you can choose between the three actions "Zoom", "Half page" or "Switch channel" or use it to jump to a page - added setup option to make background transparency configurable (0...255, VDR's default value being 127) - included Emil Naepflein's patch to improve changing pages relatively - added feature to view saved pages of other channels than the current ("Switch Channel"). Last pages are remembered over channel switching. - fixed bug when the upper half of a page was not automatically shown when using the number keys - page and channel numbers now persist when returning to VDR - added clock which can regularly be updated. (the clock shows the system time, which may definitely be different from the time broadcast via teletext) - added setup option to enable clock - now copies README to ../../man, as Reinhard Walter Buchner suggested 2003-02-05: Version 0.1 - Initial revision. vdr-plugin-osdteletext-2.3.1/Makefile000066400000000000000000000107201415701714300176110ustar00rootroot00000000000000# # Makefile for a Video Disk Recorder plugin # # The official name of this plugin. # This name will be used in the '-P...' option of VDR to load the plugin. # By default the main source file also carries this name. PLUGIN = osdteletext ### The version number of this plugin (taken from the main source file): VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ print $$6 }' | sed -e 's/[";]//g') ### switch compiler ifeq ($(CLANG), 1) CC="clang" CXX="clang++" endif ### The directory environment: # Use package data if installed...otherwise assume we're under the VDR source directory: PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell PKG_CONFIG_PATH="$$PKG_CONFIG_PATH:../../.." pkg-config --variable=$(1) vdr)) LIBDIR = $(call PKGCFG,libdir) LOCDIR = $(call PKGCFG,locdir) PLGCFG = $(call PKGCFG,plgcfg) # TMPDIR ?= /tmp ### The compiler options: export CFLAGS = $(call PKGCFG,cflags) export CXXFLAGS = $(call PKGCFG,cxxflags) ifeq ($(CLANG), 1) $(info ORG CFLAGS=$(CFLAGS)) $(info ORG CXXFLAGS=$(CXXFLAGS)) # remove not supported options (at least Fedora 33) CFLAGS_PKGCFG = $(call PKGCFG,cflags) CXXFLAGS_PKGCFG = $(call PKGCFG,cxxflags) CFLAGS_1 = $(subst -ffat-lto-objects,,$(CFLAGS_PKGCFG)) CXXFLAGS_1 = $(subst -ffat-lto-objects,,$(CXXFLAGS_PKGCFG)) CFLAGS_2 = $(subst -flto=auto,,$(CFLAGS_1)) CXXFLAGS_2 = $(subst -flto=auto,,$(CXXFLAGS_1)) CFLAGS_3 = $(subst -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1,,$(CFLAGS_2)) CXXFLAGS_3 = $(subst -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1,,$(CXXFLAGS_2)) CFLAGS_4 = $(subst -specs=/usr/lib/rpm/redhat/redhat-hardened-ld,,$(CFLAGS_3)) CXXFLAGS_4 = $(subst -specs=/usr/lib/rpm/redhat/redhat-hardened-ld,,$(CXXFLAGS_3)) CFLAGS_5 = $(subst -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1,,$(CFLAGS_4)) CXXFLAGS_5 = $(subst -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1,,$(CXXFLAGS_4)) export CFLAGS = $(CFLAGS_5) export CXXFLAGS = $(CXXFLAGS_5) $(info MOD CFLAGS=$(CFLAGS)) $(info MOD CXXFLAGS=$(CXXFLAGS)) endif ### The version number of VDR's plugin API: APIVERSION = $(call PKGCFG,apiversion) ### Allow user defined options to overwrite defaults: -include $(PLGCFG) ### The name of the distribution archive: ARCHIVE = $(PLUGIN)-$(VERSION) PACKAGE = vdr-$(ARCHIVE) ### The name of the shared object file: SOFILE = libvdr-$(PLUGIN).so ### Includes and Defines (add further entries here): INCLUDES += DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"' ### The object files (add further files here): OBJS = $(PLUGIN).o menu.o txtfont.o txtrecv.o txtrender.o displaybase.o display.o storage.o legacystorage.o packedstorage.o rootdir.o setup.o ### The main target: all: $(SOFILE) i18n ### Implicit rules: %.o: %.c $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $< ### Dependencies: MAKEDEP = $(CXX) -MM -MG DEPFILE = .dependencies $(DEPFILE): Makefile @$(MAKEDEP) $(CPPFLAGS) $(CXXFLAGS) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@ -include $(DEPFILE) ### Internationalization (I18N): PODIR = po I18Npo = $(wildcard $(PODIR)/*.po) I18Nmo = $(addsuffix .mo, $(foreach file, $(I18Npo), $(basename $(file)))) I18Nmsgs = $(addprefix $(DESTDIR)$(LOCDIR)/, $(addsuffix /LC_MESSAGES/vdr-$(PLUGIN).mo, $(notdir $(foreach file, $(I18Npo), $(basename $(file)))))) I18Npot = $(PODIR)/$(PLUGIN).pot %.mo: %.po msgfmt -c -o $@ $< $(I18Npot): $(wildcard *.c) $(wildcard *.h) xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --package-name=vdr-$(PLUGIN) --package-version=$(VERSION) --msgid-bugs-address='' -o $@ `ls $^` %.po: $(I18Npot) msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $< @touch $@ $(I18Nmsgs): $(DESTDIR)$(LOCDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo install -D -m644 $< $@ .PHONY: i18n i18n: $(I18Nmo) $(I18Npot) install-i18n: $(I18Nmsgs) ### Targets: $(SOFILE): $(OBJS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@ install-lib: $(SOFILE) install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION) install: install-lib install-i18n dist: $(I18Npo) clean @-rm -rf $(TMPDIR)/$(ARCHIVE) @mkdir $(TMPDIR)/$(ARCHIVE) @cp -a * $(TMPDIR)/$(ARCHIVE) @tar czf $(PACKAGE).tgz -C $(TMPDIR) --exclude debian --exclude CVS --exclude .svn $(ARCHIVE) @-rm -rf $(TMPDIR)/$(ARCHIVE) @echo Distribution package created as $(PACKAGE).tgz clean: @-rm -f $(PODIR)/*.mo $(PODIR)/*.pot @-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~ vdr-plugin-osdteletext-2.3.1/README000066400000000000000000000224041415701714300170330ustar00rootroot00000000000000This is a "plugin" for the Video Disk Recorder (VDR). Initially Written by: Marcel Wiesweg Original Project's homepage (EOSL): http://www.wiesweg-online.de/linux/vdr Latest version available at: https://github.com/vdr-projects/vdr-plugin-osdteletext See the file COPYING for license information. Alistair Buxtons bitmap2ttf (https://github.com/ali1234/bitmap2ttf) was used to create teletext2.ttf from tv-fonts 1.1 (c) 2002 Gerd Knorr (https://www.kraxel.org/releases/tv-fonts/). The original fonts are public domain. Description: Osd-Teletext displays the teletext directly on the OSD. Installation: You need to install the teletext2.ttf font in order to render special graphics characters properly. Usage: Keys: 1,...,9: insert page number Up: page+ Down: page- Right: sub page+ Left: sub page- Back: close teletext plugin All other user interaction ("Actions") is configurably assigned to the other available keys. You can e.g. configure that you jump to page 100 when you press Red. In this example, the Action "Jump to 100" is assigned to key "Red". Have a look at the plugin's setup page to learn the current assignment and adapt it to your needs. Available Keys: Blue, Red, Yellow, Green, Stop, FastFwd, FastRwd, Ok Actions: "Zoom", "Half page", "Switch channel", "Switch background", "Config", "24-Line-Mode", "Answer", "Pause" "Hotkey Level+", "Hotkey Level-" "OSD Preset+", "OSD Preset-" "Jump to..." a specific page. Description of the actions: Zoom: Zoom to upper half/lower half/back to full page Half Page: Reduce OSD window to the lower half of the screen and display upper half/lower half/back to full size Switch channel:Show pages of a channel different from the one currently tuned to. In case a channel is on same transponder or an additional free tuner is availabe it will change the receiver ("tuned" mode). If not, it stays in "chached" mode and only display pages which were received during tuning to selected channel in the past and pages are stored on disk already. When you press the key associated with that action, you are asked for the channel number. Press OK after you entered it with the number keys. Without providing a channel, OK switches back to live channel Jump to...: Jumps to the page you configure. Switch background: Toggles background transparency between a value configured in setup, fully black, and fully transparent. Config: Enter OSD configuration mode, currently supported Left,Top +/- Width,Height +/- Frame +/- Text Vertical Offset +/- Background Transparency +/- 24-Line-Mode: Toggle Hotkey line (line 25) or add even Hints lines (line 26+27) Answer : Display concealed chars (toggle) OSD will display yellow '?' in case page contains concealed chars OSD will display green '!' while concealed chars are displayed Pause : Stop updating page (toggle) OSD will display red '!' while paused OSD will display green '>' after release (until next page update) ** if enabled/active ** Hotkey Level+ : Change to next Hotkey level (incl. rollover) Hotkey Level- : Change to previous Hotkey level (incl. rollover) Recommended assignment: FastFwd: Hotkey Level+ FastRwd: Hotkey Level- ** if enabled/active ** OSD Preset+ : Change to next OSD preset (incl. rollover) OSD Preset- : Change to previous OSD preset (incl. rollover) Recommended assignment: Stop: OSD Preset- Play: OSD Preset+ How to configure the key bindings: In the plugins setup menu, you can assign one of actions to each key. You can choose freely which actions you need, you are not forced to assign an action to a key at all if you do not need it. If you select "Jump to...", specify the page number in the line immediately below. Other Setup options: Show Clock: Toggles whether an additional clock is drawn approximately every second. The clock shows the current system time, not any time broadcast via teletext. Let VDR set the system time from a transponder to have the exact time. Auto-update pages: Continuously checks whether a page has changed and updates it if yes. Color Mode 4bpp: Enforce 16-color mode (for some older DVB cards) 24-line mode Display (and scale for) only 24 lines Minimum user inactivity: Sets a timeout (in minutes) for user inactivity. When this timespan has elapsed and the user did not press any keys, the plugin will be closed. Set to 0 to disable this. Note that disabling timeout will also effectively disable VDR's auto-shutdown feature as long as the plugin is active. ** optional with multi-preset support ** OSD Presets visible Limit maximum visible presets OSD left, OSD top: Adjusts the left and top edge of the OSD independent from VDR's settings. The valid range is 0% to 90% OSD width, OSD height: Adjusts the width and height of the OSD independent from VDR's settings. The valid range is 10% to 100% Frame: Adjust black surrounding frame sized by amount of pixel Font: Select the font to display text Text Vertical Offset: Adjust the vertical offset by amount of (scaled) pixels The valid range is -10 to 10 (and depending on selected font) Background transparency: number between 0 (black) and 255 (transparency). Default is 128 Hotkey (color key) bindings: See above, optional with multi-level support Key bindings: See above. Command line options: A few settings are given on the command line rather than in the setup menu. Available options: -d --directory=DIR The directory where the temporary files will be stored. (default: /var/cache/vdr/vtx) Ensure that the directory exists and is writable. -n --max-cache=NUM Maximum size in megabytes of cache used to store the pages on the harddisk. (default: a calculated value below 50 MB) -s --cache-system=SYS Set the cache system to be used. Choose "legacy" for the traditional one-file-per-page system. Default is "packed" for the one-file-for-a-few-pages system. -t --toptext Store top text pages at cache. (unviewable pages) -k --key-levels=NUM Maximum amount of Hotkey levels selectable and stored default: 1 (which deactivate this feature) maximum: 9 levels -o --osd-presets=NUM Maximum amount of OSD presets selectable and stored default: 1 (which deactivate this feature) maximum: 9 presets -P|--debugpage Specify page to debug (int: autoconvert internally to hex) -S|--debugpsub Specify sub-page to debug (int: autoconvert internally to hex) -L|--debugline Specify line of page to debug -D|--debugmask Enable debugmask (see logging.h for details) Colors: On all sorts of output devices which are not limited as to color depth the original teletext colors will be displayed. (Only difference: Cyan is used instead of white to make reading easier). On the classic full-featured DVB card and other limited devices, the colors will be reduced to four. The mapping is currently optimized for German ARD, ZDF and RTL. If you are for some reason really and definitely not satisfied with my choices, edit colormapping.h and recompile. Testpages for verification Page | Reference Channel: 3sat 109 | https://blog.3sat.de/ttx/index.php?p=109_0001&c=0 ('@' char) 898-01 | https://blog.3sat.de/ttx/index.php?p=898_0001&c=0 898-02 | https://blog.3sat.de/ttx/index.php?p=898_0002&c=0 899-01 | https://blog.3sat.de/ttx/index.php?p=899_0001&c=0 899-02 | https://blog.3sat.de/ttx/index.php?p=899_0002&c=0 Channel: arte 199-01 Channel: rbb 199-01 199-02 Channel: ORF2 886-00 Channel: ARD https://www.ard-text.de/index.php?page= (currently none) Channel: ZDFinfo 199-01 199-02 199-03 Subtitle pages for verification Channel: DasErste / BR Fernsehen 150 Channel: 3sat 777 vdr-plugin-osdteletext-2.3.1/README.DE000066400000000000000000000203421415701714300173210ustar00rootroot00000000000000Beschreibung: OSD-Teletext zeigt Videotext direkt auf dem OSD an. Im Hintergrund gibt es weiterhin Bild und Ton. Tasten: 1,...,9: Seitenzahl eingeben Hoch: Seite weiter Herunter:Seite zurück Rechts: Unterseite weiter Links: Unterseite zurück Zurück: Videotext-Plugin schließen Die restliche Bedienung ("Aktionen") durch die anderen Tasten ist frei konfigurierbar. Man kann z.B. einstellen, das die man mit der Taste Rot auf die Seite 100 springt. Bei dieser Einstellung wäre die Aktion "Springe zu 100" der Taste Rot zugeordnet. Verfügbare Tasten: Blau, Rot, Gelb, Grün, Stop, Schneller Vorlauf, Schn. Rücklauf, OK Aktionen: "Vergrößern", "Halbe Seite", "Kanal wechseln", "Hotkey Ebene+", "Hotkey Ebene-" "OSD Voreinstellung+", "OSD Voreinstellung-" "Hintergrund wechseln", "Springe zu..." einer bestimmten Seite Beschreibung der Aktionen: Vergrößern: Obere / untere Hälfte vergrößern / zurück zur ganzen Seite Halbe Seite: OSD-Fenster nur noch in unterer Hälfte des Bildschirms zeigen und obere / untere Hälfte anzeigen bzw. zurück Kanal wechseln:Seiten eines anderen Senders als des gerade eingestellten anzeigen. Falls der Sender auf dem selben Transponder oder mittels eines freien Tuners verfügbar ist, wird der Empfänger umgeschaltet. Andernfalls sind nur Seiten verfügbar, die vorher gespeichert wurden, als der Kanal ausgewählt wurde. Bei Aufruf der Aktion wird nach der Kanalnummer gefragt. Die Nummer mit den Zifferntasten eingeben und OK drücken. Falls keine Nummer eingegeben wurde, wird zum Live-Kanal gewechselt. Springe zu...: Springt zu der entsprechenden Seite Hintergrund wechseln: Ändert die im Setup einstellbare Hintergrundfarbe sofort zu Schwarz und nach erneutem Aufruf wieder zurück. Konfiguration: Aktiviere den OSD Konfigurations-Modus, aktuell unterstützt Links,Oben +/- Breite,Höhe +/- Rahmen +/- Zeichensatz Text Vertikaer Offset +/- Hintergrund Transparenz +/- 24-Zeilen-Modus: Umschalten Hotkey Zeile (Zeile 25) oder zusätzliche Hinweiszeilen (line 26+27) Antwort : Zeige versteckte Zeichen (Umschalter) OSD zeigt ein gelbes '?' im Fall daß die Seite versteckte Zeichen enthält OSD zeigt ein grünes '!' während versteckte Zeichen angezeigt werden Pause : Stoppt Aktualisierung der Seite (Umschalter) OSD zeigt rotes '!' während die Aktualisierug pausiert OSD zeigt green '>' nachdem die Pause deaktiviert wurde (bis zur nächsten Aktualisierung der Seite) ** falls eingeschaltet/aktiv ** Hotkey Ebene+ : Wechsle zur nächsten Hotkey Ebene (incl. Rollover) Hotkey Ebene- : Wechsle zur vorherigen Hotkey Ebene (incl. Rollover) Empfohlene Zuweisung: FastFwd: Hotkey Ebene+ FastRwd: Hotkey Ebene- ** falls eingeschaltet/aktiv ** OSD Preset+ : Wechsle zur nächsten OSD Voreinstellung (incl. Rollover) OSD Preset- : Wechsle zur vorherigen OSD Voreinstellung (incl. rollover) Empfohlene Zuweisung: Stopp : OSD Preset- Wiedergabe: OSD Preset+ Wie man Tasten Aktionen zuordnet: Im Einstellungsmenü des Plugins kann jeder Taste eine Aktion zugeordnet werden. Dabei ist nichts vorgeschrieben - keine Aktion muss irgendeiner Taste zugewiesen werden, wenn sie nicht benötigt wird. Bei Auswahl von "Springe zu..." wird die Seitennummer in der Zeile direkt darunter angegeben. Andere Optionen: Zeige Uhr: Diese Option bestimmt, ob etwa im Sekundenabstand zusätzlich eine Uhr angezeigt wird. Die Uhr zeigt die aktuelle Systemzeit, nicht die mit dem Videotext ausgestrahlte Zeit. Um genaue Werte zu haben, kann VDR die Systemzeit von einem Transponder einstellen. Automatisch aktualisieren: Überprüft ständig, ob sich die Seite geändert hat und aktualisiert sie wenn nötig 16-Farben-Modus: Benutze nur 16 Farben (4-Bit) (für ältere DVB Karten) Mindest Benutzer-Inaktivität: Bestimmt die Zeit (in Minuten), nach der das Plugin automatisch geschlossen wird, wenn der Benutzer solange keine Taste betätigt hat. Das kann durch setzen des Wertes auf 0 verhindert werden. Dann wird jedoch auch das automatische Abschalten von VDR effektiv außer Kraft gesetzt, solange das Plugin geöffnet ist. ** optional mit Unterstützung mehrerer Voreinstellungen ** OSD-Breite, OSD-Höhe: Hier kann die Größe des OSD unabhängig von den Einstellungen für VDR bestimmt werden. Valider Bereich zwischen 10% und 100% OSD Links, OSD Oben: Hier kann die linke/obere Ecke des OSD unabhängig von den Einstellungen für VDR bestimmt werden. Valider Bereich zwischen 0% und 90% Zeichensatz: Hier kann der Zeichensatz ausgewählt werden Vertikaler Text Offset: Justage des vertikalen Offsets für Textdarstellung bei einer (skalierten) Anzahl von Pixels Valider Bereich zwischen -10 und 10 (und abhängig vom ausgewählten Font) Hintergrund-Transparenz: Zahl zwischen 0 (schwarz) und 255 (transparenz). Vorgegeben ist 128 (wie auch von VDR) Hotkey (Farb-)Tasten einrichten: siehe oben, optional mit multi-Ebenen-Unterstützung Tasten einrichten: siehe oben Kommandozeilen-Optionen: Einige Einstellungen werden über die Kommandozeile anstatt über das Menü gesetzt. Verfügbare Optionen: -d --directory=DIR Das Verzeichnis für die temporären Dateien. (Voreinstellung: /var/cache/vdr/vtx) Stellen Sie sicher, dass das Verzeichnis existiert und beschreibbar ist. -n --max-cache=NUM Maximale Größe des Zwischenspeichers für Seiten auf der Festplatte. (Voreinstellung: ein berechneter Wert unter 50 MB) -s --cache-system=SYS Das zu benutzende Zwischenspeichersystem. Wählen Sie "legacy" für das althergebrachte System "Eine Datei - eine Seite". Voreinstellung ist "packed" für ein System, das in eine Datei mehrere Seiten speichert. -t --toptext Speichere TopText Seiten (nich anzeigbar) -k --key-levels=NUM Maximale Anzahl von Hot Key Ebenen für Auswahl und Speicherung Standard: 1 (deaktiviert diese Erweiterung) Maximum: 9 Ebenen -o --osd-presets=NUM Maximale Anzahl von OSD Voreinstellungen für Auswahl und Speicherung Standard: 1 (deaktiviert diese Erweiterung) Maximum: 9 Voreinstellungen -P|--debugpage Spezifiziere Seite für Debugging (int: intern automatisch konvertiert nach hex) -S|--debugpsub Spezifiziere Unterseite für Debugging (int: intern automatisch konvertiert nach hex) -L|--debugline Spezifiziere Zeile für Debugging -D|--debugmask Aktiviere Debug-Maske (siehe logging.h für Details) Farben: Auf allen Ausgabegeräten, die nicht in der Farbtiefe des OSD beschränkt sind, werden die unveränderten Farben des Videotexts dargestellt (einzig Weiß wurde zum Zwecke der besseren Lesbarkeit durch Cyan ersetzt). Für die klassische DVB-Karte mit Hardware-Dekoder und anderen so beschränkten Geräten werden nur vier Farben dargestellt. Die Zuordnung ist auf ARD, ZDF und RTL optimiert. Sollten Sie aus irgendeinem Grund absolut nicht meiner Meinung sein, passen Sie die Datei colormapping.h an und kompilieren Sie neu. vdr-plugin-osdteletext-2.3.1/TODO000066400000000000000000000003251415701714300166410ustar00rootroot00000000000000- in case "show clock" is disabled but teletext page provides clock, update related regions automatically Channel 3sat incl. blinking ":" - extend UTF8toTeletextChar with further mappings - extend X/26 support vdr-plugin-osdteletext-2.3.1/display.c000066400000000000000000000364041415701714300177710ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) 2005 by Udo Richter * * Copyright (c) 2021 by Peter Bieringer (extenions) * * * * display.c - Actual implementation of OSD display variants and * * Display:: namespace that encapsulates a single cDisplay. * * * * 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 #include #include #include "setup.h" #include "display.h" #include "txtfont.h" #include "logging.h" // Static variables of Display:: namespace Display::Mode Display::mode=Display::Full; cDisplay *Display::display=NULL; void Display::SetMode(Display::Mode NewMode, tColor clrBackground) { // Background is optional and default predefined in display.h int hChars = 40; int vLines = TT_DISPLAY_LINES; int OSDwidth; int OSDheight; int OSDleftFrame = 0; int OSDrightFrame = 0; int OSDtopFrame = 0; int OSDbottomFrame = 0; int x0 = cOsd::OsdLeft(); // start with general OSD offset int y0 = cOsd::OsdTop(); // start with general OSD offset // (re-)set display mode. if (display!=NULL && NewMode==mode) return; // No change, nothing to do // calculate from percentage and OSD maximum OSDwidth = (cOsd::OsdWidth() * TTSETUPPRESET(Width) ) / 100; OSDheight = (cOsd::OsdHeight() * TTSETUPPRESET(Height)) / 100; // align with hChars/vLines if ((OSDwidth % hChars) > 0) OSDwidth = (OSDwidth / hChars) * hChars; if ((OSDheight % vLines) > 0) OSDheight = (OSDheight / vLines) * vLines; if (TTSETUPPRESET(Width) < 100) { if (TTSETUPPRESET(Left) > 0) { // check offset not exceeding maximum possible if ((TTSETUPPRESET(Width) + TTSETUPPRESET(Left)) > 100) { // shift to maximum x0 += cOsd::OsdWidth() - OSDwidth; } else { // add configured offset x0 += (cOsd::OsdWidth() * TTSETUPPRESET(Left)) / 100; // add 50% of alignment offset to center proper x0 += ((cOsd::OsdWidth() * TTSETUPPRESET(Width)) / 100 - OSDwidth) / 2; }; }; if (TTSETUPPRESET(Frame) > 0) { OSDleftFrame = TTSETUPPRESET(Frame); OSDrightFrame = TTSETUPPRESET(Frame); x0 -= OSDleftFrame; if (x0 < cOsd::OsdLeft()) { OSDleftFrame += x0 - cOsd::OsdLeft(); x0 = cOsd::OsdLeft(); }; if (OSDleftFrame < 0) OSDleftFrame = 0; if (x0 + OSDwidth + OSDrightFrame + OSDleftFrame > cOsd::OsdWidth() + cOsd::OsdLeft()) { // limit right frame instead drawing out-of-area OSDrightFrame = cOsd::OsdWidth() - OSDwidth - x0 - OSDleftFrame + cOsd::OsdLeft(); if (OSDrightFrame < 0) OSDrightFrame = 0; }; }; } else { // horizontal center with black frame left/right OSDleftFrame = (cOsd::OsdWidth() - OSDwidth) / 2; OSDrightFrame = cOsd::OsdWidth() - OSDwidth - OSDleftFrame; if ((OSDleftFrame > 0) && (OSDleftFrame > TTSETUPPRESET(Frame))) { x0 += OSDleftFrame - TTSETUPPRESET(Frame); OSDleftFrame = TTSETUPPRESET(Frame); }; if ((OSDrightFrame > 0) && (OSDrightFrame > TTSETUPPRESET(Frame))) { OSDrightFrame = TTSETUPPRESET(Frame); }; }; if (TTSETUPPRESET(Height) < 100) { if (TTSETUPPRESET(Top) > 0) { // check offset not exceeding maximum possible if ((TTSETUPPRESET(Height) + TTSETUPPRESET(Top)) > 100) { // shift to maximum y0 += cOsd::OsdHeight() - OSDheight; } else { // add configured offset y0 += (cOsd::OsdHeight() * TTSETUPPRESET(Top)) / 100; // add 50% of alignment offset to center proper y0 += ((cOsd::OsdHeight() * TTSETUPPRESET(Height)) / 100 - OSDheight) / 2; }; }; if (TTSETUPPRESET(Frame) > 0) { OSDtopFrame = TTSETUPPRESET(Frame); OSDbottomFrame = TTSETUPPRESET(Frame); y0 -= OSDtopFrame; if (y0 < cOsd::OsdTop()) { OSDtopFrame += y0 - cOsd::OsdTop(); y0 = cOsd::OsdTop(); }; if (OSDtopFrame < 0) OSDtopFrame = 0; if (y0 + OSDheight + OSDtopFrame + OSDbottomFrame > cOsd::OsdHeight() + cOsd::OsdTop()) { // limit bottom frame instead drawing out-of-area OSDbottomFrame = cOsd::OsdHeight() - OSDheight - y0 - OSDtopFrame + cOsd::OsdTop(); if (OSDbottomFrame < 0) OSDbottomFrame = 0; }; }; } else { // vertical center with black frame top/bottom OSDtopFrame = (cOsd::OsdHeight() - OSDheight) / 2; OSDbottomFrame = cOsd::OsdHeight() - OSDheight - OSDtopFrame; if ((OSDtopFrame > 0) && (OSDtopFrame > TTSETUPPRESET(Frame))) { y0 += OSDtopFrame - TTSETUPPRESET(Frame); OSDtopFrame = TTSETUPPRESET(Frame); }; if ((OSDbottomFrame > 0) && (OSDbottomFrame > TTSETUPPRESET(Frame))) { OSDbottomFrame = TTSETUPPRESET(Frame); }; }; DEBUG_OT_AREA("osdteletext: OSD area calculated by percent values: OL=%d OT=%d OW=%d OH=%d OwP=%d%% OhP=%d%% OlP=%d%% OtP=%d%% OfPx=%d lineMode24=%d => x0=%d y0=%d Ow=%d Oh=%d OlF=%d OrF=%d OtF=%d ObF=%d" , cOsd::OsdLeft(), cOsd::OsdTop(), cOsd::OsdWidth(), cOsd::OsdHeight() , TTSETUPPRESET(Width), TTSETUPPRESET(Height), TTSETUPPRESET(Left), TTSETUPPRESET(Top) , TTSETUPPRESET(Frame) , ttSetup.lineMode24 , x0, y0 , OSDwidth, OSDheight , OSDleftFrame, OSDrightFrame , OSDtopFrame, OSDbottomFrame ); switch (NewMode) { case Display::Full: // Need to re-initialize *display: DEBUG_OT_DBFC("osdteletext: OSD 'full' Full->reinit display"); Delete(); // Try 32BPP display first: display=new cDisplay32BPP(x0,y0,OSDwidth,OSDheight,OSDleftFrame,OSDrightFrame,OSDtopFrame,OSDbottomFrame,clrBackground); break; case Display::HalfUpper: // Shortcut to switch from HalfUpper to HalfLower: if (mode==Display::HalfLower) { DEBUG_OT_DBFC("osdteletext: OSD 'half' shortcut HalfUpper->HalfLower"); // keep instance. ((cDisplay32BPPHalf*)display)->SetZoom(cDisplay::Zoom_Upper); ((cDisplay32BPPHalf*)display)->SetUpper(true); ((cDisplay32BPPHalf*)display)->SetTop(false); break; } // Need to re-initialize *display: DEBUG_OT_DBFC("osdteletext: OSD 'half' HalfUpper->reinit display"); Delete(); display=new cDisplay32BPPHalf(x0,y0,OSDwidth,OSDheight,OSDleftFrame,OSDrightFrame,OSDtopFrame,OSDbottomFrame,true,false,clrBackground); ((cDisplay32BPPHalf*)display)->SetZoom(cDisplay::Zoom_Upper); break; case Display::HalfUpperTop: // Shortcut to switch from HalfUpperTop to HalfLowerTop: if (mode==Display::HalfLowerTop) { // keep instance. ((cDisplay32BPPHalf*)display)->SetZoom(cDisplay::Zoom_Upper); ((cDisplay32BPPHalf*)display)->SetUpper(true); ((cDisplay32BPPHalf*)display)->SetTop(true); break; } // Need to re-initialize *display: DEBUG_OT_DBFC("osdteletext: OSD 'half' HalfUpperTop->reinit display"); Delete(); display=new cDisplay32BPPHalf(x0,y0,OSDwidth,OSDheight,OSDleftFrame,OSDrightFrame,OSDtopFrame,OSDbottomFrame,true,true,clrBackground); ((cDisplay32BPPHalf*)display)->SetZoom(cDisplay::Zoom_Upper); break; case Display::HalfLower: // Shortcut to switch from HalfUpper to HalfLower: if (mode==Display::HalfUpper) { DEBUG_OT_DBFC("osdteletext: OSD 'half' shortcut HalfLower->HalfUpper"); // keep instance. ((cDisplay32BPPHalf*)display)->SetZoom(cDisplay::Zoom_Lower); ((cDisplay32BPPHalf*)display)->SetUpper(false); ((cDisplay32BPPHalf*)display)->SetTop(false); break; } // Need to re-initialize *display: DEBUG_OT_DBFC("osdteletext: OSD 'half' HalfLower->reinit display"); Delete(); display=new cDisplay32BPPHalf(x0,y0,OSDwidth,OSDheight,OSDleftFrame,OSDrightFrame,OSDtopFrame,OSDbottomFrame,false,false,clrBackground); ((cDisplay32BPPHalf*)display)->SetZoom(cDisplay::Zoom_Lower); break; case Display::HalfLowerTop: // Shortcut to switch from HalfUpperTop to HalfLowerTop: if (mode==Display::HalfUpperTop) { DEBUG_OT_DBFC("osdteletext: OSD 'half' shortcut HalfUpperTop->HalfLowerTop"); // keep instance. ((cDisplay32BPPHalf*)display)->SetZoom(cDisplay::Zoom_Lower); ((cDisplay32BPPHalf*)display)->SetUpper(false); ((cDisplay32BPPHalf*)display)->SetTop(true); break; } // Need to re-initialize *display: DEBUG_OT_DBFC("osdteletext: OSD 'half' HalfLowerTop->reinit display"); Delete(); display=new cDisplay32BPPHalf(x0,y0,OSDwidth,OSDheight,OSDleftFrame,OSDrightFrame,OSDtopFrame,OSDbottomFrame,false,true,clrBackground); ((cDisplay32BPPHalf*)display)->SetZoom(cDisplay::Zoom_Lower); break; } mode=NewMode; // If display is invalid, clean up immediately: if (!display->Valid()) Delete(); } void Display::ShowUpperHalf() { // Enforce upper half of screen to be visible if (GetZoom()==cDisplay::Zoom_Lower) SetZoom(cDisplay::Zoom_Upper); if (mode==HalfLower) SetMode(HalfUpper); } cDisplay32BPP::cDisplay32BPP(int x0, int y0, int width, int height, int leftFrame, int rightFrame, int topFrame, int bottomFrame, tColor clrBackground) : cDisplay(width,height) { // 32BPP display for True Color OSD providers osd = cOsdProvider::NewOsd(x0, y0); if (!osd) return; Background = clrBackground; width=(width+1)&~1; // Width has to end on byte boundary, so round up int bpp = 32; if (ttSetup.colorMode4bpp == true) { bpp = 4; dsyslog("osdteletext: OSD config forced to bpp=%d", bpp); }; tArea Areas[] = { { 0, 0, width - 1 + leftFrame + rightFrame, height - 1 + topFrame + bottomFrame, bpp } }; if (bpp == 32 && (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) != oeOk)) { bpp = 8; Areas[0].bpp = 8; DEBUG_OT_AREA("osdteletext: OSD is not providing TrueColor, fallback to bpp=%d", bpp); } if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) != oeOk) { DELETENULL(osd); esyslog("osdteletext: can't create requested OSD area with x0=%d y0=%d width=%d height=%d bpp=%d osdPreset=%d", x0, y0, width, height, bpp , ttSetup.osdPreset ); Skins.Message(mtError, "OSD-Teletext can't request OSD area, check plugin settings"); return; } osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); setOutputWidth(width); setOutputHeight(Height); setLeftFrame(leftFrame); setRightFrame(rightFrame); setTopFrame(topFrame); setBottomFrame(bottomFrame); isyslog("osdteletext: OSD area successful requested with x0=%d y0=%d width=%d height=%d bpp=%d lF=%d rF=%d tF=%d bF=%d bg=0x%08x osdPreset=%d" , x0, y0, width, height, bpp , leftFrame, rightFrame, topFrame, bottomFrame , clrBackground , ttSetup.osdPreset ); InitScaler(); CleanDisplay(); Dirty=true; DirtyAll=true; } cDisplay32BPPHalf::cDisplay32BPPHalf(int x0, int y0, int width, int height, int leftFrame, int rightFrame, int topFrame, int bottomFrame, bool upper, bool top, tColor clrBackground) : cDisplay(width,height), leftFrame(leftFrame) , rightFrame(rightFrame), topFrame(topFrame), bottomFrame(bottomFrame) , Upper(upper), Top(top), OsdX0(x0), OsdY0(y0) { osd=NULL; Background = clrBackground; // Redirect all real init work to method InitOSD(); } void cDisplay32BPPHalf::InitOSD() { delete osd; int x0 = OsdX0; int height = Height / 2; // half heigth int vLines = TT_DISPLAY_LINES; if ((height % vLines) > 0) height = (height / vLines) * vLines; // alignment int y0 = OsdY0; if (!Top) y0 += Height - height; // calculate y-offset osd = cOsdProvider::NewOsd(x0, y0); if (!osd) return; int width=(Width+1)&~1; // Width has to end on byte boundary, so round up int bpp = 32; if (ttSetup.colorMode4bpp == true) { bpp = 4; dsyslog("osdteletext: OSD config forced to bpp=%d", bpp); }; tArea Areas[] = { { 0, 0, width - 1 + leftFrame + rightFrame, height - 1 + topFrame + bottomFrame, bpp } }; if (bpp == 32 && (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) != oeOk)) { bpp = 8; Areas[0].bpp = 8; DEBUG_OT_AREA("osdteletext: OSD is not providing TrueColor, fallback to bpp=%d", bpp); } if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) != oeOk) { DELETENULL(osd); esyslog("osdteletext: can't create requested OSD 'half' area with x0=%d y0=%d width=%d height=%d bpp=%d", x0, y0, width, height, bpp); Skins.Message(mtError, "OSD-Teletext can't request OSD 'half' area, check plugin settings"); return; } /* // Try full-size area first while (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) != oeOk) { // Out of memory, so shrink if (Upper) { // Move up lower border Areas[0].y2=Areas[0].y2-1; } else { // Move down upper border Areas[0].y1=Areas[0].y1+1; } if (Areas[0].y1>Areas[0].y2) { // Area is empty, fail miserably DELETENULL(osd); return; } } // Add some backup // CanHandleAreas is not accurate enough if (Upper) { Areas[0].y2=Areas[0].y2-10; } else { Areas[0].y1=Areas[0].y1+10; } */ osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); isyslog("osdteletext: OSD 'half' area successful requested x0=%d y0=%d width=%d height=%d bpp=%d lF=%d rF=%d tF=%d bF=%d Upper=%s Top=%s" , x0, y0, width, height, bpp , leftFrame, rightFrame, topFrame, bottomFrame , (Upper == true) ? "yes" : "no" , (Top == true) ? "yes" : "no" ); setOutputWidth(width); setOutputHeight(height); setLeftFrame(leftFrame); setRightFrame(rightFrame); setTopFrame(topFrame); setBottomFrame(bottomFrame); InitScaler(); // In case we switched on the fly, do a full redraw CleanDisplay(); Dirty=true; DirtyAll=true; Flush(); } // vim: ts=4 sw=4 et vdr-plugin-osdteletext-2.3.1/display.h000066400000000000000000000175561415701714300200050ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) 2005 by Udo Richter * * Copyright (c) 2021 by Peter Bieringer (extenions) * * * * display.h - Actual implementation of OSD display variants and * * Display:: namespace that encapsulates a single cDisplay. * * * * 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 OSDTELETEXT_DISPLAY_H_ #define OSDTELETEXT_DISPLAY_H_ #include "displaybase.h" #include namespace Display { // The Display:: namespace mainly encapsulates a cDisplay *display variable // and allows NULL-safe access to display members. // Additionally, selects via mode the actually used instance for *display. enum Mode { Full, HalfUpper, HalfLower, HalfUpperTop, HalfLowerTop }; // Full mode: 2BPP or 4BPP full screen display, depending on memory constrains // HalfUpper: 4BPP display of upper half, drop lower half if out of memory // HalfLower: 4BPP display of lower half, drop upper half if out of memory // *Top: display top of screen (default: bottom) extern Mode mode; extern cDisplay *display; // Access to display mode: void SetMode(Display::Mode mode, tColor clrBackground = TTSETUPPRESET_TCOLOR(BackTrans)); inline void Delete() { if (display) { DELETENULL(display); } } void ShowUpperHalf(); // Make sure the upper half of screen is visible // eg. for entering numbers etc. // Wrapper calls for various *display members: inline bool GetBlink() { if (display) return display->GetBlink(); else return false; } inline bool SetBlink(bool blink) { if (display) return display->SetBlink(blink); else return false; } inline bool GetConceal() { if (display) return display->GetConceal(); else return false; } inline bool SetConceal(bool conceal) { if (display) return display->SetConceal(conceal); else return false; } inline bool GetPaused() { if (display) return display->GetPaused(); else return false; } inline void SetPaused(bool paused) { if (display) return display->SetPaused(paused); else return; } inline bool HasConceal() { if (display) return display->HasConceal(); else return false; } inline cDisplay::enumZoom GetZoom() { if (display) return display->GetZoom(); else return cDisplay::Zoom_Off; } inline void SetZoom(cDisplay::enumZoom zoom) { if (display) display->SetZoom(zoom); } inline void SetBackgroundColor(tColor c) { if (display) display->SetBackgroundColor(c); } inline tColor GetBackgroundColor() { if (display) return display->GetBackgroundColor(); else return 0; } inline void HoldFlush() { if (display) display->HoldFlush(); } inline void ReleaseFlush() { if (display) display->ReleaseFlush(); } inline void RenderTeletextCode(unsigned char *PageCode) { if (display) display->RenderTeletextCode(PageCode); } inline void DrawClock() { if (display) display->DrawClock(); } inline void DrawPageId(const char *text) { if (display) display->DrawPageId(text); } inline void DrawPageId(const char *text, const enumTeletextColor cText) { if (display) display->DrawPageId(text, cText); } inline void DrawPageId(const char *text, const enumTeletextColor cText, const bool boxedAlwaysOn) { if (display) display->DrawPageId(text, cText, boxedAlwaysOn); } inline void DrawHotkey(const char *textRed, const char *textGreen, const char* textYellow, const char *textBlue, const HotkeyFlag flag) { if (display) display->DrawHotkey(textRed, textGreen, textYellow, textBlue, flag); } inline void DrawInfo(const char *textI1, const char *textI2, const char* textI3, const char *textI4, const char *textI5, const InfoLineFlag flag) { if (display) display->DrawInfo(textI1, textI2, textI3, textI4, textI5, flag); } inline void DrawMessage(const char *txt) { if (display) display->DrawMessage(txt, NULL); } inline void DrawMessage(const char *txt, const char *txt2) { if (display) display->DrawMessage(txt, txt2); } inline void DrawMessage(const char *txt, const enumTeletextColor cFrame) { if (display) display->DrawMessage(txt, NULL, NULL, NULL, 0, 0, cFrame); } inline void DrawMessage(const char *txt, const char *txt2, const enumTeletextColor cFrame) { if (display) display->DrawMessage(txt, txt2, NULL, NULL, 0, 0, cFrame); } inline void DrawMessage(const char *txt, const char *txt2, const cString *txtArray, const int txtArrayEntries, const int txtArrayColumns, const enumTeletextColor cFrame) { if (display) display->DrawMessage(txt, txt2, txtArray, NULL, txtArrayEntries, txtArrayColumns, cFrame); } inline void DrawMessage(const char *txt, const char *txt2, const cString *txtArray, const enumTeletextColor *ctxtArray, const int txtArrayEntries, const int txtArrayColumns, const enumTeletextColor cFrame) { if (display) display->DrawMessage(txt, txt2, txtArray, ctxtArray, txtArrayEntries, txtArrayColumns, cFrame); } inline void DrawMessage(const char *txt, const enumTeletextColor cFrame, const enumTeletextColor cText) { if (display) display->DrawMessage(txt, NULL, NULL, NULL, 0, 0, cFrame, cText); } inline void DrawMessage(const char *txt, const char *txt2, const enumTeletextColor cFrame, const enumTeletextColor cText) { if (display) display->DrawMessage(txt, txt2, NULL, NULL, 0, 0, cFrame, cText); } inline void DrawMessage(const char *txt, const enumTeletextColor cFrame, const enumTeletextColor cText, const enumTeletextColor cBackground) { if (display) display->DrawMessage(txt, NULL, NULL, NULL, 0, 0, cFrame, cText, cBackground); } inline void DrawMessage(const char *txt, const char *txt2, const enumTeletextColor cFrame, const enumTeletextColor cText, const enumTeletextColor cBackground) { if (display) display->DrawMessage(txt, txt2, NULL, NULL, 0, 0, cFrame, cText, cBackground); } inline void ClearMessage() { if (display) display->ClearMessage(); } inline void ClearPage() { if (display) display->ClearPage(); } } class cDisplay32BPP : public cDisplay { // True Color OSD display // No need for color mapping // Uses cPixmap instead of cBitmap public: cDisplay32BPP(int x0, int y0, int width, int height, int leftFrame, int rightFrame, int topFrame, int bottomFrame, tColor clrBackground); }; class cDisplay32BPPHalf : public cDisplay { int leftFrame, rightFrame, topFrame, bottomFrame; // frame border // 32BPP (true color) OSD display with auto size reduction on memory constrains // Automatically tries to make visible area as big as possible // No need for color mapping bool Upper; // Prefer to show upper half or lower half? bool Top; // Prefer to show half on top or bottom? int OsdX0,OsdY0; // Needed to re-initialize osd public: cDisplay32BPPHalf(int x0, int y0, int width, int height, int leftFrame, int rightFrame, int topFrame, int bottomFrame, bool upper, bool top, tColor clrBackground); bool GetUpper() { return Upper; } void SetUpper(bool upper) { if (Upper!=upper) { Upper=upper; } } void SetTop(bool top) { if (Top!=top) { Top=top; } } protected: void InitOSD(); }; #endif vdr-plugin-osdteletext-2.3.1/displaybase.c000066400000000000000000001212331415701714300206170ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) 2005 by Udo Richter * * Copyright (c) 2021 by Peter Bieringer (extenions) * * * * displaybase.c - Base class for rendering a teletext cRenderPage to * * an actual VDR OSD. * * * * 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 #include #include #include "displaybase.h" #include "txtfont.h" #include #include "logging.h" std::string cDisplay::TXTFontFootprint = ""; int cDisplay::realFontWidths[5] = {0}; int cDisplay::realFontHeights[5] = {0}; cDisplay::cDisplay(int width, int height) : Zoom(Zoom_Off), Concealed(true), Blinked(false), FlushLock(0), Boxed(false), Width(width), Height(height), Background(clrGray50), Paused(false), PageIdDisplayedEver(false), osd(NULL), outputWidth(0), outputHeight(0), leftFrame(0), rightFrame(0), topFrame(0), bottomFrame(0), MessageFont(NULL), MessageBorder(0), MessageX(0), MessageY(0), MessageW(0), MessageH(0), TXTFont(NULL), TXTDblWFont(NULL), TXTDblHFont(NULL), TXTDblHWFont(NULL), TXTHlfHFont(NULL) { } cDisplay::~cDisplay() { DELETENULL(osd); DELETENULL(TXTFont); DELETENULL(TXTDblWFont); DELETENULL(TXTDblHFont); DELETENULL(TXTDblHWFont); DELETENULL(TXTHlfHFont); DELETENULL(MessageFont); } // This is an improved detection mechanism (still ugly hack, any ideas on how to get font size with characters (glyphs) of specified width/height?) // TODO: shrinking in case of italic fonts cFont *cDisplay::GetFont(const char *name, int fontIndex, int height, int width) { const int heightOrig = height; const int widthOrig = width; DEBUG_OT_FONT("called with font %s index %d with requested w=%3d h=%3d", name, fontIndex, widthOrig, heightOrig); cFont *font = cFont::CreateFont(name, height, width); if (font != NULL) { int realWidth = font->Width('W'); int realHeight = font->Height(); DEBUG_OT_FONT("INITIAL fontWidth =%3d -> realWidth =%3d requestedWidth =%3d", width, realWidth, widthOrig); if (realWidth > 0) { for (int i = (width * width) / realWidth; i < width * 4; i++) { DELETENULL(font); font = cFont::CreateFont(name, heightOrig, i); if (font != NULL) { realWidth = font->Width('W'); DEBUG_OT_FONT("TEST result fontWidth =%3d -> realWidth =%3d %s requestedWidth =%3d" , i, realWidth , (realWidth > widthOrig) ? "> " : "<=" , widthOrig); if (realWidth > widthOrig) { // too large, select last one and finish width = i - 1; realFontWidths[fontIndex] = width; // store in cache break; } } } } else { esyslog("osdteletext: font %s returned realWidth of 0 (should not happen, please try a different font)", name); } DEBUG_OT_FONT("INITIAL fontHeight=%3d -> realHeight=%3d requestedHeight=%3d", height, realHeight, heightOrig); if (realHeight > 0) { for (int i = height * height / realHeight; i < height * 4; i++) { DELETENULL(font); font = cFont::CreateFont(name, i, widthOrig); if (font != NULL) { realHeight = font->Height(); DEBUG_OT_FONT("TEST result fontHeight=%3d -> realHeight=%3d %s requestedHeight=%3d" , i, realHeight , (realHeight > heightOrig) ? "> " : "<=" , heightOrig); if (realHeight > heightOrig) { // too large, select last one and finish height = i - 1; realFontHeights[fontIndex] = height; // store in cache break; } } } } else { esyslog("osdteletext: font %s returned realHeight of 0 (should not happen, please try a different font)", name); } } DELETENULL(font); font = cFont::CreateFont(name, height, width); // recreate with final height and width from above DEBUG_OT_FONT("font %s index %d with requested w=%3d h=%3d => probed size w=%3d h=%3d", name, fontIndex, widthOrig, heightOrig, width, height); return font; } std::string cDisplay::GetFontFootprint(const char *name) { return std::string(cString::sprintf("%s_%d_%d_%d", name, fontWidth, fontHeight, Zoom)); } void cDisplay::InitScaler() { // Set up the scaling factors. Also do zoom mode by // scaling differently. fontWidth = (outputWidth * 2 / 40) & 0xfffe; if (Zoom == Zoom_Off) { fontHeight = (outputHeight * 2 / TT_DISPLAY_LINES) & 0xfffe; } else { fontHeight = (outputHeight * 2 * 2 / TT_DISPLAY_LINES) & 0xfffe; } // use even font size for double sized characters (prevents rounding errors during character display) fontWidth &= 0xfffe; fontHeight &= 0xfffe; DEBUG_OT_SCALER("osdteletext: InitScaler width=%d height=%d fontWidth*2=%d fontHeight=%d lineMode24=%d Zoom=%d", outputWidth, outputHeight, fontWidth, fontHeight, ttSetup.lineMode24, Zoom); int txtFontWidth = fontWidth; int txtFontHeight = fontHeight; const char *txtFontName = TTSETUPPRESET_FONTNAME(Font); std::string footprint = GetFontFootprint(txtFontName); if (footprint.compare(TXTFontFootprint) == 0) { // cached DEBUG_OT_FONT("call cFont::CreateFont for: %s", txtFontName); TXTFont = cFont::CreateFont(txtFontName, realFontHeights[0], realFontWidths[0]); TXTDblWFont = cFont::CreateFont(txtFontName, realFontHeights[1], realFontWidths[1]); TXTDblHFont = cFont::CreateFont(txtFontName, realFontHeights[2], realFontWidths[2]); TXTDblHWFont = cFont::CreateFont(txtFontName, realFontHeights[3], realFontWidths[3]); TXTHlfHFont = cFont::CreateFont(txtFontName, realFontHeights[4], realFontWidths[4]); } else { TXTFontFootprint = footprint; DEBUG_OT_FONT("call GetFont for: %s", txtFontName); TXTFont = GetFont(txtFontName, 0, txtFontHeight / 2, txtFontWidth / 2); TXTDblWFont = GetFont(txtFontName, 1, txtFontHeight / 2, txtFontWidth); TXTDblHFont = GetFont(txtFontName, 2, txtFontHeight, txtFontWidth / 2); TXTDblHWFont = GetFont(txtFontName, 3, txtFontHeight, txtFontWidth); TXTHlfHFont = GetFont(txtFontName, 4, txtFontHeight / 4, txtFontWidth / 2); } // calculate scaled Height depending of outputHeight int MessageFontHeight = ceil((float) (Setup.FontOsdSize * outputHeight) / (float) cOsd::OsdHeight()); DEBUG_OT_FONT("create MessageFont with height based on Setup.FontOsdSize=%d outputHeight=%d cOsd::OsdHeight=%d -> MessageFontHeight=%d", Setup.FontOsdSize, outputHeight, cOsd::OsdHeight(), MessageFontHeight); MessageFont = cFont::CreateFont(Setup.FontOsd, MessageFontHeight); // scale border depending on width, base: 720 -> 6 MessageBorder = ceil((float) (6 * outputWidth) / (float) 720); } bool cDisplay::SetBlink(bool blink) { DEBUG_OT_BLINK("called with blink=%d", blink); int x,y; bool Change=false; if (blink==Blinked) return false; // touch all blinking chars for (y=0;y<25;y++) { for (x=0;x<40;x++) { if (Page[x][y].GetBlink()) { Page[x][y].SetDirty(true); Change=true; } } } Blinked=blink; if (Change) Dirty=true; Flush(); return Change; } bool cDisplay::SetConceal(bool conceal) { int x,y; bool Change=false; if (conceal==Concealed) return false; // touch all concealed chars for (y=0;y<25;y++) { for (x=0;x<40;x++) { if (Page[x][y].GetConceal()) { Page[x][y].SetDirty(true); Change=true; } } } Concealed=conceal; if (Change) Dirty=true; Flush(); return Change; } bool cDisplay::HasConceal() { int x,y; bool HasConceal=false; // check all concealed chars for (y=0;y<25;y++) { for (x=0;x<40;x++) { if (Page[x][y].GetConceal()) { HasConceal=true; } } } return HasConceal; } void cDisplay::SetZoom(enumZoom zoom) { DEBUG_OT_DBFC("called: zoom=%d", zoom); if (!osd) return; if (Zoom==zoom) return; Zoom=zoom; // Re-initialize scaler to let zoom take effect InitScaler(); Dirty=true; DirtyAll=true; Flush(); } void cDisplay::SetBackgroundColor(tColor c) { DEBUG_OT_DBFC("called: tColor=0x%08x", c); Background=c; CleanDisplay(); Flush(); } void cDisplay::CleanDisplay() { tColor bgc; if (!osd) return; if (Boxed) bgc = GetColorRGB(ttcTransparent,0); else if (m_debugmask & DEBUG_MASK_OT_ACT_OSD_BACK_RED) bgc = GetColorRGB(ttcRed,0); else bgc = Background; DEBUG_OT_RENCLN("called: outputWidth=%d outputHeight=%d boxed=%s color=0x%08x", outputWidth, outputHeight, BOOLTOTEXT(Boxed), bgc); osd->DrawRectangle(0, 0, outputWidth - 1 + leftFrame + rightFrame, outputHeight - 1 + topFrame + bottomFrame, bgc); // repaint all Dirty=true; DirtyAll=true; } // AARRGGBB #define COLOR_HALF(clr) ((clr & 0xff000000) | ((clr & 0x00fe0000) >> 1) | ((clr & 0x0000fe00) >> 1) | ((clr & 0x000000fe) >> 1)) tColor cDisplay::GetColorRGB(enumTeletextColor ttc, int Area) { switch (ttc) { case ttcBlack: return Background; case ttcRed: return clrRed; case ttcGreen: return clrGreen; case ttcYellow: return clrYellow; case ttcBlue: return clrBlue; case ttcMagenta: return clrMagenta; case ttcCyan: return clrCyan; case ttcWhite: return clrWhite; case ttcTransparent: return clrTransparent; case ttcHalfRed: return COLOR_HALF(clrRed); case ttcHalfGreen: return COLOR_HALF(clrGreen); case ttcHalfYellow: return COLOR_HALF(clrYellow); case ttcHalfBlue: return COLOR_HALF(clrBlue); case ttcHalfMagenta: return COLOR_HALF(clrMagenta); case ttcHalfCyan: return COLOR_HALF(clrCyan); case ttcGrey: return COLOR_HALF(clrWhite); // 16-31 according to ETSI EN 300 706 V1.2.1 (2003-012.4) 12.4 case ttcColor16: return 0xFFFC005C; case ttcColor17: return 0xFFFC7C00; case ttcColor18: return 0xFF00FC7C; case ttcColor19: return 0xFFFCFCBC; case ttcColor20: return 0xFFFCFCBC; case ttcColor21: return 0xFF00CCAC; case ttcColor22: return 0xFF5C0000; case ttcColor23: return 0xFF6C5C2C; case ttcColor24: return 0xFFCC7C7C; case ttcColor25: return 0xFF3C3C3C; // grey25 case ttcColor26: return 0xFFFC7C7C; case ttcColor27: return 0xFF7CFC7C; case ttcColor28: return 0xFFFCFC7C; case ttcColor29: return 0xFF7C7CFC; case ttcColor30: return 0xFF7CFCFC; case ttcColor31: return 0xFFDCDCDC; // grey75 default: return Background; } } tColor cDisplay::GetColorRGBAlternate(enumTeletextColor ttc, int Area) { // TODO implement ?? return GetColorRGB(ttc,Area); } void cDisplay::RenderTeletextCode(unsigned char *PageCode) { // Interprete teletext code referenced by PageCode // and draw the whole page content into OSD. // PageCode must be a buffer containing TelePageData structure (see storage.h) HoldFlush(); cRenderPage::ReadTeletextHeader(PageCode); DEBUG_OT_RENCLN("called with Boxed=%s Flags=0x%02x", BOOLTOTEXT(Boxed), Flags); if (!Boxed && (Flags&0x60)!=0) { DEBUG_OT_RENCLN("Toggle Boxed: false->true"); Boxed=true; CleanDisplay(); } else if (Boxed && (Flags&0x60)==0) { DEBUG_OT_RENCLN("Toggle Boxed: true->false"); Boxed=false; CleanDisplay(); } if (memcmp(PageCode, "VTXV5", 5) != 0) { esyslog("osdteletext: cDisplay::RenderTeletextCode called with PageCode which is not starting with 'VTXV5' (not supported)"); return; }; cRenderPage::RenderTeletextCode(PageCode+12); ReleaseFlush(); } void cDisplay::DrawDisplay() { DEBUG_OT_DD("called with Blinked=%d Concealed=%d Dirty=%s DirtyAll=%s IsDirty()=%s", Blinked, Concealed, BOOLTOTEXT(Dirty), BOOLTOTEXT(DirtyAll), BOOLTOTEXT(IsDirty())); int x,y; if (!IsDirty()) return; // nothing to do for (y = 0; y < TT_DISPLAY_LINES; y++) { for (x=0;x<40;x++) { if (IsDirty(x,y)) { // Need to draw char to osd cTeletextChar c=Page[x][y]; c.SetDirty(false); if ((Blinked && c.GetBlink()) || (Concealed && c.GetConceal())) { DEBUG_OT_BLINK("blink by replacing char %08x with ' ' on x=%d y=%d", c.GetC(), x, y); c.SetChar(0x20); c.SetCharset(CHARSET_LATIN_G0_DE); } DrawChar(x,y,c); } } } Dirty=false; DirtyAll=false; } inline bool IsPureChar(unsigned int *bitmap) { // Check if character is pure foreground or // pure background color int i; if (bitmap[0]==0x0000) { for (i=1;i<10;i++) { if (bitmap[i]!=0x0000) return false; } } else if (bitmap[0]==0xfff0) { for (i=1;i<10;i++) { if (bitmap[i]!=0xfff0) return false; } } else { return false; } return true; } void cDisplay::DrawChar(int x, int y, cTeletextChar c) { // Get colors enumTeletextColor ttfg=c.GetFGColor(); enumTeletextColor ttbg=c.GetBGColor(); static int cache_txtVoffset = 0; static int cache_outputHeight = 0; static int cache_OsdHeight = 0; static int cache_Vshift = 0; static int cache_valid = 0; if (!osd) return; if (Boxed && c.GetBoxedOut()) { ttbg=ttcTransparent; ttfg=ttcTransparent; } tColor fg=GetColorRGB(ttfg, 0); tColor bg=GetColorRGB(ttbg, 0); char buf[5]; uint t = GetVTXChar(c); int tl = Utf8CharSet(t, buf); buf[tl] = 0; const cFont *font = TXTFont; // FIXED: -Wmaybe-uninitialized int charset = c.GetCharset(); int fontType = 0; int w = fontWidth / 2; int h = fontHeight / 2; if (c.GetDblWidth() != dblw_Normal) { fontType |= 1; w = fontWidth; } if (c.GetDblHeight() != dblh_Normal) { fontType |= 2; h = fontHeight; } bool isGraphicsChar; if (charset == CHARSET_GRAPHICS_G1 || charset == CHARSET_GRAPHICS_G1_SEP) { isGraphicsChar = true; } else { if (c.GetChar() == 0x7f) // filled rectangle isGraphicsChar = true; else isGraphicsChar = false; switch(fontType) { case 0: font = TXTFont; break; case 1: font = TXTDblWFont; break; case 2: font = TXTDblHFont; break; case 3: font = TXTDblHWFont; break; } } bool h_scale_div2 = false; int lines_div2 = 0; if (Zoom == Zoom_Lower) { y -= 12; if (y < 0 || y > 11) { if ((ttSetup.lineMode24 != HintLinesNone) && (y >= 12)) { // display special line >= 25 in half height h /= 2; h_scale_div2 = true; font = TXTHlfHFont; lines_div2 = y - 12; } else { // display only line 12-23 (12 lines) return; }; }; }; if (Zoom == Zoom_Upper) { if (y > 11) { if ((ttSetup.lineMode24 != HintLinesNone) && (y >= 24)) { // display special line >= 25 in half height y -= 12; h /= 2; h_scale_div2 = true; font = TXTHlfHFont; lines_div2 = y - 12; } else { // display only line 0-11 (12 lines) return; }; }; }; if ((m_debugmask & DEBUG_MASK_OT_ACT_LIMIT_LINES) && (y > 8)) return; int vx = x * fontWidth / 2; int vy = y * fontHeight / 2 - lines_div2 * h; bool drawChar = true; if (c.GetDblWidth() == dblw_Right) { drawChar = false; } if (c.GetDblHeight() == dblh_Bottom) { drawChar = false; } if (drawChar) { if (isGraphicsChar) { unsigned int buffer[10]; unsigned int *charmap; // Get character face: charmap=GetFontChar(c,buffer); if (!charmap) { // invalid - clear buffer bzero(&buffer,sizeof buffer); charmap=buffer; } cBitmap charBm(w, h, 24); if (m_debugmask & DEBUG_MASK_OT_ACT_CHAR_BACK_BLUE) charBm.DrawRectangle(0, 0, w - 1, h - 1, GetColorRGB(ttcBlue,0)); else charBm.DrawRectangle(0, 0, w - 1, h - 1, bg); // draw scaled graphics char int virtY = 0; while (virtY<=h) { int bitline; bitline=charmap[virtY * 10 / h / ((h_scale_div2 == true) ? 2 : 1)]; int virtX=0; while (virtX < w) { int bit=(virtX * 12 / w); if (bitline&(0x8000>>bit)) { charBm.DrawPixel(virtX,virtY,fg); // } else { // charBm.DrawPixel(virtX,virtY,bg); } virtX++; } virtY++; } osd->DrawBitmap(vx + leftFrame, vy + topFrame, charBm); } else { cBitmap charBm(w, h, 24); if (m_debugmask & DEBUG_MASK_OT_ACT_CHAR_BACK_BLUE) charBm.DrawRectangle(0, 0, w - 1, h - 1, GetColorRGB(ttcBlue,0)); else charBm.DrawRectangle(0, 0, w - 1, h - 1, bg); // charBm.DrawText(0, 0, buf, fg, bg, font); if ( (cache_valid == 0) || ( (cache_txtVoffset != TTSETUPPRESET(Voffset)) || (cache_outputHeight != outputHeight ) || (cache_OsdHeight != cOsd::OsdHeight() ) ) ) { cache_valid = 1; cache_txtVoffset = TTSETUPPRESET(Voffset); cache_outputHeight = outputHeight; cache_OsdHeight = cOsd::OsdHeight(); cache_Vshift = (cache_txtVoffset * cache_outputHeight) / cache_OsdHeight; DEBUG_OT_DTXT("osdteletext: DrawText vertical shift cache updated: txtVoffset=%d outputHeight=%d OsdHeight=%d => Vshift=%d", cache_txtVoffset, cache_outputHeight, cache_OsdHeight, cache_Vshift); }; if ((m_debugline >= 0) && (y == m_debugline)) { DEBUG_OT_DCHR("y=%2d x=%2d vy=%4d vx=%4d w=%d h=%d cache_Vshift=%d ttfg=%d fg=0x%08x ttbg=%d bg=0x%08x BoxedOut=%d text charset=0x%04x char='%s'", y, x, vy, vx, w, h, cache_Vshift, ttfg, fg, ttbg, bg, c.GetBoxedOut(), charset, buf); }; charBm.DrawText(0, cache_Vshift, buf, fg, 0, font, 0, 0); if (m_debugmask & DEBUG_MASK_OT_DCHR) { // draw a bunch of markers into bitmap tColor color = GetColorRGB(ttcRed,0); if(((x % 2 != 0) && ((y % 2) == 0)) || ((x % 2 == 0) && ((y % 2) != 0))) color = GetColorRGB(ttcBlue,0); for (int i = 0; i < w; i++) { charBm.DrawPixel(i , 0 , color); // horizontal top charBm.DrawPixel(i , h - 1, color); // horizontal bottom if ((h > 2) && ((i % 5) == 0)) { // mark at 5 charBm.DrawPixel(i , 0 + 1, color); // horizontal top charBm.DrawPixel(i , h - 2, color); // horizontal bottom }; if ((h > 4) && ((i % 10) == 0)) { // mark at 10 charBm.DrawPixel(i , 0 + 2, color); // horizontal top charBm.DrawPixel(i , 0 + 3, color); // horizontal top charBm.DrawPixel(i , h - 2, color); // horizontal bottom charBm.DrawPixel(i , h - 3, color); // horizontal bottom }; }; for (int i = 0; i < h; i++) { charBm.DrawPixel(0 , i, color); // vertical left charBm.DrawPixel(w - 1 , i, color); // vertical right if ((w > 2) && ((i % 5) == 0)) { // mark at 5 charBm.DrawPixel(0 + 1 , i, color); // vertical left charBm.DrawPixel(w - 1 , i, color); // vertical right }; if ((w > 4) && ((i % 10) == 0)) { // mark at 10 charBm.DrawPixel(0 + 2 , i, color); // vertical left charBm.DrawPixel(0 + 3 , i, color); // vertical left charBm.DrawPixel(w - 2 , i, color); // vertical right charBm.DrawPixel(w - 3 , i, color); // vertical right }; }; }; osd->DrawBitmap(vx + leftFrame, vy + topFrame, charBm); } } } uint8_t UTF8toTeletextChar(const uint8_t c1, const uint8_t c2, enumCharsets *TeletextCharset) { // Convert UTF char into TeletextChar and set related TeletextCharset uint8_t TeletextChar = '?'; // default "unknown" *TeletextCharset = CHARSET_LATIN_G0; // default switch (c1) { case 0xc3: switch (c2) { // CHARSET_LATIN_G0_DE case 0x84: // LATIN CAPITAL LETTER A WITH DIAERESIS TeletextChar = 0x5b; *TeletextCharset = CHARSET_LATIN_G0_DE; break; case 0x96: // LATIN CAPITAL LETTER O WITH DIAERESIS TeletextChar = 0x5c; *TeletextCharset = CHARSET_LATIN_G0_DE; break; case 0x9c: // LATIN CAPITAL LETTER U WITH DIAERESIS TeletextChar = 0x7d; *TeletextCharset = CHARSET_LATIN_G0_DE; break; case 0xa4: // LATIN SMALL LETTER A WITH DIAERESIS TeletextChar = 0x7b; *TeletextCharset = CHARSET_LATIN_G0_DE; break; case 0xb6: // LATIN SMALL LETTER O WITH DIAERESIS TeletextChar = 0x7c; *TeletextCharset = CHARSET_LATIN_G0_DE; break; case 0xbc: // LATIN SMALL LETTER U WITH DIAERESIS TeletextChar = 0x7d; *TeletextCharset = CHARSET_LATIN_G0_DE; break; case 0x9f: // LATIN SMALL LETTER SHARP S TeletextChar = 0x7e; *TeletextCharset = CHARSET_LATIN_G0_DE; break; } // TODO: implement other required mapping } return (TeletextChar); } void cDisplay::DrawTextExtended(const int x, const int y, const char *text, const int len, const enumAlignment alignment, const enumTeletextColor ttcFg, enumTeletextColor const ttcBg) { // Copy text to teletext page with alignment and foreground/background color int len_text_utf8 = Utf8StrLen(text); int len_text = strlen(text); DEBUG_OT_DTXT("called with x=%d y=%d len=%d alignment=%d ttcFg=%d ttcBg=%d text='%s' strlen(text)=%d utf8len(text)=%d", x, y, len, alignment, ttcFg, ttcBg, text, len_text, len_text_utf8); int fill_left = 0; if (len_text_utf8 < len) { if (alignment == AlignmentRight) { fill_left = len - len_text_utf8; } else if (alignment == AlignmentCenter) { fill_left = (len - len_text_utf8) / 2; }; }; cTeletextChar c; c.SetFGColor(ttcFg); c.SetBGColor(ttcBg); int j = 0; for (int i = 0; i < len; i++) { if (i < fill_left) { // fill left with space c.SetChar(' '); } else if (i > fill_left + len_text_utf8) { // fill right with space c.SetChar(' '); } else { c.SetCharset(CHARSET_LATIN_G0); // default uint8_t c1 = text[j]; if (j +1 < len_text) { // check for UTF-8 if ((text[j + 1] & 0xC0) == 0x80) { // unicode uint8_t c2 = text[j + 1]; enumCharsets Charset; uint8_t Char = UTF8toTeletextChar(c1, c2, &Charset); DEBUG_OT_DTXT("unicode mapped i=%d c1=%x c2=%x -> c=%02x cs=%04x", i, c1, c2, Char, Charset); c.SetCharset(Charset); c1 = Char; j++; } }; c.SetChar(c1); j++; }; SetChar(x+i, y, c); }; Flush(); }; void cDisplay::DrawText(int x, int y, const char *text, int len, const enumTeletextColor cText) { // Copy text to teletext page DEBUG_OT_DTXT("called with x=%d y=%d len=%d text='%s' strlen(text)=%d", x, y, len, text, (int) strlen(text)); cTeletextChar c; c.SetFGColor(cText); // default ttcWhite c.SetBGColor(ttcBlack); c.SetCharset(CHARSET_LATIN_G0); // Copy chars up to len or null char while (len>0 && *text!=0x00) { c.SetChar(*text); SetChar(x,y,c); text++; x++; len--; } // Fill remaining chars with spaces c.SetChar(' '); while (len>0) { SetChar(x,y,c); x++; len--; } // .. and display Flush(); } void cDisplay::ClearPage(void) { // Clear Teletext Page on OSD cTeletextChar c; c.SetFGColor(ttcTransparent); // no char c.SetBGColor(ttcBlack); // pass selected background c.SetChar(' '); // reset 40x24 area with space for (int y = 0; y < 24; y++) for (int x = 0; x < 40; x++) SetChar(x, y, c); return; }; void cDisplay::DrawPageId(const char *text, const enumTeletextColor cText, const bool boxedAlwaysOn) { // Draw Page ID string to OSD // In case of "Boxed" page: only until 1st page update unless "boxedAlwaysOn" is set // "boxedAlwaysOn" also unhides the 1st line completly static char text_last[9] = ""; // remember static bool paused_last = false; cTeletextChar c; DEBUG_OT_DRPI("called with text='%s' text_last='%s' Boxed=%d HasConceal=%d GetConceal=%d boxedAlwaysOn=%s", text, text_last, Boxed, HasConceal(), GetConceal(), BOOLTOTEXT(boxedAlwaysOn)); if ((! GetPaused()) && Boxed && (! boxedAlwaysOn) && PageIdDisplayedEver && (strcmp(text, text_last) == 0)) { // don't draw PageId a 2nd time on boxed pages for (int i = 0; i < 8; i++) { c.SetFGColor(ttcTransparent); c.SetBGColor(ttcTransparent); c.SetChar(0); SetChar(i,0,c); }; return; }; if (Boxed && boxedAlwaysOn) { for (int x = 8; x < 40; x++) { // de-boxing of 1st line in case OSD is not matching live channel c = GetChar(x, 0); c.SetBoxedOut(false); SetChar(x, 0, c); }; }; DrawText(0,0,text,8, cText); strncpy(text_last, text, sizeof(text_last) - 1); PageIdDisplayedEver = true; if (HasConceal()) { c.SetBGColor(ttcBlack); if (GetConceal()) { c.SetFGColor(ttcYellow); c.SetChar('?'); } else { c.SetFGColor(ttcGreen); c.SetChar('!'); }; DEBUG_OT_DRPI("trigger SetChar for Conceiled hint ttfg=%x ttbg=%x", c.GetFGColor(), c.GetBGColor()); SetChar(6, 0, c); }; if (GetPaused()) { paused_last = true; c.SetBGColor(ttcBlack); c.SetFGColor(ttcRed); c.SetChar('!'); DEBUG_OT_DRPI("trigger SetChar for Paused hint ttfg=%x ttbg=%x", c.GetFGColor(), c.GetBGColor()); SetChar(3, 0, c); } else if (paused_last == true) { paused_last = false; c.SetBGColor(ttcBlack); c.SetFGColor(ttcGreen); c.SetChar('>'); DEBUG_OT_DRPI("trigger SetChar for Paused finished hint ttfg=%x ttbg=%x", c.GetFGColor(), c.GetBGColor()); SetChar(3, 0, c); }; } void cDisplay::DrawHotkey(const char *textRed, const char *textGreen, const char* textYellow, const char *textBlue, const HotkeyFlag flag) { if (Boxed) return; // don't draw hotkey on boxed pages switch(flag) { case HotkeyNormal: DrawTextExtended( 0, 24, textRed , 10, AlignmentCenter, ttcWhite, ttcRed ); DrawTextExtended(10, 24, textGreen , 10, AlignmentCenter, ttcBlack, ttcGreen ); DrawTextExtended(20, 24, textYellow, 10, AlignmentCenter, ttcBlack, ttcYellow ); DrawTextExtended(30, 24, textBlue , 10, AlignmentCenter, ttcWhite, ttcBlue ); break; case HotkeyYellowValue: DrawTextExtended( 0, 24, textRed , 10, AlignmentCenter, ttcWhite, ttcRed ); DrawTextExtended(10, 24, textGreen , 10, AlignmentCenter, ttcBlack, ttcGreen ); DrawTextExtended(20, 24, textYellow, 10, AlignmentCenter, ttcWhite, ttcMagenta); DrawTextExtended(30, 24, textBlue , 10, AlignmentCenter, ttcWhite, ttcBlue ); break; case HotkeyGreenYellowValue: DrawTextExtended( 0, 24, textRed , 10, AlignmentCenter, ttcWhite, ttcRed ); DrawTextExtended(10, 24, textGreen , 20, AlignmentCenter, ttcWhite, ttcMagenta); DrawTextExtended(30, 24, textBlue , 10, AlignmentCenter, ttcWhite, ttcBlue ); break; }; } void cDisplay::DrawInfo(const char *textI1, const char *textI2, const char* textI3, const char *textI4, const char *textI5, const InfoLineFlag flag) { if (Boxed) return; // don't draw hints on boxed pages switch(flag) { case InfoLine1: DrawTextExtended( 0, 25, textI1, 8, AlignmentCenter, ttcHalfCyan, ttcGrey ); DrawTextExtended( 8, 25, textI2, 8, AlignmentCenter, ttcHalfCyan, ttcColor25); DrawTextExtended(16, 25, textI3, 8, AlignmentCenter, ttcHalfCyan, ttcGrey ); DrawTextExtended(24, 25, textI4, 8, AlignmentCenter, ttcHalfCyan, ttcColor25); DrawTextExtended(32, 25, textI5, 8, AlignmentCenter, ttcHalfCyan, ttcGrey ); break; case InfoLine2: DrawTextExtended( 0, 26, textI1, 8, AlignmentCenter, ttcColor25 , ttcGrey ); DrawTextExtended( 8, 26, textI2, 8, AlignmentCenter, ttcColor31 , ttcColor25); DrawTextExtended(16, 26, textI3, 8, AlignmentCenter, ttcColor25 , ttcGrey ); DrawTextExtended(24, 26, textI4, 8, AlignmentCenter, ttcColor31 , ttcColor25); DrawTextExtended(32, 26, textI5, 8, AlignmentCenter, ttcColor25 , ttcGrey ); break; }; } void cDisplay::DrawClock() { if (Boxed) return; // don't draw Clock in on boxed pages char text[9]; time_t t=time(0); struct tm loct; localtime_r(&t, &loct); sprintf(text, "%02d:%02d:%02d", loct.tm_hour, loct.tm_min, loct.tm_sec); DrawText(32,0,text,8); } void cDisplay::DrawMessage(const char *txt1, const char *txt2, const cString *txtArray, const enumTeletextColor *ctxtArray, const int txtArrayEntries, const int txtArrayColumns, const enumTeletextColor cFrame, const enumTeletextColor cText, const enumTeletextColor cBackground, const enumTeletextColor cTextArray) { if (!osd) return; int border = MessageBorder; HoldFlush(); // Hold flush until done ClearMessage(); // Make sure old message is gone if (IsDirty()) DrawDisplay(); // Make sure all characters are out, so we can draw on top // text w/h int w1 = MessageFont->Width(txt1); int h1 = MessageFont->Height(txt1); int w2 = 0; int h2 = 0; // remember for later int w1_orig = w1; int w2_orig = w2; // box w/h int w = w1; int h = h1; // text offset int o1 = 0; int o2 = 0; bool txtArrayActive = (txtArray != NULL) && (txtArrayEntries > 0) && (txtArrayColumns > 0); if (txt2 != NULL) { // 2nd line active w2 = MessageFont->Width(txt2); h2 = MessageFont->Height(txt2); h += h2 + border / 2; // increase height if (txtArrayActive) { // in case of txtArray mode, add gap between txt and txt2 h += border; }; if (w2 > w1) { // 2nd line is longer w = w2; o1 = (w2 - w1) / 2; } else if (w2 < w1) { // 1st line is longer o2 = (w1 - w2) / 2; }; } else { if (txtArrayActive) { // in case of txtArray mode, add gap between txt and txtArray h += border; }; }; int wa[3] = {0, 0, 0}; int ha[3] = {0, 0, 0}; int ca = (txtArrayColumns <= 3) ? txtArrayColumns : 3; // limit to maximum 3 int wal; int hal; int cl; if (txtArrayActive) { // clear offset, always have alignment=left o1 = 0; o2 = 0; // lines per column cl = ceil((float) txtArrayEntries / (float) ca); // calculate width and height per column int c = 0; for (int l = 0; l < txtArrayEntries; l++) { if (l >= (c + 1) * cl) { // next column c++; if (c >= ca) { // limit reached (should not happen) break; }; }; wal = MessageFont->Width(txtArray[l]); hal = MessageFont->Height(txtArray[l]); if (wal > wa[c]) wa[c] = wal; // increase maximum width of column ha[c] += hal + border / 2; // increase height }; // calculate maximum width/height int waMax = 0; int haMax = 0; for (c = 0; c < ca; c++) { // add width per column waMax += wa[c]; // find maximum height if (ha[c] > haMax) haMax = ha[c]; }; // add column gap (2*border) waMax += (ca - 1) * border * 2; // check for maximum width of message box if (waMax > w) { w = waMax; }; // add maximum height h += haMax; }; w += 4 * border; h += 4 * border; // limit to maximum if (w > outputWidth) { w = outputWidth; if (txtArrayActive) { if (ca > 1) { // make all textArray columns equal size int wc = (w - (ca - 1) * border * 2 - 4 * border) / ca; for (int c = 0; c < ca; c++) wa[c] = wc; }; }; }; if (h > outputHeight) h = outputHeight; // center box int x = (outputWidth -w)/2 + leftFrame; int y = (outputHeight-h)/2 + topFrame; // Get local color mapping tColor fg = GetColorRGB(cText, 0); tColor bg = GetColorRGB(cBackground, 0); tColor fr = GetColorRGB(cFrame, 0); tColor fa = GetColorRGB(cTextArray, 0); if (cBackground == ttcBlack) { bg = clrBlack; // avoid transparent background on message boxes }; if (fg == bg) bg = GetColorRGBAlternate(cBackground,0); // Draw framed box (2 outer pixel always background) osd->DrawRectangle(x , y , x+w-1 , y+h-1 , bg); // outer rectangle osd->DrawRectangle(x+(border/2), y+(border/2), x+w-1-border/2, y+h-1-border/2, fr); // inner rectangle osd->DrawRectangle(x+border , y+border , x+w-1-border , y+h-1-border , bg); // background for text // Remember box MessageW = w; MessageH = h; MessageX = x; MessageY = y; // limit width if ((w - 4 * border) < w1) { w1 = w - 4 * border; wsyslog_ot("text too long for box, apply width limit (%d->%d) for txt1='%s'", w1_orig, w1, txt1); }; if (txt2 != NULL) { if ((w - 4 * border) < w2) { w2 = w - 4 * border; wsyslog_ot("text too long for box, apply width limit (%d->%d) for txt2='%s'", w2_orig, w2, txt2); }; }; // Draw text int xDraw = x + 2 * border; int yDraw = y + 2 * border; if (txt2 == NULL) { DEBUG_OT_MSG("MX=%d MY=%d MW=%d MH=%d OW=%d OH=%d w1=%d h1=%d txt1='%s'", MessageX, MessageY, MessageW, MessageH, outputWidth, outputHeight, w1, h1, txt1); osd->DrawText(xDraw + o1, yDraw, txt1, fg, bg, MessageFont, w1, h1); yDraw += h1 + border / 2; if (txtArrayActive) yDraw += border; // add gap } else { DEBUG_OT_MSG("MX=%d MY=%d MW=%d MH=%d OW=%d OH=%d w1=%d h1=%d w2=%d w2=%d txt1='%s' txt2='%s'", MessageX, MessageY, MessageW, MessageH, outputWidth, outputHeight, w1, h1, w2, h2, txt1, txt2); osd->DrawText(xDraw + o1, yDraw, txt1, fg, bg, MessageFont, w1, h1); yDraw += h1 + border / 2; if (txtArrayActive) yDraw += border; // add gap osd->DrawText(xDraw + o2, yDraw, txt2, (txtArrayActive) ? fa : fg, bg, MessageFont, w2, h2); // textArrayActive use related color yDraw += h2 + border / 2; }; // Draw text array in frame color if ((txtArray != NULL) && (txtArrayEntries > 0) && (txtArrayColumns > 0)) { DEBUG_OT_MSG("txtArray draw txtArrayEntries=%d txtArrayColumns=%d ca=%d cl=%d", txtArrayEntries, txtArrayColumns, ca, cl); int c = 0; int xa = 0; int ya = 0; for (int l = 0; l < txtArrayEntries; l++) { if (l >= (c + 1) * cl) { // next column xa += wa[c] + (2 * border); // add width of current column + 2*border ya = 0; // reset y c++; // increase counter if (c >= ca) { // limit reached (should not happen) break; }; }; wal = MessageFont->Width(txtArray[l]); hal = MessageFont->Height(txtArray[l]); if (wal > wa[c]) wal = wa[c]; // limit to column maximum if (ctxtArray != NULL) { fa = GetColorRGB(ctxtArray[l], 0); }; DEBUG_OT_MSG("txtArray l=%d c=%d xa=%d ya=%d, wal=%d hal=%d col=0x%08x txt='%s''", l, c, xa, ya, wal, hal, fa, *txtArray[l]); osd->DrawText(xDraw + o1 + xa, yDraw + ya, txtArray[l], fa, bg, MessageFont, wal, hal); ya += hal + border / 2; }; }; // And flush all changes ReleaseFlush(); } void cDisplay::ClearMessage() { if (!osd) return; if (MessageW==0 || MessageH==0) return; // NEW, reverse calculation based on how DrawChar // map to character x/y int x0 = (MessageX - leftFrame) / (fontWidth / 2); int y0 = (MessageY - topFrame ) / (fontHeight / 2); int x1 = (MessageX + MessageW - 1 - leftFrame) / (fontWidth / 2); int y1 = (MessageY + MessageH - 1 - topFrame ) / (fontHeight / 2); DEBUG_OT_MSG("MX=%d MY=%d MW=%d MH=%d => x0=%d/y0=%d x1=%d/y1=%d", MessageX, MessageY, MessageW, MessageH, x0, y0, x1, y1); #define TESTOORX(X) (X < 0 || X >= 40) #define TESTOORY(Y) (Y < 0 || Y >= 25) if ( TESTOORX(x0) || TESTOORX(x1) || TESTOORY(y0) || TESTOORY(y1) ) { // something out-of-range esyslog("osdteletext: %s out-of-range detected(crop) MessageX=%d MessageY=%d MessageW=%d MessageH=%d => x0=%d%s y0=%d%s x1=%d%s y1=%d%s", __FUNCTION__, MessageX, MessageY, MessageW, MessageH, x0, TESTOORX(x0) ? "!" : "", y0, TESTOORY(y0) ? "!" : "", x1, TESTOORX(x1) ? "!" : "", y1, TESTOORY(y1) ? "!" : "" ); // crop to limits if (x0 < 0) x0 = 0; if (x1 < 0) x1 = 0; if (y0 < 0) y0 = 0; if (y1 < 0) y1 = 0; if TESTOORX(x0) x0 = 40 - 1; if TESTOORX(x1) x1 = 40 - 1; if TESTOORY(y0) y0 = 25 - 1; if TESTOORY(y1) y1 = 25 - 1; } HoldFlush(); // DEBUG_OT_MSG("call MakeDirty with area x0=%d/y0=%d <-> x1=%d/y1=%d", x0, y0, x1, y1); for (int x=x0;x<=x1;x++) { for (int y=y0;y<=y1;y++) { MakeDirty(x,y); } } MessageW=0; MessageH=0; ReleaseFlush(); } // vim: ts=4 sw=4 et vdr-plugin-osdteletext-2.3.1/displaybase.h000066400000000000000000000224261415701714300206300ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) 2005 by Udo Richter * * Copyright (c) 2021 by Peter Bieringer (extenions) * * * * displaybase.h - Base class for rendering a teletext cRenderPage to * * an actual VDR OSD. * * * * 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 OSDTELETEXT_DISPLAYBASE_H_ #define OSDTELETEXT_DISPLAYBASE_H_ #include "txtrender.h" #include "setup.h" #include #include // #define dsyslog_osdteletext(format, arg...) dsyslog(format, ## arg) #define dsyslog_osdteletext(format, arg...) { } class cDisplay : public cRenderPage { // Class that extends the virtual cRenderPage with the capability // to render its contents to an OSD of variable size. // Renders incrementally - just changes // plus adds some more display features like message display. public: enum enumZoom { // Zoom up upper/lower half of page Zoom_Off, Zoom_Upper, Zoom_Lower } Zoom; enum enumAlignment { AlignmentLeft, AlignmentCenter, AlignmentRight } Alignment; protected: bool Concealed; // Hidden text internal state bool Blinked; // Blinking text internal state int FlushLock; // Lock counter for bundeling OSD flushes bool Boxed; // Page is 'boxed mode' transparent int Width; int Height; // OSD pixel dimension tColor Background; // Color to be used for black background // - allow transparency bool Paused; // Paused internal state bool PageIdDisplayedEver; // Flag whether the PageId was ever displayed so far cOsd *osd; // The osd object. If creation fails, may be NULL int outputWidth; int outputHeight; // for 32bpp true color, If creation fails, may be NULL int leftFrame, rightFrame, topFrame, bottomFrame; // frame border const cFont *MessageFont; int MessageBorder; int MessageX,MessageY,MessageW,MessageH; const cFont *TXTFont; const cFont *TXTDblWFont; const cFont *TXTDblHFont; const cFont *TXTDblHWFont; const cFont *TXTHlfHFont; int fontHeight; int fontWidth; static int realFontWidths[5]; static int realFontHeights[5]; class cBox { // helper class. Represents a character's box in virtual coordinates public: int XMin,YMin,XMax,YMax; inline void SetToCharacter(int x, int y); }; friend class cBox; class cVirtualCoordinate { // helper class. Represents a coordinate in virtual display space // and in OSD pixel coordinates. public: int OsdX,OsdY; int VirtX,VirtY; inline void VirtualToPixel(cDisplay *Display, int x, int y); inline void IncPixelX(cDisplay *Display); inline void IncPixelY(cDisplay *Display); }; friend class cVirtualCoordinate; public: cDisplay(int width, int height); virtual ~cDisplay(); bool Valid() { return (osd!=NULL); } // After creation, check for Valid(). Destroy, if not valid. void setOutputWidth(int w) { outputWidth = w; }; void setOutputHeight(int h) { outputHeight = h; }; void setLeftFrame (int lF) { leftFrame = lF; }; void setRightFrame (int rF) { rightFrame = rF; }; void setTopFrame (int tF) { topFrame = tF; }; void setBottomFrame(int bF) { bottomFrame = bF; }; static std::string GFXFontFootprint; static std::string TXTFontFootprint; protected: void InitScaler(); // Initialize transformation for OSD->Virtual coordinates // Some words about scaling: // OSD display is variable width x height, with 3 pixels border // on all sides. There is a virtual coordinate system projected // on this, with (3,3) mapped to (0,0) and (width-3,height-3) // mapped to (480<<16,250<<16). // The idea is, that each font pixel uses a virtual rectangle // of (1<<16,1<<16) size. // ScaleX,ScaleY represent the (virtual) width and height of a // physical OSD pixel. public: bool GetBlink() { return Blinked; } bool SetBlink(bool blink); // Switch blink frequently to get blinking chars // Returns true if there are blinking characters. bool GetConceal() { return Concealed; } bool SetConceal(bool conceal); // Hidden text. Set to true to see hidden text. // Returns true if there are concealed characters. bool HasConceal(); // Returns true if there are concealed characters. void SetPaused(bool paused) { Paused = paused; return; }; bool GetPaused() { return Paused; }; // Returns true if paused enumZoom GetZoom() { return Zoom; } void SetZoom(enumZoom zoom); // Zoom to upper/lower half of page void SetBackgroundColor(tColor c); tColor GetBackgroundColor() { return Background; } // Set the background color for black. Allows transparent black. // Color mapping interface. virtual tColor GetColorRGB(enumTeletextColor ttc, int Area); // Map a teletext color to an OSD color in #Area. virtual tColor GetColorRGBAlternate(enumTeletextColor ttc, int Area); // For color collision: // Map this teletext color to an OSD color in #Area, but dont // return same as GetColorRGB(). Used to solve conflicts if // foreground and background are mapped to same color. // Defaults to 1:1 identity. Not needed if all colors actually // supported by OSD. protected: void DrawDisplay(); // Draw all dirty characters from cRenderPage buffer to OSD void CleanDisplay(); // Clean OSD completely virtual void DrawChar(int x, int y, cTeletextChar c); // Draw a single character to OSD public: void HoldFlush() { FlushLock++; } // Hold all OSD flush updates to bundle operations. void ReleaseFlush() { FlushLock--; Flush(); } // Release hold of flush updates. After last release, // the flush will be done protected: void Flush() { // Commit all changes from OSD internal bitmaps to device // All draw operations inside cDisplay should call it, // no one outside should need to call it. if (FlushLock>0) return; if (!osd) return; if (IsDirty()) DrawDisplay(); osd->Flush(); } public: void RenderTeletextCode(unsigned char *PageCode); // Interprete teletext code referenced by PageCode // and draw the whole page content into OSD. // PageCode must be a 40*24+12 bytes buffer void DrawText(int x, int y, const char *text, int len, const enumTeletextColor cText = ttcWhite); // Draw some characters in teletext page. // Max len chars, fill up with spaces void DrawTextExtended(const int x, const int y, const char *text, int len, const enumAlignment alignment, const enumTeletextColor ttcFg, const enumTeletextColor ttcBg); // Draw some characters in teletext page. // Max len chars, fill up with spaces // with alignment, foreground and background color void DrawHotkey(const char *textRed, const char *textGreen, const char* textYellow, const char *textBlue, const HotkeyFlag flag); // Draw hotkey to OSD (line 25) void DrawInfo(const char *textI1, const char *textI2, const char* textI3, const char *textI4, const char *textI5, const InfoLineFlag flag); // Draw info line with 5 columns to OSD (line 26: flag=InfoLine1, line 27: flag=InfoLine2) void DrawClock(); // Draw current time to OSD void DrawPageId(const char *text, const enumTeletextColor cText = ttcWhite, const bool boxedAlwaysOn = false); // Draw Page ID string to OSD with optional text color and optional always in boxed mode void DrawMessage(const char *txt1, const char *txt2 = NULL, const cString *txtArray = NULL, const enumTeletextColor *ctxtArray = NULL, const int txtArrayEntries = 0, const int txtArrayColumns = 0, const enumTeletextColor cFrame = ttcWhite, const enumTeletextColor cText = ttcWhite, const enumTeletextColor cBackground = ttcBlack, const enumTeletextColor cTextArray = ttcGrey); // Draw a framed, centered message box to OSD with // optional(default) color definition for frame(white), text(white), background(black), txtArray(grey) // optional a 2nd line // optional additional lines with text in columns // optional colors for additional lines void ClearMessage(); // Remove message box and redraw hidden content void ClearPage(void); // Clear Teletext Page on OSD private: cFont *GetFont(const char *name, int index, int height, int width); std::string GetFontFootprint(const char *name); }; inline void cDisplay::cBox::SetToCharacter(int x, int y) { // Virtual box area of a character XMin=(x*12)<<16; YMin=(y*10)<<16; XMax=XMin+(12<<16)-1; YMax=YMin+(10<<16)-1; } #endif vdr-plugin-osdteletext-2.3.1/legacystorage.c000066400000000000000000000115621415701714300211530ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) 2003,2004 by Marcel Wiesweg * * * * 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 #include "legacystorage.h" LegacyStorage::LegacyStorage(int maxMB) : fsBlockSize(1), pageBytes(TELETEXT_PAGESIZE) { initMaxStorage(maxMB); } LegacyStorage::~LegacyStorage() { } /* static inline int FilesForMegabytes(double MB, int blocksize) { double pageBytes; if (TELETEXT_PAGESIZE<=blocksize) pageBytes=blocksize; else pageBytes=((TELETEXT_PAGESIZE/blocksize)+1)*blocksize; //reserve 10% for directories return (int)( (1024.0 * 1024.0 * (MB-MB*0.1)) / pageBytes ); }*/ int LegacyStorage::actualFileSize(int netFileSize) { if (netFileSize<=0) return 0; if (netFileSize<=fsBlockSize) return fsBlockSize; else return ((netFileSize/fsBlockSize)+1)*fsBlockSize; } //max==0 means unlimited, max==-1 means a reasonable default value shall be calculated void LegacyStorage::initMaxStorage(int maxMB) { struct statfs fs; if (statfs(getRootDir(), &fs)!=0) { esyslog("osdteletext: Error statfs'ing root directory \"%s\": %s, cache size uncontrolled", getRootDir(), strerror(errno)); return; } fsBlockSize=fs.f_bsize; pageBytes=actualFileSize(TELETEXT_PAGESIZE); if (maxMB>=0) { if (maxMB<3) { esyslog("osdteletext: Request to use at most %d MB for caching. This is not enough, using 3 MB", maxMB); maxMB=3; } maxBytes=MEGABYTE(maxMB); } else if (maxMB==-1) { //calculate a default value double blocksPerMeg = 1024.0 * 1024.0 / fs.f_bsize; double capacityMB=fs.f_blocks / blocksPerMeg; double freeMB=(fs.f_bavail / blocksPerMeg); if (capacityMB<=50 || freeMB<50) { //small (<=50MB) filesystems as root dir are assumed to be dedicated for use as a teletext cache //for others, the maximum default size is set to 50 MB maxBytes=MEGABYTE((int)freeMB); //maxPages= FilesForMegabytes(freeMB, fs.f_bsize); if (freeMB<3.0) { esyslog("osdteletext: Less than %.1f MB free on filesystem of root directory \"%s\"!", freeMB, getRootDir()); maxBytes=MEGABYTE(3); } } else { //the maximum default size is set to 50 MB maxBytes=MEGABYTE(50); } //printf("Set maxBytes to %ld, %.2f %.2f\n", maxBytes, capacityMB, freeMB); } } void LegacyStorage::cleanUp() { byteCount -= Storage::doCleanUp(); } void LegacyStorage::registerFile(PageID page) { //pageBytes is already effective size if ( maxBytes && (byteCount+=pageBytes)>maxBytes ) freeSpace(); } StorageHandle LegacyStorage::openForReading(PageID page, bool countAsAccess) { //the countAsAccess argument was intended for use in a LRU cache, currently unused char filename[PATH_MAX]; getFilename(filename, sizeof(filename), page); StorageHandle ret=(StorageHandle)open(filename, O_RDONLY); return ret; } StorageHandle LegacyStorage::openForWriting(PageID page) { static bool wroteError=false; char filename[PATH_MAX]; getFilename(filename, sizeof(filename), page); bool existed=exists(filename); //first try StorageHandle fd=(StorageHandle)open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (fd) { if (!existed) registerFile(page); return fd; } //no space on disk? make some space available if (errno == ENOSPC) freeSpace(); //second try fd=(StorageHandle)open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (!fd && !wroteError) { //report error to syslog - once! wroteError=true; esyslog("osdteletext: Error opening teletext file %s: %s", filename, strerror(errno)); } //make sure newly created files are counted if (fd && !existed) registerFile(page); return fd; } ssize_t LegacyStorage::write(const void *ptr, size_t size, StorageHandle stream) { ssize_t written; if (!(written=::write((int)stream, ptr, size)) ) { switch (errno) { case ENOSPC: freeSpace(); return ::write((int)stream, ptr, size); case EINTR: esyslog("osdteletext: EINTR while writing. Please contact the author and tell him this happened."); break; default: break; } } return written; } vdr-plugin-osdteletext-2.3.1/legacystorage.h000066400000000000000000000027711415701714300211620ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) 2003,2004 by Marcel Wiesweg * * * * 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 __LEGACYSTORAGE_H #define __LEGACYSTORAGE_H #include "storage.h" class LegacyStorage : public Storage { private: void initMaxStorage(int maxMB=-1); public: LegacyStorage(int maxMB); virtual ~LegacyStorage(); virtual void cleanUp(); virtual StorageHandle openForWriting(PageID page); virtual StorageHandle openForReading(PageID page, bool countAsAccess); virtual ssize_t write(const void *ptr, size_t size, StorageHandle stream); virtual ssize_t read(void *ptr, size_t size, StorageHandle stream) { return ::read((int)stream, ptr, size); } virtual void close(StorageHandle stream) { ::close((int)stream); } protected: void registerFile(PageID page); virtual int actualFileSize(int netFileSize); //int maxPages; long maxBytes; int fsBlockSize; int pageBytes; }; #endif vdr-plugin-osdteletext-2.3.1/logging.h000066400000000000000000000077461415701714300177660ustar00rootroot00000000000000 #ifndef LOGGING_H_INCLUDED #define LOGGING_H_INCLUDED #include extern unsigned int m_debugmask; extern unsigned int m_debugpage; extern unsigned int m_debugpsub; extern int m_debugline; #define BOOLTOTEXT(var) ((var == true) ? "true" : "false") #define DEBUG_MASK_OT 0x00000001 // general #define DEBUG_MASK_OT_CACHE 0x00000002 // Caching System #define DEBUG_MASK_OT_TXTRCVC 0x00000004 // Text Receiver channel related #define DEBUG_MASK_OT_KNONE 0x00000010 // Knone action #define DEBUG_MASK_OT_KEYS 0x00000020 // Keys action #define DEBUG_MASK_OT_NEPG 0x00000100 // new cTelePage #define DEBUG_MASK_OT_COPG 0x00000200 // regular log amount of new cTelePage #define DEBUG_MASK_OT_SETUP 0x00000800 // ttSetup #define DEBUG_MASK_OT_DD 0x00001000 // DrawDisplay #define DEBUG_MASK_OT_MSG 0x00002000 // Draw/Clear Message #define DEBUG_MASK_OT_DRPI 0x00004000 // DrawPageId #define DEBUG_MASK_OT_HOTK 0x00008000 // DrawHotkey #define DEBUG_MASK_OT_FONT 0x00010000 // Font #define DEBUG_MASK_OT_AREA 0x00020000 // Area #define DEBUG_MASK_OT_DBFC 0x00040000 // DisplayBase Function Call #define DEBUG_MASK_OT_SCALER 0x00080000 // Scaler #define DEBUG_MASK_OT_BLINK 0x00100000 // Text Blink #define DEBUG_MASK_OT_DCHR 0x00200000 // DrawChar #define DEBUG_MASK_OT_BOXED 0x00400000 // BoxedOut #define DEBUG_MASK_OT_DTXT 0x00800000 // DrawText #define DEBUG_MASK_OT_TXTRDT 0x01000000 // Text Rendering triplet #define DEBUG_MASK_OT_RENCLN 0x02000000 // Render/Clean #define DEBUG_MASK_OT_TXTRCVD 0x04000000 // Text Receiver dump to stdout (particular page only, see code) #define DEBUG_MASK_OT_TXTRD 0x08000000 // Text Rendering dump to stdout // special action mask #define DEBUG_MASK_OT_ACT_LIMIT_LINES 0x10000000 // Limit Lines (debugging for detecting pixel offset issues) #define DEBUG_MASK_OT_ACT_OSD_BACK_RED 0x20000000 // OSD Background Red (debugging for detecting pixel offset issues) #define DEBUG_MASK_OT_ACT_CHAR_BACK_BLUE 0x40000000 // Char Background Blue (debugging for detecting pixel offset issues) #define dsyslog_ot(format, arg...) dsyslog("osdteletext: DEBUG %s/%s: " format, __FILE__, __FUNCTION__, ## arg) #define wsyslog_ot(format, arg...) esyslog("osdteletext: WARN %s/%s: " format, __FILE__, __FUNCTION__, ## arg) #define DEBUG_OT if (m_debugmask & DEBUG_MASK_OT) dsyslog_ot #define DEBUG_OT_FONT if (m_debugmask & DEBUG_MASK_OT_FONT) dsyslog_ot #define DEBUG_OT_DBFC if (m_debugmask & DEBUG_MASK_OT_DBFC) dsyslog_ot #define DEBUG_OT_NEPG if (m_debugmask & DEBUG_MASK_OT_NEPG) dsyslog_ot #define DEBUG_OT_COPG if (m_debugmask & DEBUG_MASK_OT_COPG) dsyslog_ot #define DEBUG_OT_AREA if (m_debugmask & DEBUG_MASK_OT_AREA) dsyslog_ot #define DEBUG_OT_SCALER if (m_debugmask & DEBUG_MASK_OT_SCALER) dsyslog_ot #define DEBUG_OT_BLINK if (m_debugmask & DEBUG_MASK_OT_BLINK) dsyslog_ot #define DEBUG_OT_SETUP if (m_debugmask & DEBUG_MASK_OT_SETUP) dsyslog_ot #define DEBUG_OT_DD if (m_debugmask & DEBUG_MASK_OT_DD) dsyslog_ot #define DEBUG_OT_KNONE if (m_debugmask & DEBUG_MASK_OT_KNONE) dsyslog_ot #define DEBUG_OT_KEYS if (m_debugmask & DEBUG_MASK_OT_KEYS) dsyslog_ot #define DEBUG_OT_MSG if (m_debugmask & DEBUG_MASK_OT_MSG) dsyslog_ot #define DEBUG_OT_DRPI if (m_debugmask & DEBUG_MASK_OT_DRPI) dsyslog_ot #define DEBUG_OT_HOTK if (m_debugmask & DEBUG_MASK_OT_HOTK) dsyslog_ot #define DEBUG_OT_DCHR if (m_debugmask & DEBUG_MASK_OT_DCHR) dsyslog_ot #define DEBUG_OT_BOXED if (m_debugmask & DEBUG_MASK_OT_BOXED) dsyslog_ot #define DEBUG_OT_DTXT if (m_debugmask & DEBUG_MASK_OT_DTXT ) dsyslog_ot #define DEBUG_OT_CACHE if (m_debugmask & DEBUG_MASK_OT_CACHE) dsyslog_ot #define DEBUG_OT_TXTRDT if (m_debugmask & DEBUG_MASK_OT_TXTRDT) dsyslog_ot #define DEBUG_OT_RENCLN if (m_debugmask & DEBUG_MASK_OT_RENCLN) dsyslog_ot #define DEBUG_OT_TXTRCVC if (m_debugmask & DEBUG_MASK_OT_TXTRCVC) dsyslog_ot #define DEBUG_OT_TXTRCVD if (m_debugmask & DEBUG_MASK_OT_TXTRCVD) dsyslog_ot #define DEBUG_OT_TXTRD if (m_debugmask & DEBUG_MASK_OT_TXTRD) dsyslog_ot #endif vdr-plugin-osdteletext-2.3.1/menu.c000066400000000000000000001533771415701714300173010ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) 2003,2004 by Marcel Wiesweg * * Copyright (c) 2021 by Peter Bieringer (extenions) * * * * 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 #include #include #include #include "menu.h" #include "display.h" #include "setup.h" #include "txtrecv.h" #include "logging.h" #define GET_HUNDREDS(x) ( ( (x) - ((x)%256) ) /256 ) #define GET_TENS(x) ( (( (x) - ((x)%16) )%256 ) /16 ) #define GET_ONES(x) ( (x)%16 ) #define GET_HUNDREDS_DECIMAL(x) ( ( (x) - ((x)%100) ) /100 ) #define GET_TENS_DECIMAL(x) ( (( (x) - ((x)%10) )%100 ) /10 ) #define GET_ONES_DECIMAL(x) ( (x)%10 ) #define PSEUDO_HEX_TO_DECIMAL(x) ( (GET_HUNDREDS_DECIMAL(x))*256 + (GET_TENS_DECIMAL(x))*16 + (GET_ONES_DECIMAL(x)) ) #define TTC_CHANNEL_LIVE ttcWhite #define TTC_CHANNEL_TUNED ttcMagenta #define TTC_CHANNEL_CACHED ttcCyan using namespace std; typedef map IntMap; IntMap channelPageMap; // map for flag whether Page100 was stored already in cache, used on ChannelSwitch hint page typedef map IntBoolMap; IntBoolMap channelPage100Stored; //static variables int TeletextBrowser::currentPage=0x100; //Believe it or not, the teletext numbers are somehow hexadecimal int TeletextBrowser::currentSubPage=0; tChannelID TeletextBrowser::channel; cChannel TeletextBrowser::channelClass; int TeletextBrowser::currentChannelNumber=0; int TeletextBrowser::liveChannelNumber=0; bool TeletextBrowser::switchChannelInProgress = false; eChannelInfo TeletextBrowser::ChannelInfo; TeletextBrowser* TeletextBrowser::self=0; tColor clrBackground; bool clrBackgroundInit = false; extern int maxOsdPreset; extern int maxHotkeyLevel; eTeletextActionConfig configMode = LastActionConfig; TeletextBrowser::TeletextBrowser(cTxtStatus *txtSt,Storage *s) : cursorPos(0), pageFound(true), selectingChannel(false), hotkeyLevel(0), delayClearMessage(0), needClearMessage(false), selectingChannelNumber(-1), txtStatus(txtSt), previousPage(currentPage), previousSubPage(currentSubPage), pageBeforeNumberInput(currentPage), lastActivity(time(NULL)), inactivityTimeout(-1), storage(s) { DEBUG_OT("called"); if (!clrBackgroundInit) { clrBackground = TTSETUPPRESET_TCOLOR(BackTrans); // default clrBackgroundInit = true; }; ttSetup.osdPreset = 0; // default preset self=this; } TeletextBrowser::~TeletextBrowser() { DEBUG_OT("called"); Display::Delete(); self=0; } void TeletextBrowser::Show(void) { DEBUG_OT("called"); Display::SetMode(Display::mode, clrBackground); ShowPage(); } bool TeletextBrowser::CheckIsValidChannel(int number) { #if defined(APIVERSNUM) && APIVERSNUM >= 20301 LOCK_CHANNELS_READ; return (Channels->GetByNumber(number) != 0); #else return (Channels.GetByNumber(number) != 0); #endif } // callback from txtrec in case of page 100 was received and stored void TeletextBrowser::ChannelPage100Stored(int ChannelNumber) { DEBUG_OT_TXTRCVC("called with ChNu=%d", ChannelNumber); channelPage100Stored[ChannelNumber] = true; }; void TeletextBrowser::ChannelSwitched(int ChannelNumber, const eChannelInfo info) { static eChannelInfo infoLast = ChannelIsLive; static int ChannelNumberLast = 0; DEBUG_OT_TXTRCVC("called with ChNu=%d ChNuLa=%d liChNu=%d info=%d infoLa=%d switchChannelInProgress=%s", ChannelNumber, ChannelNumberLast, liveChannelNumber, info, infoLast, BOOLTOTEXT(switchChannelInProgress)); #if defined(APIVERSNUM) && APIVERSNUM >= 20301 LOCK_CHANNELS_READ; const cChannel *chan=Channels->GetByNumber(ChannelNumber); #else cChannel *chan=Channels.GetByNumber(ChannelNumber); #endif if (!chan) return; tChannelID chid=chan->GetChannelID(); if (chid==tChannelID::InvalidID) return; channel=chid; channelClass = *chan; // remember for later to display channel name if ((info == ChannelIsLive) || (info == ChannelIsLiveButHasNoTeletext)) liveChannelNumber= ChannelNumber; // remember active live channel ChannelInfo = info; // store info //store page number of current channel IntMap::iterator it; channelPageMap[currentChannelNumber] = currentPage; currentChannelNumber=ChannelNumber; currentPage=0x100; currentSubPage=0; //see if last page number on this channel was stored it=channelPageMap.find(ChannelNumber); if (it != channelPageMap.end()) { //found currentPage=(*it).second; } //on the one hand this must work in background mode, when the plugin is not active. //on the other hand, if active, the page should be shown. //so this self-Pointer. if (self) { char str[80] = ""; char str2[80] = ""; Display::ClearPage(); enumTeletextColor color = ttcBlue; snprintf(str2, sizeof(str2), "%d: %s", channelClass.Number(), channelClass.Name()); self->delayClearMessage = 1; // default if ((info == ChannelIsLiveButHasNoTeletext) || (info == ChannelIsTunedButHasNoTeletext)) { snprintf(str, sizeof(str), "%s %s (%s %s)", tr("Switch to"), tr("Channel"), tr("without"), tr("Teletext")); color = ttcRed; } else if (info == ChannelIsLive) { if (infoLast == ChannelIsLive) { // don't display message during zapping } else { snprintf(str, sizeof(str), "%s %s %s", tr("Switch to"), tr("live"), tr("Channel")); }; } else if (info == ChannelIsTuned) { if (liveChannelNumber == currentChannelNumber) { snprintf(str, sizeof(str), "%s %s", tr("Switch back to live"), tr("Channel")); ChannelInfo = ChannelIsLive; } else { snprintf(str, sizeof(str), "%s - %s", tr("Tuner available"), tr("display current pages")); color = ttcMagenta; }; } else if (info == ChannelWasTunedNewChannelIsLive) { // received trigger that TUNED channel has no longer a receiver but new would be a LIVE channel // suppress a message which will be shortly overwritten anyhow by starting receiver on new channel ChannelInfo = ChannelIsCached; // new status } else if (info == ChannelWasTuned) { // received trigger that TUNED channel has no longer a receiver if (! switchChannelInProgress) { // but no channel switch action in progress -> display message snprintf(str, sizeof(str), "%s - %s", tr("Tuner busy"), tr("display cached pages")); color = ttcCyan; } else { // suppress a message which will be shortly overwritten anyhow by starting receiver on new channel }; ChannelInfo = ChannelIsCached; // new status } else if (info == ChannelIsCached) { snprintf(str, sizeof(str), "%s %s %s", tr("Switch to"), tr("cached"), tr("Channel")); color = ttcCyan; } else { // all cases catched }; self->ShowPage((strlen(str) > 0)); if (strlen(str) > 0) { self->needClearMessage=true; Display::DrawMessage(str, str2, color); }; } // store for acting related on next call infoLast = info; ChannelNumberLast = ChannelNumber; // clear status switchChannelInProgress = false; } bool TeletextBrowser::TriggerChannelSwitch(const int channelNumber) { bool result = false; // switch to new channel #if defined(APIVERSNUM) && APIVERSNUM >= 20301 LOCK_CHANNELS_READ; const cChannel* newChannel = Channels->GetByNumber(channelNumber); #else const cChannel* newChannel = Channels.GetByNumber(channelNumber); #endif if (!newChannel) return false; if (txtStatus->receiver) { // receiver is already running if (txtStatus->receiver->Live()) { if (channelNumber == liveChannelNumber) { DEBUG_OT_TXTRCVC("requested channel %d is LIVE channel, running receiver found on LIVE channel %d - not action required", channelNumber, liveChannelNumber); } else { DEBUG_OT_TXTRCVC("requested channel %d is NON-LIVE channel, running receiver found on LIVE channel %d - action will be triggered later", channelNumber, liveChannelNumber); }; } else { if (channelNumber == liveChannelNumber) { DEBUG_OT_TXTRCVC("requested channel %d is LIVE channel, running receiver found on NON-LIVE channel %d - action will be triggered later", channelNumber, liveChannelNumber); } else { DEBUG_OT_TXTRCVC("requested channel %d is NON-LIVE channel, running receiver found on NON-LIVE channel %d - stop receiver to release device", channelNumber, liveChannelNumber); switchChannelInProgress = true; DELETENULL(txtStatus->receiver); }; }; }; cDevice *device = cDevice::GetDeviceForTransponder(newChannel, TRANSFERPRIORITY - 1); if (device != NULL) { needClearMessage = true; switchChannelInProgress = true; if (device->SwitchChannel(newChannel, (channelNumber == liveChannelNumber) ? true : false)) { if (1 == 0) { // too verbose - disabled Display::DrawMessage(tr("Channel Tuning Successful"), ttcGreen); }; result = true; DEBUG_OT_TXTRCVC("DVB %d successful tuned to channel %d (live=%s)", device->DeviceNumber(), channelNumber, BOOLTOTEXT(channelNumber == liveChannelNumber)); } else { needClearMessage = true; delayClearMessage = 5; Display::DrawMessage(tr("Channel Tuning Not Successful"), ttcRed); DEBUG_OT_TXTRCVC("DVB %d cannot tune to channel %d", device->DeviceNumber(), channelNumber); }; } else { if (1 == 0) { // too verbose - disabled needClearMessage = true; delayClearMessage = 2; Display::DrawMessage(tr("No Free Tuner Found - Use Cache Only"), ttcYellow); }; DEBUG_OT_TXTRCVC("no free tuner available to tune to channel %d (use cache)", channelNumber); ChannelSwitched(channelNumber, ChannelIsCached); }; return (result); }; eOSState TeletextBrowser::ProcessKey(eKeys Key) { cDisplay::enumZoom zoomR; Display::Mode modeR; tColor bgcR, bgcSetup = TTSETUPPRESET_TCOLOR(BackTrans); bool changedConfig = false; if (Key != kNone) lastActivity = time(NULL); if (Key != kNone) DEBUG_OT_KEYS("called with Key=%d", Key); switch (Key) { case k1: SetNumber(1);break; case k2: SetNumber(2);break; case k3: SetNumber(3);break; case k4: SetNumber(4);break; case k5: SetNumber(5);break; case k6: SetNumber(6);break; case k7: SetNumber(7);break; case k8: SetNumber(8);break; case k9: SetNumber(9);break; case k0: //same behavior for 0 as VDR does it with channels if ((cursorPos==0) && (!selectingChannel)) { //swap variables int tempPage=currentPage; int tempSubPage=currentSubPage; currentPage=previousPage; currentSubPage=previousSubPage; previousPage=tempPage; previousSubPage=tempSubPage; ShowPage(); } else SetNumber(0); break; case kOk: if (selectingChannel) { selectingChannel=false; Display::ClearMessage(); if (selectingChannelNumber>0) { if (CheckIsValidChannel(selectingChannelNumber)) { if (selectingChannelNumber != liveChannelNumber) { DEBUG_OT_KEYS("trigger switch to channel %d", selectingChannelNumber); txtStatus->SetNonLiveChannelNumber(selectingChannelNumber); // preload next channel switch with a non-live channel (-> TUNED) TriggerChannelSwitch(selectingChannelNumber); } else { // nothing todo DEBUG_OT_KEYS("no need to trigger switch to channel %d because currently running as live channel", selectingChannelNumber); ChannelSwitched(liveChannelNumber, ChannelIsLive); }; } else { needClearMessage=true; delayClearMessage = 3; char str[9]; snprintf(str, sizeof(str), "%d", selectingChannelNumber); Display::DrawMessage(trVDR("*** Invalid Channel ***"), str, ttcRed); } } else { if (selectingChannelNumber != liveChannelNumber) { txtStatus->SetNonLiveChannelNumber(0); // clear non-live channel for next channel switch DEBUG_OT_KEYS("trigger switch to channel %d", liveChannelNumber); TriggerChannelSwitch(liveChannelNumber); selectingChannelNumber = liveChannelNumber; } else { // nothing todo DEBUG_OT_KEYS("no need to trigger switch to channel because unchanged"); }; } } else { ExecuteAction(TranslateKey(Key)); }; break; case kBack: return osEnd; case kNone: //approx. every second DEBUG_OT_KNONE("section 'kNone' reached with GetPaused=%s needClearMessage=%s delayClearMessage=%d", BOOLTOTEXT(Display::GetPaused()), BOOLTOTEXT(needClearMessage), delayClearMessage); //checking if page changed if ((delayClearMessage == 0) && ! Display::GetPaused() && pageFound && ttSetup.autoUpdatePage && cursorPos==0 && !selectingChannel && (PageCheckSum() != checkSum) ) { DEBUG_OT_KNONE("section 'kNone' detected: 'page change'"); ShowPage(); //check if page was previously not found and is available now } else if ((delayClearMessage == 0) && !pageFound && CheckFirstSubPage(0)) { DEBUG_OT_KNONE("section 'kNone' detected: 'previous not found page is now available'"); ShowPage(); } else { DEBUG_OT_KNONE("section 'kNone' default"); if (needClearMessage) { if (delayClearMessage > 0) { delayClearMessage--; } else { needClearMessage=false; Display::ClearMessage(); if (!pageFound) // (re-)display "not found" information ShowPage(); }; } else { delayClearMessage = 0; // reset }; if (! selectingChannel && pageFound) { //updating clock if (! Display::GetPaused()) UpdateClock(); //updating hotkey UpdateHotkey(); //trigger blink if (! Display::GetPaused()) Display::SetBlink(not(Display::GetBlink())); }; } //check for activity timeout if (Setup.MinUserInactivity && ((time(NULL) - lastActivity) > (Setup.MinUserInactivity * 60))) return osEnd; break; case kUp: if (selectingChannel) { selectingChannel=false; Display::ClearMessage(); } if (cursorPos != 0) { //fully revert cursor SetNumber(-3); } ChangePageRelative(DirectionForward); Display::ShowUpperHalf(); ShowPage(); break; case kDown: if (selectingChannel) { selectingChannel=false; Display::ClearMessage(); } if (cursorPos != 0) { //fully reset SetNumber(-3); } ChangePageRelative(DirectionBackward); Display::ShowUpperHalf(); ShowPage(); break; case kRight: if (selectingChannel) { selectingChannel=false; Display::ClearMessage(); } if (cursorPos != 0) { //fully reset SetNumber(-3); } ChangeSubPageRelative(DirectionForward); Display::ShowUpperHalf(); ShowPage(); break; case kLeft: if (selectingChannel) { selectingChannel=false; Display::ClearMessage(); } if (cursorPos != 0) { //revert cursor SetNumber(-1); break; } ChangeSubPageRelative(DirectionBackward); Display::ShowUpperHalf(); ShowPage(); break; case kRed: if (configMode != LastActionConfig) { // catch config mode changedConfig = ExecuteActionConfig(configMode, -1); // decrement break; }; // continue below case kGreen: if (configMode != LastActionConfig) { // catch config mode changedConfig = ExecuteActionConfig(configMode, +1); // increment break; }; // continue below case kYellow: if (configMode != LastActionConfig) { // key is inactive in config mode (displaying value) break; }; // continue below case kBlue: if (configMode != LastActionConfig) { // catch config mode ExecuteAction(Config); break; }; // continue below case kPlay: //case kPause: // not passed into plugin somehow case kStop: //case kRecord: // not passed into plugin somehow case kFastFwd: case kFastRew: if (cursorPos != 0) { //fully reset SetNumber(-3); } ExecuteAction(TranslateKey(Key)); break; default: break; } if (changedConfig) { zoomR = Display::GetZoom(); // remember zoom modeR = Display::mode; // remember mode if (TTSETUPPRESET_TCOLOR(BackTrans) != bgcSetup) { bgcR = TTSETUPPRESET_TCOLOR(BackTrans); // color was changed during config clrBackground = bgcR; // set globally DEBUG_OT_KEYS("osdteletext: recreate display with remembered mode=%d zoom=%d and setup configured bgc=%08x", modeR, zoomR, bgcR); } else { bgcR = Display::GetBackgroundColor(); // remember color DEBUG_OT_KEYS("osdteletext: recreate display with remembered mode=%d zoom=%d bgc=%08x", modeR, zoomR, bgcR); }; Display::Delete(); Display::SetMode(modeR, bgcR); // new with remembered mode and background color Display::SetZoom(zoomR); // apply remembered zoom ShowPage(); }; return osContinue; } bool TeletextBrowser::ExecuteActionConfig(eTeletextActionConfig e, int delta) { bool changedConfig = false; #define COND_ADJ_VALUE(value, min, max, delta) \ if (((value + delta) >= min) && ((value + delta) <= max)) { \ value += delta; \ changedConfig = true; \ } else if ((value + delta) < min) { \ value = min; \ changedConfig = true; \ } else if ((value + delta) > max) { \ value = max; \ changedConfig = true; \ }; switch (configMode) { case Left: COND_ADJ_VALUE(TTSETUPPRESET(configMode), OSDleftPctMin, OSDleftPctMax, delta); break; case Top: COND_ADJ_VALUE(TTSETUPPRESET(configMode), OSDtopPctMin, OSDtopPctMax, delta); break; case Width: COND_ADJ_VALUE(TTSETUPPRESET(configMode), OSDwidthPctMin, OSDwidthPctMax, delta); break; case Height: COND_ADJ_VALUE(TTSETUPPRESET(configMode), OSDheightPctMin, OSDheightPctMax, delta); break; case Frame: COND_ADJ_VALUE(TTSETUPPRESET(configMode), OSDframePixMin, OSDframePixMax, delta); break; case Font: TTSETUPPRESET(configMode)++; if (TTSETUPPRESET(configMode) >= ttSetup.txtFontNames.Size()) TTSETUPPRESET(configMode) = 0; // rollover changedConfig = true; break; case Voffset: COND_ADJ_VALUE(TTSETUPPRESET(configMode), txtVoffsetMin, txtVoffsetMax, delta); break; case BackTrans: DEBUG_OT_KEYS("key action: 'Config->BackTrans' BackTrans=%d BackTransMin=%d BackTransMax=%d delta=%d", TTSETUPPRESET(configMode), BackTransMin, BackTransMax, delta * 8); COND_ADJ_VALUE(TTSETUPPRESET(configMode), BackTransMin, BackTransMax, delta * 8); break; default: // nothing todo break; }; return (changedConfig); }; void TeletextBrowser::ExecuteAction(eTeletextAction e) { cDisplay::enumZoom zoomR; Display::Mode modeR; switch (e) { case Zoom: DEBUG_OT_KEYS("key action: 'Zoom' Display::GetZoom=%d", Display::GetZoom()); if (selectingChannel) { selectingChannel=false; Display::ClearMessage(); } switch (Display::GetZoom()) { case cDisplay::Zoom_Off: Display::SetZoom(cDisplay::Zoom_Upper); break; case cDisplay::Zoom_Upper: Display::SetZoom(cDisplay::Zoom_Lower); break; case cDisplay::Zoom_Lower: Display::SetZoom(cDisplay::Zoom_Off); break; } break; case HalfPage: DEBUG_OT_KEYS("key action: 'Half Page' Display::mode=%d clrBackground=%08x", Display::mode, clrBackground); if (selectingChannel) { selectingChannel=false; Display::ClearMessage(); } switch (Display::mode) { case Display::HalfUpper: Display::SetMode(Display::HalfLower, clrBackground); break; case Display::HalfLower: Display::SetMode(Display::HalfUpperTop, clrBackground); break; case Display::HalfUpperTop: Display::SetMode(Display::HalfLowerTop, clrBackground); break; case Display::HalfLowerTop: Display::SetMode(Display::Full, clrBackground); break; case Display::Full: Display::SetMode(Display::HalfUpper, clrBackground); break; } ShowPage(); break; case SwitchChannel: DEBUG_OT_KEYS("key action: 'SwitchChannel'"); if (!selectingChannel) { selectingChannelNumber=0; selectingChannel=true; ShowAskForChannel(); } else { selectingChannel=false; Display::ClearMessage(); }; break; case DarkScreen: DEBUG_OT_KEYS("key action: 'DarkScreen'"); ChangeBackground(); break; case LineMode24: DEBUG_OT_KEYS("key action: 'LineMode24' lineMode24=%d", ttSetup.lineMode24); // toggle LineMode24: Hotkeys -> Hotkeys+Stdkeys -> None -> Hotkeys // 0: 25 lines / Hotkeys // 1: 24 lines / None // 2: 27 lines / Hotkeys+Stdkeys if (ttSetup.lineMode24 == HintLinesHotkeysAndStdkeys) { ttSetup.lineMode24 = HintLinesNone; } else if (ttSetup.lineMode24 == HintLinesNone) { ttSetup.lineMode24 = HintLinesHotkeys; } else { ttSetup.lineMode24 = HintLinesHotkeysAndStdkeys; }; zoomR = Display::GetZoom(); // remember zoom modeR = Display::mode; // remember mode Display::Delete(); Display::SetMode(modeR, clrBackground); // new with remembered mode and background color Display::SetZoom(zoomR); // apply remembered zoom ShowPage(); break; case Config: DEBUG_OT_KEYS("key action: 'Config' lineMode24=%d configMode=%d", ttSetup.lineMode24, configMode); if (ttSetup.lineMode24 == 1) { // config mode is only supported in 25/27-line mode needClearMessage=true; delayClearMessage = 3; Display::DrawMessage(tr("*** Config mode is not supported in 24-line mode ***"), ttcYellow); break; }; switch(configMode) { case LastActionConfig : configMode = Left ; break; // start config mode case Left : configMode = Top ; break; case Top : configMode = Width ; break; case Width : configMode = Height ; break; case Height : configMode = Frame ; break; case Frame : configMode = Font ; break; case Font : configMode = Voffset ; break; case Voffset : configMode = BackTrans; break; case BackTrans : configMode = LastActionConfig; break; // stop config mode }; ShowPage(); break; case HotkeyLevelPlus: case HotkeyLevelMinus: if (ttSetup.lineMode24 == 1) { // HotkeyLevel switch mode is only supported in 25/27-line mode // otherwise one can get lost and has to enter plugin setup menu to disable 24-line mode there needClearMessage=true; delayClearMessage = 3; Display::DrawMessage(tr("Hotkey level change is not supported in 24-line mode"), ttcYellow); break; }; if (maxHotkeyLevel <= 1) { // HotkeyLevel disabled by command line option limit to 1 or default needClearMessage=true; delayClearMessage = 3; Display::DrawMessage(tr("Hotkey levels are disabled"), ttcRed); break; }; if (ttSetup.hotkeyLevelMax < 2) { // HotkeyLevel not active by setup limit to 1 needClearMessage=true; delayClearMessage = 3; Display::DrawMessage(tr("Hotkey levels are not active"), ttcYellow); break; }; switch(e) { case HotkeyLevelPlus: DEBUG_OT_KEYS("key action: 'HotkeyLevelPlus' current hotkeyLevel=%d ttSetup.hotkeyLevelMax=%d", hotkeyLevel, ttSetup.hotkeyLevelMax); hotkeyLevel++; if (hotkeyLevel == ttSetup.hotkeyLevelMax) hotkeyLevel = 0; // rollover to minimum break; case HotkeyLevelMinus: DEBUG_OT_KEYS("key action: 'HotkeyLevelMinus' current hotkeyLevel=%d ttSetup.hotkeyLevelMax=%d", hotkeyLevel, ttSetup.hotkeyLevelMax); hotkeyLevel--; if (hotkeyLevel < 0) hotkeyLevel = ttSetup.hotkeyLevelMax - 1; // rollover to maximum break; default: // will not reached but avoids compiler warning break; }; ShowPage(); break; case OsdPresetPlus: case OsdPresetMinus: if (maxOsdPreset <= 1) { // OSD Preset disabled by command line option limit to 1 or default needClearMessage=true; delayClearMessage = 3; Display::DrawMessage(tr("OSD presets are disabled"), ttcRed); break; }; if (ttSetup.osdPresetMax <= 2) { // HotkeyLevel not active by setup limit to 1 needClearMessage=true; delayClearMessage = 3; Display::DrawMessage(tr("OSD presets are not active"), ttcYellow); break; }; switch(e) { case OsdPresetPlus: DEBUG_OT_KEYS("key action: 'OsdPresetPlus' current ttSetup.osdPreset=%d ttSetup.osdPresetMax=%d", ttSetup.osdPreset, ttSetup.osdPresetMax); ttSetup.osdPreset++; if (ttSetup.osdPreset == ttSetup.osdPresetMax) ttSetup.osdPreset = 0; // rollover to minimum break; case OsdPresetMinus: DEBUG_OT_KEYS("key action: 'HotkeyLevelMinus' current ttSetup.osdPreset=%d ttSetup.ttSetup.osdPresetMax=%d", ttSetup.osdPreset, ttSetup.osdPresetMax); ttSetup.osdPreset--; if (ttSetup.osdPreset < 0) ttSetup.osdPreset = ttSetup.osdPresetMax - 1; // rollover to maximum break; default: // will not reached but avoids compiler warning break; }; Display::Delete(); Display::SetMode(Display::Full, TTSETUPPRESET_TCOLOR(BackTrans)); ShowPage(); break; case ToggleConceal: DEBUG_OT_KEYS("key action: 'ToggleConceal' Concealed=%d -> %d", Display::GetConceal(), not(Display::GetConceal())); Display::SetConceal(not(Display::GetConceal())); ShowPage(); break; case TogglePause: if ((ChannelInfo == ChannelIsLive) || (ChannelInfo == ChannelIsTuned)) { DEBUG_OT_KEYS("key action: 'TogglePause' paused=%d -> %d", Display::GetPaused(), not(Display::GetPaused())); // toggle paused status only if LIVE or TUNED channel (otherwise useless) Display::SetPaused(not(Display::GetPaused())); ShowPage(); } else { DEBUG_OT_KEYS("key action: 'TogglePause' useless, currently not a LIVE or TUNED channel on OSD"); }; break; default: //In osdteletext.c, numbers are thought to be decimal, the setup page //entries will display them in this way. It is a lot easier to do the //conversion to hexadecimal here. //This means, we convert the number to what it would be if the string //had been parsed with hexadecimal base. int pageNr=PSEUDO_HEX_TO_DECIMAL((int)e); if (0x100<=pageNr && pageNr<=0x899) { if (selectingChannel) { selectingChannel=false; Display::ClearMessage(); } SetPreviousPage(currentPage, currentSubPage, pageNr); currentPage=pageNr; cursorPos=0; currentSubPage=0; Display::ShowUpperHalf(); ShowPage(); } break; } } // 3-state toggling between configured->transparent->black. // If configured is black or transparent, do 2-state transparent->black only. void TeletextBrowser::ChangeBackground() { tColor clrConfig = TTSETUPPRESET_TCOLOR(BackTrans); tColor clrCurrent = clrBackground; if (clrCurrent == clrConfig) if (clrConfig == clrTransparent) clrBackground = clrBlack; else clrBackground = clrTransparent; else if (clrCurrent == clrBlack) if (clrConfig == clrBlack) clrBackground = clrTransparent; else clrBackground = clrConfig; else // clrCurrent == clrTransparent clrBackground = clrBlack; Display::SetBackgroundColor(clrBackground); } eTeletextAction TeletextBrowser::TranslateKey(eKeys Key) { switch(Key) { case kRed: return (eTeletextAction)ttSetup.mapHotkeyToAction[ActionHotkeyRed] [hotkeyLevel]; case kGreen: return (eTeletextAction)ttSetup.mapHotkeyToAction[ActionHotkeyGreen] [hotkeyLevel]; case kYellow: return (eTeletextAction)ttSetup.mapHotkeyToAction[ActionHotkeyYellow][hotkeyLevel]; case kBlue: return (eTeletextAction)ttSetup.mapHotkeyToAction[ActionHotkeyBlue] [hotkeyLevel]; case kPlay: return (eTeletextAction)ttSetup.mapKeyToAction[ActionKeyPlay]; //case kPause: return (eTeletextAction)ttSetup.mapKeyToAction[ActionKeyPause]; // not passed into plugin somehow case kOk: return (eTeletextAction)ttSetup.mapKeyToAction[ActionKeyOk]; case kStop: return (eTeletextAction)ttSetup.mapKeyToAction[ActionKeyStop]; //case kRecord: return (eTeletextAction)ttSetup.mapKeyToAction[ActionKeyRecord]; // not passed into plugin somehow case kFastFwd: return (eTeletextAction)ttSetup.mapKeyToAction[ActionKeyFastFwd]; case kFastRew: return (eTeletextAction)ttSetup.mapKeyToAction[ActionKeyFastRew]; default: return (eTeletextAction)100; //just to keep gcc quiet } } void TeletextBrowser::SetNumber(int i) { //cursorPos means insertion after, 0<=cursorPos<=2 if (selectingChannel) { selectingChannelNumber = selectingChannelNumber*10+i; ShowAskForChannel(); return; } //i<0 means revert cursor position if (i<0) { for (;i<0;i++) { switch (cursorPos) { case 0: return; case 1: currentPage = currentPage-256*GET_HUNDREDS(currentPage)+256*GET_HUNDREDS(pageBeforeNumberInput); break; case 2: currentPage = currentPage-16*GET_TENS(currentPage)+16*GET_TENS(pageBeforeNumberInput); break; } cursorPos--; } ShowPageNumber(); return; } static int tempPage; switch (cursorPos) { case 0: if (i<1) i=1; //accept no 9 when cursorPos==0 if (i>8) i=8; tempPage= currentPage; pageBeforeNumberInput = currentPage; currentPage = currentPage-256*GET_HUNDREDS(currentPage)+256*i; break; case 1: if (i<0) i=0; if (i>9) i=9; currentPage = currentPage-16*GET_TENS(currentPage)+16*i; break; case 2: if (i<0) i=0; if (i>9) i=9; currentPage = currentPage-GET_ONES(currentPage)+i; pageBeforeNumberInput = currentPage; SetPreviousPage(tempPage, currentSubPage, currentPage); break; } pageFound=true; //so that "page ... not found" is not displayed, but e.g. 1**-00 if (++cursorPos>2) { cursorPos=0; CheckFirstSubPage(0); Display::ShowUpperHalf(); ShowPage(); } else { ShowPageNumber(); } } //returns whether x, when written in hexadecimal form, //will only contain the digits 0...9 and not A...F //in the first three digits. static inline bool onlyDecimalDigits(int x) { return (( x & 0xE) < 0xA) && (( (x>>4) & 0xE) < 0xA) && (( (x>>8) & 0xE) < 0xA); } //after 199 comes 1A0, but if these pages exist, they contain no useful data, so filter them out int TeletextBrowser::nextValidPageNumber(int start, Direction direction) { do { switch (direction) { case DirectionForward: start++; break; case DirectionBackward: start--; break; } } while (!onlyDecimalDigits(start)); return start; } void TeletextBrowser::ChangePageRelative(Direction direction) { int oldpage = currentPage; int oldSubPage = currentSubPage; do { /*if (back) currentPage--; else currentPage++;*/ currentPage=nextValidPageNumber(currentPage, direction); if (currentPage>0x899) currentPage=0x100; if (currentPage<0x100) currentPage=0x899; // sub page is always 0 if you change the page if (CheckFirstSubPage(0)) { SetPreviousPage(oldpage, oldSubPage, currentPage); return; } } while (currentPage != oldpage); return; } void TeletextBrowser::ChangeSubPageRelative(Direction direction) { int oldsubpage = currentSubPage; do { /*if (back) currentSubPage--; else currentSubPage++;*/ currentSubPage=nextValidPageNumber(currentSubPage, direction); if (currentSubPage > 0x99) currentSubPage=0; if (currentSubPage < 0) currentSubPage=0x99; if (CheckPage()) return; } while (currentSubPage != oldsubpage); return; } bool TeletextBrowser::CheckFirstSubPage(int startWith) { int oldsubpage = currentSubPage; do { if (CheckPage()) return true; //currentSubPage++; currentSubPage=nextValidPageNumber(currentSubPage, DirectionForward); if (currentSubPage > 0x99) currentSubPage=0; if (currentSubPage < 0) currentSubPage=0x99; } while (currentSubPage != oldsubpage); return false; } bool TeletextBrowser::CheckPage() { StorageHandle fd; if (!(fd=storage->openForReading(PageID(channel, currentPage, currentSubPage), false)) ) return false; storage->close(fd); return true; } //sets the previousPage variables if and only if new page is different from old page void TeletextBrowser::SetPreviousPage(int oldPage, int oldSubPage, int newPage) { if (oldPage != newPage) { previousPage=oldPage; previousSubPage=oldSubPage; } } void TeletextBrowser::ShowPage(bool suppressMessage) { DEBUG_OT("called with suppressMessage=%s", BOOLTOTEXT(suppressMessage)); if ((pageFound=DecodePage(suppressMessage))) { if (ttSetup.autoUpdatePage) checkSum=PageCheckSum(); } } void TeletextBrowser::ShowPageNumber() { DEBUG_OT_DRPI("called with currentPage=%03x currentSubPage=%02x", currentPage, currentSubPage); char str[9]; snprintf(str, sizeof(str), "%3x-%02x ", currentPage, currentSubPage); if (cursorPos>0) { str[2]='*'; if (cursorPos==1) str[1]='*'; } if (ChannelInfo == ChannelIsTuned) { str[7]='t'; Display::DrawPageId(str, TTC_CHANNEL_TUNED, true); // colored } else if (liveChannelNumber != currentChannelNumber) { str[7]='c'; Display::DrawPageId(str, TTC_CHANNEL_CACHED, true); // colored } else Display::DrawPageId(str); } void TeletextBrowser::ShowAskForChannel() { #define channelHintsEntriesMax 40 #define channelHintsColumns 3 // cached during plugin run cString channelHintsArray[channelHintsEntriesMax]; enumTeletextColor channelHintsArrayColors[channelHintsEntriesMax]; int channelHintsEntries = 0; if (selectingChannel) { int channelNumber = 1; while (channelHintsEntries < channelHintsEntriesMax) { if (! CheckIsValidChannel(channelNumber)) { // no more channels break; }; #if defined(APIVERSNUM) && APIVERSNUM >= 20301 LOCK_CHANNELS_READ; const cChannel* Channel = Channels->GetByNumber(channelNumber); #else const cChannel* Channel = Channels.GetByNumber(channelNumber); #endif if (Channel->Tpid()) { // only store channels with Teletext bool cached = false; IntBoolMap::iterator it = channelPage100Stored.find(channelNumber); if (it != channelPage100Stored.end()) { //found cached = true; }; const char *hint = ""; enumTeletextColor color = ttcGrey; // default if (channelNumber == liveChannelNumber) { hint = ":L"; color = TTC_CHANNEL_LIVE; } else if (channelNumber == currentChannelNumber) { hint = ":T"; color = TTC_CHANNEL_TUNED; } else if (cached) { hint = ":C"; color = TTC_CHANNEL_CACHED; }; // add additional hint text channelHintsArray[channelHintsEntries] = cString::sprintf("%d%s: %s", channelNumber, hint, Channel->ShortName(true)); channelHintsArrayColors[channelHintsEntries] = color; channelHintsEntries++; }; channelNumber++; }; cString str = cString::sprintf((selectingChannelNumber > 0) ? "%s%d_" : "%s_", tr("Channel (press OK): "), selectingChannelNumber); if (channelHintsEntries > 0) { // new, with channel hints cString str2 = cString::sprintf("%s (Top %d %s %s)", tr("Channels"), channelHintsEntries, tr("with"), tr("Teletext")); Display::DrawMessage(str, str2, channelHintsArray, channelHintsArrayColors, channelHintsEntries, channelHintsColumns, ttcBlue); } else { // default without channel hints Display::DrawMessage(str, ttcBlue); }; } } //this is taken and adapted from the teletext plugin since it uses its data bool TeletextBrowser::DecodePage(bool suppressMessage) { DEBUG_OT("called with suppressMessage=%s", BOOLTOTEXT(suppressMessage)); // Load the page and decodes it unsigned char cache[sizeof(TelePageData)]; StorageHandle fd; // Take a look if there is a xxx-00 page if (currentSubPage==0) { if ( !(fd=storage->openForReading(PageID(channel, currentPage,currentSubPage), false)) ) { // There is no subpage 0 so look if there is subpage 1 currentSubPage++; // Generate file string } else { // yes file exists storage->close(fd); } } if ( (fd=storage->openForReading(PageID(channel, currentPage, currentSubPage), true)) ) { storage->read(cache,sizeof cache,fd); // Read full page data storage->close(fd); Display::HoldFlush(); Display::ClearMessage(); Display::RenderTeletextCode(cache); ShowPageNumber(); UpdateClock(); UpdateHotkey(); Display::ReleaseFlush(); } else { // page doesn't exist currentSubPage--; Display::HoldFlush(); char str[80]; char str2[80]; snprintf(str2, sizeof(str2), "%d: %s", channelClass.Number(), channelClass.Name()); enumTeletextColor color = ttcYellow; if ((ChannelInfo == ChannelIsLiveButHasNoTeletext) || (ChannelInfo == ChannelIsTunedButHasNoTeletext)) { snprintf(str, sizeof(str), "%s %s (%s %s)", tr("Switch to"), tr("Channel"), tr("without"), tr("Teletext")); color = ttcRed; } else { ShowPageNumber(); snprintf(str, sizeof(str), "%s %3x-%02x%s%s %s%s%s%s",tr("Page"),currentPage, currentSubPage , (ChannelInfo == ChannelIsCached) ? " " : "" , (ChannelInfo == ChannelIsCached) ? tr("in cache") : "" , tr("not found") , ((ChannelInfo == ChannelIsTuned) || (ChannelInfo == ChannelIsLive)) ? " (" : "" , ((ChannelInfo == ChannelIsTuned) || (ChannelInfo == ChannelIsLive)) ? tr("please wait") : "" , ((ChannelInfo == ChannelIsTuned) || (ChannelInfo == ChannelIsLive)) ? ")" : "" ); if (ChannelInfo == ChannelIsTuned) { color = ttcMagenta; } else if (ChannelInfo == ChannelIsCached) { color = ttcRed; }; }; if (! suppressMessage) { needClearMessage = false; Display::DrawMessage(str, str2, color); }; UpdateHotkey(); Display::ReleaseFlush(); return false; } return true; } int TeletextBrowser::PageCheckSum() { int retSum=0; StorageHandle fd; CheckFirstSubPage(currentSubPage); if ((fd=storage->openForReading(PageID(channel, currentPage, currentSubPage), false)) ) { uchar cache[960]; storage->read(cache, 12, fd); //skip storage->read(cache, sizeof(cache), fd); storage->close(fd); memset(cache+12, 0, 8); //it seems that there the clock is transmitted, ignore changes for (uint i=0;i 1 // implant hotkeyLevel/osdPreset +/- in case of text length is above limit-2 #define CONVERT_ACTION_TO_TEXT(text, mode, limit) \ if ((mode == HotkeyLevelPlus) || (mode == HotkeyLevelMinus)) { \ snprintf(text, sizeof(text), "%-40s", tr(st_modesHotkey[mode])); \ if (strlen(tr(st_modesHotkey[mode])) > limit - 1) text[limit - 2] = (mode == HotkeyLevelPlus) ? '+' : '-'; \ text[limit - 1] = '0' + (int) hotkeyLevel + 1; \ text[limit] = '\0'; \ } else if ((mode == OsdPresetPlus) || (mode == OsdPresetMinus)) { \ snprintf(text, sizeof(text), "%-40s", tr(st_modesHotkey[mode])); \ if (strlen(tr(st_modesHotkey[mode])) > limit - 1) text[limit - 2] = (mode == OsdPresetPlus) ? '+' : '-'; \ text[limit - 1] = '0' + (int) ttSetup.osdPreset + 1; \ text[limit] = '\0'; \ } else if ((mode == Config) && (ttSetup.osdPresetMax > 1) && (configMode != LastActionConfig)) { \ snprintf(text, sizeof(text), "%-40s", tr(st_modesHotkey[mode])); \ text[limit - 2] = ' '; \ text[limit - 1] = '0' + (int) ttSetup.osdPreset + 1; \ text[limit] = '\0'; \ } else if ((int) mode < 100) { \ snprintf(text, sizeof(text), "%s", tr(st_modesHotkey[mode])); \ } else if ((int) mode < 999) { \ snprintf(text, sizeof(text), "-> %03d", mode); \ } else { \ snprintf(text, sizeof(text), "ERROR"); \ }; \ void TeletextBrowser::UpdateHotkey() { DEBUG_OT_HOTK("called with lineMode24=%d", ttSetup.lineMode24); if (ttSetup.lineMode24 == 1) return; // nothing to do char textRed[81]= "", textGreen[81] = "", textYellow[81] = "", textBlue[81] = ""; // 40x UTF-8 char + \0 HotkeyFlag flag = HotkeyNormal; // default eTeletextActionValueType valueType = None; if (configMode == LastActionConfig) { eTeletextAction AkRed = TranslateKey(kRed); eTeletextAction AkGreen = TranslateKey(kGreen); eTeletextAction AkYellow = TranslateKey(kYellow); eTeletextAction AkBlue = TranslateKey(kBlue); DEBUG_OT_HOTK("AkRed=%d AkGreen=%d AkYellow=%d AkBlue=%d", AkRed, AkGreen, AkYellow, AkBlue); CONVERT_ACTION_TO_TEXT(textRed , AkRed , 10); CONVERT_ACTION_TO_TEXT(textGreen , AkGreen , 10); CONVERT_ACTION_TO_TEXT(textYellow, AkYellow, 10); CONVERT_ACTION_TO_TEXT(textBlue , AkBlue , 10); } else { switch (configMode) { case Left: case Top: case Width: case Height: case Frame: case Voffset: case BackTrans: snprintf(textRed , sizeof(textRed) , "%s-", tr(config_modes[configMode])); // - snprintf(textGreen , sizeof(textGreen) , "%s+", tr(config_modes[configMode])); // + flag = HotkeyYellowValue; break; case Font: snprintf(textRed , sizeof(textRed) , "%s" , tr(config_modes[configMode])); // DEBUG_OT_HOTK("txtFontIndex=%d txtFontNames[%d]='%s'", TTSETUPPRESET(Font), TTSETUPPRESET(Font), ttSetup.txtFontNames[TTSETUPPRESET(Font)]); snprintf(textGreen, sizeof(textGreen) , "%s", ttSetup.txtFontNames[TTSETUPPRESET(Font)]); // FontName flag = HotkeyGreenYellowValue; break; default: break; }; int valueInt = 0; char *valueStr = NULL; switch (configMode) { case Left: case Top: case Width: case Height: valueInt = TTSETUPPRESET(configMode); valueType = Pct; break; case Frame: case Voffset: valueInt = TTSETUPPRESET(configMode); valueType = Pix; break; case BackTrans: valueInt = TTSETUPPRESET(configMode); valueType = Int; break; default: break; }; switch(valueType) { case Pct: snprintf(textYellow, sizeof(textYellow), "%d %%", valueInt); break; case Pix: snprintf(textYellow, sizeof(textYellow), "%d Px", valueInt); break; case Int: snprintf(textYellow, sizeof(textYellow), "%d", valueInt); break; case Str: if (valueStr != NULL) snprintf(textYellow, sizeof(textYellow), "%s", valueStr); else snprintf(textYellow, sizeof(textYellow), "%s", "ERROR-STR"); // should not happen break; case None: // handled above directly break; default: snprintf(textYellow, sizeof(textYellow), "%s", "ERROR"); // should not happen break; }; CONVERT_ACTION_TO_TEXT(textBlue, Config, 10); // option itself with optional preset number }; DEBUG_OT_HOTK("textRed='%s' textGreen='%s' text Yellow='%s' textBlue='%s' flag=%d", textRed, textGreen, textYellow, textBlue, flag); Display::DrawHotkey(textRed, textGreen, textYellow, textBlue, flag); if (ttSetup.lineMode24 != 2) return; // nothing more to do // Hint lines char textI1[81]= "FastRew", textI2[81] = "Stop", textI3[81] = "OK", textI4[81] = "Play", textI5[81] = "FastFwd"; // 40x UTF-8 char + \0 Display::DrawInfo(textI1, textI2, textI3, textI4, textI5, InfoLine1); eTeletextAction AkFastRew = TranslateKey(kFastRew); eTeletextAction AkFastFwd = TranslateKey(kFastFwd); eTeletextAction AkStop = TranslateKey(kStop); eTeletextAction AkOk = TranslateKey(kOk); eTeletextAction AkPlay = TranslateKey(kPlay); DEBUG_OT_HOTK("AkFastRew=%d AkStop=%d AkOk=%d AkPlay=%d AkFastFwd=%d", AkFastRew, AkStop, AkOk, AkPlay, AkFastFwd); CONVERT_ACTION_TO_TEXT(textI1, AkFastRew, 8); CONVERT_ACTION_TO_TEXT(textI2, AkStop , 8); CONVERT_ACTION_TO_TEXT(textI3, AkOk , 8); CONVERT_ACTION_TO_TEXT(textI4, AkPlay , 8); CONVERT_ACTION_TO_TEXT(textI5, AkFastFwd, 8); Display::DrawInfo(textI1, textI2, textI3, textI4, textI5, InfoLine2); } TeletextSetup ttSetup; TeletextSetup::TeletextSetup() //Set default values for setup options : migrationFlag_2_2(false), showClock(true), autoUpdatePage(true), osdPresetMax(1), hotkeyLevelMax(1), HideMainMenu(false), colorMode4bpp(false), lineMode24(HintLinesHotkeys) { // init osdConfig int p = 0; // Preset "default" osdConfig[Left] [p] = 15; osdConfig[Top] [p] = 5; osdConfig[Width] [p] = 70; osdConfig[Height] [p] = 90; osdConfig[Frame] [p] = 0; osdConfig[Font] [p] = 0; osdConfig[Voffset] [p] = 0; osdConfig[BackTrans][p] = 128; // Preset "2" .. "5" 50% in corners for (p = 1; p < 5; p++) { if (p < OSD_PRESET_MAX_LIMIT) { if ((p == 1) || (p == 4)) osdConfig[Left] [p] = 0; else osdConfig[Left] [p] = 50; if ((p == 1) || (p == 2)) osdConfig[Top] [p] = 0; else osdConfig[Top] [p] = 50; osdConfig[Width] [p] = 50; osdConfig[Height] [p] = 50; osdConfig[Frame] [p] = 8; osdConfig[Font] [p] = 0; osdConfig[Voffset] [p] = 0; if (p == 1) osdConfig[BackTrans][p] = 0; else if (p == 2) osdConfig[BackTrans][p] = 64; else if (p == 3) osdConfig[BackTrans][p] = 192; else if (p == 4) osdConfig[BackTrans][p] = 255; }; }; // Preset "6" .. "9" 25% in corners for (p = 5; p < 9; p++) { if (p < OSD_PRESET_MAX_LIMIT) { if ((p == 5) || (p == 8)) osdConfig[Left] [p] = 0; else osdConfig[Left] [p] = 75; if ((p == 5) || (p == 6)) osdConfig[Top] [p] = 0; else osdConfig[Top] [p] = 75; osdConfig[Width] [p] = 25; osdConfig[Height] [p] = 25; osdConfig[Frame] [p] = 4; osdConfig[Font] [p] = 0; osdConfig[Voffset] [p] = 0; if (p == 5) osdConfig[BackTrans][p] = 0; else if (p == 6) osdConfig[BackTrans][p] = 64; else if (p == 7) osdConfig[BackTrans][p] = 192; else if (p == 8) osdConfig[BackTrans][p] = 255; }; }; //init key bindings for (int i=0; i < LastActionKey; i++) mapKeyToAction[i]=(eTeletextAction)0; mapKeyToAction[ActionKeyStop]=Config; mapKeyToAction[ActionKeyFastRew]=LineMode24; mapKeyToAction[ActionKeyFastFwd]=ToggleConceal; mapKeyToAction[ActionKeyOk]=TogglePause; // init Hotkey bindings for (int i=0; i < LastActionHotkey; i++) for (int l = 0; l < HOTKEY_LEVEL_MAX_LIMIT; l++) mapHotkeyToAction[i][l]=(eTeletextAction)0; int l = 0; // hot key mapping for level 1 (default) if (l < HOTKEY_LEVEL_MAX_LIMIT) { mapHotkeyToAction[ActionHotkeyRed] [l] = DarkScreen; mapHotkeyToAction[ActionHotkeyGreen] [l] = (eTeletextAction) 100; // page 100 mapHotkeyToAction[ActionHotkeyYellow][l] = HalfPage; mapHotkeyToAction[ActionHotkeyBlue] [l] = Zoom; }; // hot key mapping for level 2 l++; if (l < HOTKEY_LEVEL_MAX_LIMIT) { mapHotkeyToAction[ActionHotkeyRed] [l] = SwitchChannel; mapHotkeyToAction[ActionHotkeyGreen] [l] = ToggleConceal; mapHotkeyToAction[ActionHotkeyYellow][l] = TogglePause; mapHotkeyToAction[ActionHotkeyBlue] [l] = HotkeyLevelPlus; }; // hot key mapping for level 3 l++; if (l < HOTKEY_LEVEL_MAX_LIMIT) { mapHotkeyToAction[ActionHotkeyRed] [l] = LineMode24; mapHotkeyToAction[ActionHotkeyGreen] [l] = (eTeletextAction) 150; // page 150 ARD Subtitle mapHotkeyToAction[ActionHotkeyYellow][l] = (eTeletextAction) 777; // page 777 3sat Subtitle mapHotkeyToAction[ActionHotkeyBlue] [l] = HotkeyLevelPlus; }; // hot key mapping for level 4 l++; if (l < HOTKEY_LEVEL_MAX_LIMIT) { mapHotkeyToAction[ActionHotkeyRed] [l] = HotkeyLevelMinus; mapHotkeyToAction[ActionHotkeyGreen] [l] = (eTeletextAction) 200; // page 200 mapHotkeyToAction[ActionHotkeyYellow][l] = (eTeletextAction) 300; // page 300 mapHotkeyToAction[ActionHotkeyBlue] [l] = HotkeyLevelPlus; }; // hot key mapping for level 5 l++; if (l < HOTKEY_LEVEL_MAX_LIMIT) { mapHotkeyToAction[ActionHotkeyRed] [l] = (eTeletextAction) 898; // page 898 3sat Test#1 mapHotkeyToAction[ActionHotkeyGreen] [l] = (eTeletextAction) 199; // page 199 ARD/ZDF Test mapHotkeyToAction[ActionHotkeyYellow][l] = (eTeletextAction) 886; // page 886 ORF2 Test mapHotkeyToAction[ActionHotkeyBlue] [l] = HotkeyLevelPlus; }; // default for other levels l++; while (l < HOTKEY_LEVEL_MAX_LIMIT) { mapHotkeyToAction[ActionHotkeyRed] [l] = (eTeletextAction) 100 + l; // page 100 + l mapHotkeyToAction[ActionHotkeyGreen] [l] = (eTeletextAction) 200 + l; // page 200 + l mapHotkeyToAction[ActionHotkeyYellow][l] = (eTeletextAction) 300 + l; // page 300 + l mapHotkeyToAction[ActionHotkeyBlue] [l] = HotkeyLevelPlus; l++; } } // vim: ts=3 sw=3 et vdr-plugin-osdteletext-2.3.1/menu.h000066400000000000000000000061671415701714300173000ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) 2003,2004 by Marcel Wiesweg * * Copyright (c) 2021 by Peter Bieringer (extenions) * * * * 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 OSDTELETEXT_MENU__H #define OSDTELETEXT_MENU__H #include #include #include #include #include "txtrecv.h" #include "setup.h" // status of current channel enum eChannelInfo { ChannelIsLive, ChannelIsTuned, ChannelIsCached, ChannelWasTuned, ChannelWasTunedNewChannelIsLive, ChannelIsLiveButHasNoTeletext, ChannelIsTunedButHasNoTeletext }; class TeletextBrowser : public cOsdObject { public: TeletextBrowser(cTxtStatus *txtSt,Storage *s); ~TeletextBrowser(); void Show(void); static void ChannelSwitched(int ChannelNumber, const eChannelInfo info); static void ChannelPage100Stored(int ChannelNumber); virtual eOSState ProcessKey(eKeys Key); protected: enum Direction { DirectionForward, DirectionBackward }; void SetNumber(int i); void ShowPage(bool suppressMessage = false); void UpdateClock(); void UpdateHotkey(); bool DecodePage(bool suppressMessage = false); void ChangePageRelative(Direction direction); void ChangeSubPageRelative(Direction direction); bool CheckPage(); void ShowAskForChannel(); bool CheckFirstSubPage(int startWith); void SetPreviousPage(int oldPage, int oldSubPage, int newPage); bool CheckIsValidChannel(int number); int PageCheckSum(); void ShowPageNumber(); void ExecuteAction(eTeletextAction e); bool ExecuteActionConfig(eTeletextActionConfig e, int delta); int nextValidPageNumber(int start, Direction direction); bool TriggerChannelSwitch(const int channelNumber); char fileName[PATH_MAX]; char page[40][24]; int cursorPos; eTeletextAction TranslateKey(eKeys Key); bool pageFound; bool selectingChannel; static eChannelInfo ChannelInfo; int hotkeyLevel; int delayClearMessage; bool needClearMessage; int selectingChannelNumber; int checkSum; cTxtStatus *txtStatus; bool paused; int previousPage; int previousSubPage; int pageBeforeNumberInput; time_t lastActivity; int inactivityTimeout; static int currentPage; static int currentSubPage; static tChannelID channel; // TODO: rename to channelId static cChannel channelClass; static int currentChannelNumber; static int liveChannelNumber; static bool switchChannelInProgress; static TeletextBrowser* self; Storage *storage; private: void ChangeBackground(); }; #endif // vim: ts=3 sw=3 et vdr-plugin-osdteletext-2.3.1/osdteletext.c000066400000000000000000001262611415701714300206710ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) 2003,2004 by Marcel Wiesweg * * (autogenerated code (c) Klaus Schmidinger) * * Copyright (c) 2021 by Peter Bieringer (extenions) * * * * 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 #include #include #include #include using namespace std; #include "menu.h" #include "txtrecv.h" #include "setup.h" #include "legacystorage.h" #include "packedstorage.h" #include "logging.h" #if defined(APIVERSNUM) && APIVERSNUM < 10739 #error "VDR-1.7.39 API version or greater is required!" #endif #define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0])) static const char *VERSION = "2.3.1"; static const char *DESCRIPTION = trNOOP("Displays teletext on the OSD"); static const char *MAINMENUENTRY = trNOOP("Teletext"); extern tColor clrBackground; unsigned int m_debugmask = 0; unsigned int m_debugpage = 0; unsigned int m_debugpsub = 0; int maxOsdPreset = 1; int maxHotkeyLevel = 1; int m_debugline = -1; class cPluginTeletextosd : public cPlugin { private: // Add any member variables or functions you may need here. cTxtStatus *txtStatus; bool startReceiver; bool storeTopText; Storage *storage; int maxStorage; void initTexts(); Storage::StorageSystem storageSystem; public: cPluginTeletextosd(void); virtual ~cPluginTeletextosd(); virtual const char *Version(void) { return VERSION; } virtual const char *Description(void) { return tr(DESCRIPTION); } virtual const char *CommandLineHelp(void); virtual bool ProcessArgs(int argc, char *argv[]); virtual bool Start(void); virtual void Stop(void); virtual void Housekeeping(void); virtual const char *MainMenuEntry(void); virtual cOsdObject *MainMenuAction(void); virtual cMenuSetupPage *SetupMenu(void); virtual bool SetupParse(const char *Name, const char *Value); }; class cTeletextSetupPage; // macro for creating setup string with given text and conditional index+1 suffix #define CREATE_SETUP_STRING_COND_SUFFIX(index, text) \ if (index == 0) \ snprintf(str, sizeof(str), "%s", text); \ else \ snprintf(str, sizeof(str), "%s%d", text, index + 1); class ActionEdit { public: void Init(cTeletextSetupPage*, int, cMenuEditIntItem *, cMenuEditStraItem *); void Init(cTeletextSetupPage*, int, int, bool, cMenuEditIntItem *, cMenuEditStraItem *); cMenuEditStraItem *action; cMenuEditIntItem *number; }; struct ActionKeyName { const char *internalName; const char *userName; }; class cTeletextSetupPage : public cMenuSetupPage { friend class ActionEdit; friend class cPluginTeletextosd; private: TeletextSetup temp; int osdPreset; int hotkeyLevel; int tempPageNumber[LastActionKey]; int tempPageNumberHotkey[LastActionHotkey][HOTKEY_LEVEL_MAX_LIMIT]; cOsdItem *osdPresetMaxItem; cOsdItem *osdPresetItem; cString osdPresetString; cOsdItem *osdPresetConfigItem[LastActionConfig][OSD_PRESET_MAX_LIMIT]; // array of supported configuration items cOsdItem *menuSectionKeysItem; cOsdItem *hotkeyLevelMaxItem; cOsdItem *hotkeyLevelItem; cString hotkeyLevelString; protected: virtual void Store(void); int osdConfig[LastActionConfig][OSD_PRESET_MAX_LIMIT]; // matrix of supported presets ActionEdit ActionEdits[LastActionKey]; ActionEdit ActionEditsHotkey[LastActionHotkey][HOTKEY_LEVEL_MAX_LIMIT]; void SetupRefreshKeys(void); void SetupRefreshHotkeys(void); void SetupRefreshOsdConfig(void); virtual eOSState ProcessKey(eKeys Key); public: cTeletextSetupPage(void); static const ActionKeyName *actionKeyNames; static const ActionKeyName *actionHotkeyNames; static const char **modes; //~cTeletextSetupPage(void); //void SetItemVisible(cOsdItem *Item, bool visible, bool callDisplay=false); }; const ActionKeyName *cTeletextSetupPage::actionKeyNames = 0; const ActionKeyName *cTeletextSetupPage::actionHotkeyNames = 0; const char **cTeletextSetupPage::modes = 0; /*class MenuEditActionItem : public cMenuEditStraItem { public: MenuEditActionItem(cTeletextSetupPage *parentMenu, cMenuEditIntItem *pageNumberMenuItem, const char *Name, int *Value, int NumStrings, const char * const *Strings); protected: virtual eOSState ProcessKey(eKeys Key); cTeletextSetupPage *parent; cMenuEditIntItem *pageNumberItem; };*/ cPluginTeletextosd::cPluginTeletextosd(void) : txtStatus(0), startReceiver(true), storage(NULL), maxStorage(-1) , storageSystem(Storage::StorageSystemPacked) { // Initialize any member variables here. // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT! initTexts(); // read available fonts into Vector cFont::GetAvailableFontNames(&ttSetup.txtFontNames, true); // run through available fonts backwards and delete blacklisted ones for (int i = ttSetup.txtFontNames.Size() -1; i >= 0; i--) { if ( (strcasestr(ttSetup.txtFontNames[i], "Italic" ) != NULL) || (strcasestr(ttSetup.txtFontNames[i], "Oblique") != NULL) ) { DEBUG_OT_FONT("available font='%s' BLACKLISTED", ttSetup.txtFontNames[i]); ttSetup.txtFontNames.Remove(i); } else { DEBUG_OT_FONT("available font='%s' WHITELISTED", ttSetup.txtFontNames[i]); }; }; // display selectable fonts for (int i = 0; i < ttSetup.txtFontNames.Size(); i++) { if (ttSetup.txtFontNames[i] != NULL) { DEBUG_OT_FONT("selectable font[%d]='%s'", i, ttSetup.txtFontNames[i]); }; }; ttSetup.configuredClrBackground = -1; // flag for check whether it's still in setup.conf }; cPluginTeletextosd::~cPluginTeletextosd() { // Clean up after yourself! } const char *cPluginTeletextosd::CommandLineHelp(void) { // Return a string that describes all known command line options. return " -d --directory=DIR The directory where the temporary files will be stored.\n" " default: /var/cache/vdr/vtx\n" " Ensure that the directory exists and is writable.\n" " -n --max-cache=NUM Maximum size in megabytes of cache used\n" " to store the pages on the harddisk.\n" " default: a calculated value below 50 MB\n" " -s --cache-system=SYS Set the cache system to be used.\n" " Choose \"legacy\" for the traditional\n" " one-file-per-page system.\n" " Default is \"packed\" for the \n" " one-file-for-a-few-pages system.\n" " -t, --toptext Store top text pages at cache. (unviewable pages)\n" " -k --key-levels=NUM Maximum amount of Hotkey levels selectable and stored\n" " default: 1 (which deactivate this feature)\n" " maximum: " HOTKEY_LEVEL_MAX_LIMIT_STRING " levels\n" " -o --osd-presets=NUM Maximum amount of OSD presets selectable and stored\n" " default: 1 (which deactivate this feature)\n" " maximum: " OSD_PRESET_MAX_LIMIT_STRING " presets\n" " -P|--debugpage Specify page to debug (int: autoconvert internally to hex)\n" " -S|--debugpsub Specify sub-page to debug (int: autoconvert internally to hex)\n" " -L|--debugline Specify line of page to debug\n" " -D|--debugmask Enable debugmask (see logging.h for details)\n"; } bool cPluginTeletextosd::ProcessArgs(int argc, char *argv[]) { // Implement command line argument processing here if applicable. static struct option long_options[] = { { "directory", required_argument, NULL, 'd' }, { "max-cache", required_argument, NULL, 'n' }, { "cache-system", required_argument, NULL, 's' }, { "toptext", no_argument, NULL, 't' }, { "key-levels", required_argument, NULL, 'k' }, { "osd-presets", required_argument, NULL, 'o' }, { "debugmask", required_argument, NULL, 'D' }, { "debugpage", required_argument, NULL, 'P' }, { "debugpsub", required_argument, NULL, 'S' }, { "debugline", required_argument, NULL, 'L' }, { NULL } }; int c; while ((c = getopt_long(argc, argv, "o:k:s:d:n:tD:", long_options, NULL)) != -1) { switch (c) { case 's': if (!optarg) break; if (strcasecmp(optarg, "legacy")==0) storageSystem = Storage::StorageSystemLegacy; else if (strcasecmp(optarg, "packed")==0) storageSystem = Storage::StorageSystemPacked; break; case 'd': Storage::setRootDir(optarg); break; case 'n': if (isnumber(optarg)) { int n = atoi(optarg); maxStorage=n; } break; case 't': storeTopText=true; break; case 'k': if (isnumber(optarg)) { int n = atoi(optarg); if (n < 1) { maxHotkeyLevel = 1; esyslog("osdteletext: maximum key-level value (-k %s) below 1 (ignore and use minimum)", optarg); } else if ((n > HOTKEY_LEVEL_MAX_LIMIT)) { maxHotkeyLevel = HOTKEY_LEVEL_MAX_LIMIT; esyslog("osdteletext: maximum key-level value (-k %s) above limit of %d (ignore and use maximum)", optarg, HOTKEY_LEVEL_MAX_LIMIT); } else { maxHotkeyLevel = n; }; } break; case 'o': if (isnumber(optarg)) { int n = atoi(optarg); if (n < 1) { maxOsdPreset = 1; esyslog("osdteletext: maximum OSD-preset value (-o %s) below 1 (ignore and use minimum)", optarg); } else if ((n > OSD_PRESET_MAX_LIMIT)) { maxOsdPreset = OSD_PRESET_MAX_LIMIT; esyslog("osdteletext: maximum OSD-preset value (-o %s) above limit of %d (ignore and use maximum)", optarg, OSD_PRESET_MAX_LIMIT); } else { maxOsdPreset = n; }; } break; case 'D': if ((strlen(optarg) > 2) && (strncasecmp(optarg, "0x", 2) == 0)) { // hex conversion if (sscanf(optarg + 2, "%x", &m_debugmask) == 0) { esyslog("osdteletext: can't parse hexadecimal debug mask (skip): %s", optarg); }; } else { m_debugmask = atoi(optarg); }; dsyslog("osdteletext: enable debug mask: %d (0x%08x)", m_debugmask, m_debugmask); break; case 'P': if ((strlen(optarg) > 2) && (strncasecmp(optarg, "0x", 2) == 0)) { // hex conversion if (sscanf(optarg + 2, "%x", &m_debugpage) == 0) { esyslog("osdteletext: can't parse hexadecimal debug page (skip): %s", optarg); }; } else { // hex conversion if (sscanf(optarg, "%x", &m_debugpage) == 0) { esyslog("osdteletext: can't parse hexadecimal debug page (skip): %s", optarg); }; }; dsyslog("osdteletext: enable debug page: %03x", m_debugpage); break; case 'S': if ((strlen(optarg) > 2) && (strncasecmp(optarg, "0x", 2) == 0)) { // hex conversion if (sscanf(optarg + 2, "%x", &m_debugpsub) == 0) { esyslog("osdteletext: can't parse hexadecimal debug sub-page (skip): %s", optarg); }; } else { // hex conversion if (sscanf(optarg, "%x", &m_debugpsub) == 0) { esyslog("osdteletext: can't parse hexadecimal debug sub-page (skip): %s", optarg); }; }; dsyslog("osdteletext: enable debug sub-page: %03x", m_debugpsub); break; case 'L': m_debugline = atoi(optarg); dsyslog("osdteletext: enable debug page line: %d", m_debugline); break; } } return true; } bool cPluginTeletextosd::Start(void) { // Start any background activities the plugin shall perform. //Clean any files which might be remaining from the last session, //perhaps due to a crash they have not been deleted. switch (storageSystem) { case Storage::StorageSystemLegacy: isyslog("osdteletext: selected storage system: legacy"); storage = new LegacyStorage(maxStorage); break; case Storage::StorageSystemPacked: default: isyslog("osdteletext: selected storage system: packed"); storage = new PackedStorage(maxStorage); break; } if (startReceiver) txtStatus=new cTxtStatus(storeTopText, storage); if (maxOsdPreset > 1) isyslog("osdteletext: OSD multiple preset feature enabled with maximum of presets: %d", maxOsdPreset); else isyslog("osdteletext: OSD multiple preset feature not activated"); if (maxHotkeyLevel > 1) isyslog("osdteletext: OSD menu Hotkey multi-level feature enabled with maximum of levels: %d", maxHotkeyLevel); else isyslog("osdteletext: OSD menu Hotkey multi-level feature not activated"); ttSetup.osdPreset = 0; // default // legacy migration handling if ((ttSetup.migrationFlag_2_2 == false) && (ttSetup.configuredClrBackground >= 0)) { // BackTrans(1) not found, but configuredClrBackground found in setup.conf // overtake value from legacy TODO remove >= 2.3.0 ttSetup.osdConfig[BackTrans][0] = ttSetup.configuredClrBackground; dsyslog("osdteletext: overtake into 'OSDbackTrans' (preset 1) from setup.conf: configuredClrBackground: %d -> %d" , 255 - ttSetup.configuredClrBackground, ttSetup.osdConfig[BackTrans][0]); }; return true; } void cPluginTeletextosd::Stop(void) { char str[40]; // TODO: deduplicate code, see also cTeletextSetupPage::Store // Question: how to share that code beteen cTeletextSetupPage and cPluginTeletextosd // store OSD presets // preset "1" (internally 0) without digit suffix for backwards compatibility for (int p = 0; p < maxOsdPreset; p++) { CREATE_SETUP_STRING_COND_SUFFIX(p, "OSDleftPct") SetupStore(str, ttSetup.osdConfig[Left][p]); CREATE_SETUP_STRING_COND_SUFFIX(p, "OSDtopPct") SetupStore(str, ttSetup.osdConfig[Top][p]); CREATE_SETUP_STRING_COND_SUFFIX(p, "OSDwidthPct") SetupStore(str, ttSetup.osdConfig[Width][p]); CREATE_SETUP_STRING_COND_SUFFIX(p, "OSDheightPct") SetupStore(str, ttSetup.osdConfig[Height][p]); CREATE_SETUP_STRING_COND_SUFFIX(p, "OSDframePix") SetupStore(str, ttSetup.osdConfig[Frame][p]); CREATE_SETUP_STRING_COND_SUFFIX(p, "txtVoffset") SetupStore(str, ttSetup.osdConfig[Voffset][p]); CREATE_SETUP_STRING_COND_SUFFIX(p, "txtFontName") SetupStore(str, ttSetup.txtFontNames[ttSetup.osdConfig[Font][p]]); // convert into name CREATE_SETUP_STRING_COND_SUFFIX(p, "OSDbackTrans") SetupStore(str, ttSetup.osdConfig[BackTrans][p]); }; // legacy TODO remove >= 2.3.0 if (ttSetup.configuredClrBackground >= 0) { // found in setup.conf during read, so store it back in legacy format SetupStore("configuredClrBackground", 255 - ttSetup.osdConfig[BackTrans][0]); }; DELETENULL(txtStatus); if (storage) { storage->cleanUp(); DELETENULL(storage); } } void cPluginTeletextosd::initTexts() { if (cTeletextSetupPage::actionKeyNames) return; static const ActionKeyName st_actionKeyNames[] = { { "Action_kFastRew", trVDR("Key$FastRew") }, { "Action_kFastFwd", trVDR("Key$FastFwd") }, { "Action_kStop", trVDR("Key$Stop") }, { "Action_kOk", trVDR("Key$Ok") }, { "Action_kPlay", trVDR("Key$Play") }, }; cTeletextSetupPage::actionKeyNames = st_actionKeyNames; static const ActionKeyName st_actionHotkeyNames[] = { { "Action_kRed", trVDR("Key$Red") }, { "Action_kGreen", trVDR("Key$Green") }, { "Action_kYellow", trVDR("Key$Yellow") }, { "Action_kBlue", trVDR("Key$Blue") }, }; cTeletextSetupPage::actionHotkeyNames = st_actionHotkeyNames; static const char *st_modes[] = { // 1:1 relation between st_modes[] in osdteletext.c + eTeletextAction in setup.h + st_modesHotkey in setup.c tr("Zoom"), tr("Half page"), tr("Change channel"), tr("Switch background"), //tr("Suspend receiving"), tr("Config"), tr("Footer Line"), tr("Answer"), tr("Pause"), tr("Hotkey Level+"), tr("Hotkey Level-"), tr("OSD Preset+"), tr("OSD Preset-"), tr("Jump to...") // has to stay always as the last one }; cTeletextSetupPage::modes = st_modes; } void cPluginTeletextosd::Housekeeping(void) { // Perform any cleanup or other regular tasks. } const char *cPluginTeletextosd::MainMenuEntry(void) { return ttSetup.HideMainMenu ? 0 : tr(MAINMENUENTRY); } cOsdObject *cPluginTeletextosd::MainMenuAction(void) { // Perform the action when selected from the main VDR menu. return new TeletextBrowser(txtStatus,storage); } cMenuSetupPage *cPluginTeletextosd::SetupMenu(void) { // Return a setup menu in case the plugin supports one. return new cTeletextSetupPage; } /* index extraction macro */ #define CHECK_SETUP_STRING_COND_SUFFIX(name, text, index, limit) \ index = -1; \ if (! strcasecmp(name, text)) { \ index = 0; \ } else { \ if (! strncasecmp(name, text, strlen(text))) { \ if ((strlen(name) - 1) != strlen(text)) { \ esyslog("osdteletext: ignore entry with too long suffix in setup.conf: osdteletext.%s", name); \ return false; /* invalid option, only 1 digit is supported */ \ } \ /* extract digit suffix */ \ index = atoi(name + strlen(text)) - 1; /* last char digit */ \ if ((index < 1) || (index >= limit)) { \ /* ignore out-of-range suffix */ \ esyslog("osdteletext: ignore entry with out-of-range digit in setup.conf: osdteletext.%s (detected index=%d)", name, index); \ return false; \ }; \ }; \ }; \ if (index >= 0) { DEBUG_OT_SETUP("found setup config: Name=%s Text=%s Index=%d Value='%s'\n", name, text, index, Value); }; /* value check/store macro */ #define CHECK_STORE_INT_VALUE(store, value, min, max) \ store = atoi(value); \ if (store < min) store = min; \ else if (store > max) store = max; /* ignore obsolete options */ #define DSYSLOG_IGNORE_OPTION(info) dsyslog("osdteletext: ignore obsolete option in setup.conf: osdteletext.%s (%s)", Name, info); bool cPluginTeletextosd::SetupParse(const char *Name, const char *Value) { initTexts(); // Parse your own setup parameters and store their values. if (!strcasecmp(Name, "HideMainMenu")) ttSetup.HideMainMenu=atoi(Value); else if (!strcasecmp(Name, "showClock")) ttSetup.showClock=atoi(Value); else if (!strcasecmp(Name, "autoUpdatePage")) ttSetup.autoUpdatePage=atoi(Value); else if (!strcasecmp(Name, "txtG0Block")) ttSetup.txtG0Block=atoi(Value); else if (!strcasecmp(Name, "txtG2Block")) ttSetup.txtG2Block=atoi(Value); else if (!strcasecmp(Name, "colorMode4bpp")) ttSetup.colorMode4bpp=atoi(Value); else if (!strcasecmp(Name, "lineMode24")) ttSetup.lineMode24=atoi(Value); else if (!strcasecmp(Name, "OSDHAlign" )) { DSYSLOG_IGNORE_OPTION("<1.0.0") } else if (!strcasecmp(Name, "OSDVAlign" )) { DSYSLOG_IGNORE_OPTION("<1.0.0") } else if (!strcasecmp(Name, "OSDheight" )) { DSYSLOG_IGNORE_OPTION("<1.0.0") } else if (!strcasecmp(Name, "OSDwidth" )) { DSYSLOG_IGNORE_OPTION("<1.0.0") } else if (!strcasecmp(Name, "OSDhcentPct")) { DSYSLOG_IGNORE_OPTION("1.0.0-1.0.4") } else if (!strcasecmp(Name, "OSDvcentPct")) { DSYSLOG_IGNORE_OPTION("1.0.0-1.0.4") } else if (!strcasecmp(Name, "OSDframePct")) { DSYSLOG_IGNORE_OPTION(">1.0.6 && <1.0.7") } else if (!strcasecmp(Name, "suspendReceiving")) { DSYSLOG_IGNORE_OPTION("<0.8.0") } else if (!strcasecmp(Name, "inactivityTimeout")) { DSYSLOG_IGNORE_OPTION("<0.8.0") } else if (!strcasecmp(Name, "configuredClrBackground")) { // DSYSLOG_IGNORE_OPTION("<2.2.0") TODO >= 2.3.0 ttSetup.configuredClrBackground = 255 - atoi(Value); // legacy setting, map already to new internal value handling if (ttSetup.configuredClrBackground < 0) ttSetup.configuredClrBackground = 0; else if (ttSetup.configuredClrBackground > 255) ttSetup.configuredClrBackground = 255; } else if (!strcasecmp(Name, "osdPresetMax")) { ttSetup.osdPresetMax = atoi(Value); if (ttSetup.osdPresetMax > maxOsdPreset) { // limit by command line option maximum ttSetup.osdPresetMax = maxOsdPreset; } else if (ttSetup.osdPresetMax < 1) { // minimum is 1 ttSetup.osdPresetMax = 1; }; } else if (!strcasecmp(Name, "hotkeyLevelMax")) { ttSetup.hotkeyLevelMax = atoi(Value); if (ttSetup.hotkeyLevelMax > maxHotkeyLevel) { // limit by command line option maximum ttSetup.hotkeyLevelMax = maxHotkeyLevel; } else if (ttSetup.hotkeyLevelMax < 1) { // minimum is 1 ttSetup.hotkeyLevelMax = 1; }; } else { // parse setup related to OSD with preset int p; CHECK_SETUP_STRING_COND_SUFFIX(Name, "OSDleftPct", p, OSD_PRESET_MAX_LIMIT); if (p >= 0) { CHECK_STORE_INT_VALUE(ttSetup.osdConfig[Left][p], Value, OSDleftPctMin, OSDleftPctMax) return true; }; CHECK_SETUP_STRING_COND_SUFFIX(Name, "OSDtopPct", p, OSD_PRESET_MAX_LIMIT); if (p >= 0) { CHECK_STORE_INT_VALUE(ttSetup.osdConfig[Top][p], Value, OSDtopPctMin, OSDtopPctMax); return true; }; CHECK_SETUP_STRING_COND_SUFFIX(Name, "OSDwidthPct", p, OSD_PRESET_MAX_LIMIT); if (p >= 0) { CHECK_STORE_INT_VALUE(ttSetup.osdConfig[Width][p], Value, OSDwidthPctMin, OSDwidthPctMax); return true; }; CHECK_SETUP_STRING_COND_SUFFIX(Name, "OSDheightPct", p, OSD_PRESET_MAX_LIMIT); if (p >= 0) { CHECK_STORE_INT_VALUE(ttSetup.osdConfig[Height][p], Value, OSDheightPctMin, OSDheightPctMax); return true; }; CHECK_SETUP_STRING_COND_SUFFIX(Name, "OSDframePix", p, OSD_PRESET_MAX_LIMIT); if (p >= 0) { CHECK_STORE_INT_VALUE(ttSetup.osdConfig[Frame][p], Value, OSDframePixMin, OSDframePixMax); return true; }; CHECK_SETUP_STRING_COND_SUFFIX(Name, "txtVoffset", p, OSD_PRESET_MAX_LIMIT); if (p >= 0) { CHECK_STORE_INT_VALUE(ttSetup.osdConfig[Voffset][p], Value, txtVoffsetMin, txtVoffsetMax); return true; }; CHECK_SETUP_STRING_COND_SUFFIX(Name, "OSDbackTrans", p, OSD_PRESET_MAX_LIMIT); if (p >= 0) { CHECK_STORE_INT_VALUE(ttSetup.osdConfig[BackTrans][p], Value, BackTransMin, BackTransMax); if (p == 0) ttSetup.migrationFlag_2_2 = true; // set migration flag for 2.2.0 (configuredClrBackground) return true; }; CHECK_SETUP_STRING_COND_SUFFIX(Name, "txtFontName", p, OSD_PRESET_MAX_LIMIT); if (p >= 0) { // font name to index conversion int i = ttSetup.txtFontNames.Find(Value); if (i < 0) i = 0; // not found -> default is 1st one ttSetup.osdConfig[Font][p] = i; DEBUG_OT_SETUP("map setup config: Name=%s Index=%d Value='%s' to FontIndex=%d\n", Name, p, Value, i); return true; }; // parse setup related to keys for (int i=0;i= 0) { CHECK_STORE_INT_VALUE(v, Value, 0, 899); if ((v < 100) && (v >= (int) LastAction)) { esyslog("osdteletext: ignore entry with out-of-range value in setup.conf: osdteletext.%s (%d)", Name, v); return true; }; ttSetup.mapHotkeyToAction[i][l] = (eTeletextAction) v; return true; }; }; return false; } return true; } void cTeletextSetupPage::Store(void) { char str[40]; // copy temporary preset table for (int p = 0; p < OSD_PRESET_MAX_LIMIT; p++) { for (int t = 0; t < LastActionConfig; t++) { ttSetup.osdConfig[t][p] = temp.osdConfig[t][p]; }; }; ttSetup.osdPresetMax=temp.osdPresetMax; // copy key table for (int i=0;i= LastAction) //jump to page selected ttSetup.mapKeyToAction[i]=(eTeletextAction)tempPageNumber[i]; else //one of the other modes selected ttSetup.mapKeyToAction[i]=temp.mapKeyToAction[i]; } // copy Hotkey table for (int l = 0; l < HOTKEY_LEVEL_MAX_LIMIT; l++) { for (int i = 0;i < LastActionHotkey; i++) { if (temp.mapHotkeyToAction[i][l] >= LastAction) //jump to page selected ttSetup.mapHotkeyToAction[i][l] = (eTeletextAction)tempPageNumberHotkey[i][l]; else //one of the other modes selected ttSetup.mapHotkeyToAction[i][l] = temp.mapHotkeyToAction[i][l]; } } ttSetup.hotkeyLevelMax=temp.hotkeyLevelMax; ttSetup.showClock=temp.showClock; ttSetup.autoUpdatePage=temp.autoUpdatePage; ttSetup.HideMainMenu=temp.HideMainMenu; ttSetup.txtG0Block=temp.txtG0Block; ttSetup.txtG2Block=temp.txtG2Block; ttSetup.colorMode4bpp=temp.colorMode4bpp; ttSetup.lineMode24=temp.lineMode24; // store key table for (int i=0;i= 2.3.0 if (ttSetup.configuredClrBackground >= 0) { // found in setup.conf during read, so store it back in legacy format SetupStore("configuredClrBackground", 255 - ttSetup.osdConfig[BackTrans][0]); }; // Global SetupStore("showClock", ttSetup.showClock); SetupStore("autoUpdatePage", ttSetup.autoUpdatePage); SetupStore("HideMainMenu", ttSetup.HideMainMenu); SetupStore("txtG0Block", ttSetup.txtG0Block); SetupStore("txtG2Block", ttSetup.txtG2Block); SetupStore("colorMode4bpp", ttSetup.colorMode4bpp); SetupStore("lineMode24", ttSetup.lineMode24); if (clrBackground != TTSETUPPRESET_TCOLOR(BackTrans)) { clrBackground = TTSETUPPRESET_TCOLOR(BackTrans); }; } cTeletextSetupPage::cTeletextSetupPage(void) { cString buf; cOsdItem *item; temp.txtBlock[0] = tr("Latin 1"); temp.txtBlock[1] = tr("Latin 2"); temp.txtBlock[2] = tr("Latin 3"); temp.txtBlock[3] = tr("Latin 4"); temp.txtBlock[4] = tr("Cyrillic"); temp.txtBlock[5] = tr("Reserved"); temp.txtBlock[6] = tr("Greek"); temp.txtBlock[7] = tr("Reserved"); temp.txtBlock[8] = tr("Arabic"); temp.txtBlock[9] = tr("Reserved"); temp.txtBlock[10] = tr("Hebrew"); temp.lineMode[0] = tr("Hotkeys"); temp.lineMode[1] = tr("None"); temp.lineMode[2] = tr("Hotkeys+Stdkeys"); osdPreset = 1; temp.osdPresetMax = ttSetup.osdPresetMax; // init temporary preset table for (int p = 0; p < OSD_PRESET_MAX_LIMIT; p++) { for (int t = 0; t < LastActionConfig; t++) { temp.osdConfig[t][p] = ttSetup.osdConfig[t][p]; }; }; hotkeyLevel = 1; temp.hotkeyLevelMax = ttSetup.hotkeyLevelMax; // init key tables for (int i=0;i= LastAction) {//jump to page selected temp.mapKeyToAction[i]=LastAction; //to display the last string tempPageNumber[i]=ttSetup.mapKeyToAction[i]; } else { //one of the other modes selected temp.mapKeyToAction[i]=ttSetup.mapKeyToAction[i]; tempPageNumber[i]=100; } } // init Hotkey tables for (int l = 0; l < HOTKEY_LEVEL_MAX_LIMIT; l++) { for (int i = 0; i < LastActionHotkey; i++) { if (ttSetup.mapHotkeyToAction[i][l] >= LastAction) {//jump to page selected temp.mapHotkeyToAction[i][l] = LastAction; //to display the last string tempPageNumberHotkey[i][l] = ttSetup.mapHotkeyToAction[i][l]; } else { //one of the other modes selected temp.mapHotkeyToAction[i][l] = ttSetup.mapHotkeyToAction[i][l]; tempPageNumberHotkey[i][l] = 100; } } } temp.showClock=ttSetup.showClock; temp.autoUpdatePage=ttSetup.autoUpdatePage; temp.osdPresetMax=ttSetup.osdPresetMax; temp.hotkeyLevelMax=ttSetup.hotkeyLevelMax; temp.HideMainMenu=ttSetup.HideMainMenu; temp.txtG0Block=ttSetup.txtG0Block; temp.txtG2Block=ttSetup.txtG2Block; temp.colorMode4bpp=ttSetup.colorMode4bpp; temp.lineMode24=ttSetup.lineMode24; Add(new cMenuEditBoolItem(tr("Hide mainmenu entry"), &temp.HideMainMenu)); Add(new cMenuEditBoolItem(tr("Show clock"), &temp.showClock )); Add(new cMenuEditBoolItem(tr("Auto-update pages"), &temp.autoUpdatePage )); Add(new cMenuEditStraItem(tr("G0 code block"), &temp.txtG0Block, NUMELEMENTS(temp.txtBlock), temp.txtBlock)); Add(new cMenuEditStraItem(tr("G2 code block"), &temp.txtG2Block, NUMELEMENTS(temp.txtBlock), temp.txtBlock)); Add(new cMenuEditBoolItem(tr("16-Color Mode"), &temp.colorMode4bpp)); Add(new cMenuEditStraItem(tr("Footer Line"), &temp.lineMode24, NUMELEMENTS(temp.lineMode), temp.lineMode)); // OSD presets if (maxOsdPreset > 1) buf = cString::sprintf("OSD %s (%s %s %d/%d):", tr("Config"), tr("max"), tr("Presets"), maxOsdPreset, OSD_PRESET_MAX_LIMIT); else buf = cString::sprintf("OSD %s", tr("Config")); item = new cOsdItem(*buf); item->SetSelectable(false); Add(item); if (maxOsdPreset > 1) { // maximum given by command line option: maxOsdPreset cString buf2 = cString::sprintf("OSD %s %s", tr("Presets"), tr("visible")); osdPresetMaxItem = new cMenuEditIntItem(buf2, &temp.osdPresetMax, 1, maxOsdPreset); Add(osdPresetMaxItem); osdPresetString = cString::sprintf("OSD %s %s", tr("Presets"), tr("Config")); // remember string for refresh osdPresetItem = new cMenuEditIntItem(osdPresetString, &osdPreset, 1, temp.osdPresetMax); Add(osdPresetItem); } else { // hide option but remember for hook later the section entry from above osdPresetItem = item; }; for (int p = 0; p < OSD_PRESET_MAX_LIMIT; p++) { // precreate all menu entries osdPresetConfigItem[Left] [p] = new cMenuEditIntItem(tr("OSD left (%)" ), &temp.osdConfig[Left] [p], OSDleftPctMin , OSDleftPctMax ); osdPresetConfigItem[Top] [p] = new cMenuEditIntItem(tr("OSD top (%)" ), &temp.osdConfig[Top] [p], OSDtopPctMin , OSDtopPctMax ); osdPresetConfigItem[Width] [p] = new cMenuEditIntItem(tr("OSD width (%)" ), &temp.osdConfig[Width] [p], OSDwidthPctMin , OSDwidthPctMax ); osdPresetConfigItem[Height] [p] = new cMenuEditIntItem(tr("OSD height (%)" ), &temp.osdConfig[Height] [p], OSDheightPctMin, OSDheightPctMax); osdPresetConfigItem[Frame] [p] = new cMenuEditIntItem(tr("OSD frame pixel" ), &temp.osdConfig[Frame] [p], OSDframePixMin , OSDframePixMax ); osdPresetConfigItem[Font] [p] = new cMenuEditStraItem(tr("Text Font" ), &temp.osdConfig[Font] [p], ttSetup.txtFontNames.Size(), &ttSetup.txtFontNames[0]); osdPresetConfigItem[Voffset] [p] = new cMenuEditIntItem(tr("Text Vertical Offset" ), &temp.osdConfig[Voffset] [p], txtVoffsetMin , txtVoffsetMax ); osdPresetConfigItem[BackTrans][p] = new cMenuEditIntItem(tr("Background transparency"), &temp.osdConfig[BackTrans][p], BackTransMin , BackTransMax ); }; SetupRefreshOsdConfig(); // Hotkey bindings if (maxHotkeyLevel > 1) buf = cString::sprintf("%s Hotkey (%s %s %d/%d):", tr("Key bindings"), tr("max"), tr("Levels"), maxHotkeyLevel, HOTKEY_LEVEL_MAX_LIMIT); else buf = cString::sprintf("%s Hotkey:", tr("Key bindings")); item = new cOsdItem(*buf); item->SetSelectable(false); Add(item); if (maxHotkeyLevel > 1) { // maximum given by command line option: maxHotkeyLevel cString buf2 = cString::sprintf("OSD Hotkey %s %s", tr("Levels"), tr("visible")); hotkeyLevelMaxItem = new cMenuEditIntItem(buf2, &temp.hotkeyLevelMax, 1, maxHotkeyLevel); Add(hotkeyLevelMaxItem); hotkeyLevelString = cString::sprintf("OSD Hotkey %s %s", tr("Level"), tr("Config")); // remember string for refresh hotkeyLevelItem = new cMenuEditIntItem(hotkeyLevelString, &hotkeyLevel, 1, temp.hotkeyLevelMax); Add(hotkeyLevelItem); } else { // hide option but remember for hook later the section entry from above hotkeyLevelItem = item; }; for (int l = 0; l < maxHotkeyLevel; l++) { for (int i = 0; i < LastActionHotkey; i++) { ActionEditsHotkey[i][l].Init(this, i, l , (l == (hotkeyLevel - 1)) , new cMenuEditIntItem(tr(" Page number"), &tempPageNumberHotkey[i][l], 100, 899) , new cMenuEditStraItem(actionHotkeyNames[i].userName, (int*)&temp.mapHotkeyToAction[i][l], LastAction+1, modes) ); }; } // Standard Key bindings buf = cString::sprintf("%s:", tr("Key bindings")); menuSectionKeysItem = new cOsdItem(*buf); menuSectionKeysItem->SetSelectable(false); Add(menuSectionKeysItem); for (int i=0;i::Contains(item)) cList::Del(item, false); // remove all entries for (int t = 0; t < LastActionConfig; t++) for (int p = 0; p < OSD_PRESET_MAX_LIMIT; p++) DELETE_IF_EXISTING(osdPresetConfigItem[t][p]); int p = osdPreset - 1; DEBUG_OT_SETUP("display setup menu for OSD preset: %d\n", osdPreset); for (int t = 0; t < LastActionConfig; t++) { if (t == Left) { // using hook from section or preset switch Add(osdPresetConfigItem[t][p], false, osdPresetItem); } else { // use previous hook Add(osdPresetConfigItem[t][p] , false, osdPresetConfigItem[t - 1][p]); } }; }; void cTeletextSetupPage::SetupRefreshKeys(void) { // recreate key setup without sophisticated and issue causing dynamic Insert+Add (e.g. last line 'Jump to' is not working) // delete all key entry if existing for (int i = 0; i < LastActionKey; i++) { if (cList::Contains(ActionEdits[i].action)) cList::Del(ActionEdits[i].action, false); if (cList::Contains(ActionEdits[i].number)) cList::Del(ActionEdits[i].number, false); }; // add selected ones cOsdItem *hook = menuSectionKeysItem; for (int i = 0; i < LastActionKey; i++) { DEBUG_OT_KEYS("key assigment menu i=%d action=%d (main)", i, temp.mapKeyToAction[i]); Add(ActionEdits[i].action, false, hook); hook = ActionEdits[i].action; if (temp.mapKeyToAction[i] == LastAction) { // insert number if selected DEBUG_OT_KEYS("key assigment menu i=%d action=%d pagenumber=%d", i, temp.mapKeyToAction[i], tempPageNumber[i]); Add(ActionEdits[i].number, false, hook); hook = ActionEdits[i].number; }; }; } void cTeletextSetupPage::SetupRefreshHotkeys(void) { // recreate hot key setup without sophisticated and issue causing dynamic Insert+Add (e.g. last line 'Jump to' is not working) // Hotkey assignment int l = hotkeyLevel - 1; // delete all hot key entry if existing for (int l = 0; l < HOTKEY_LEVEL_MAX_LIMIT; l++) { for (int i = 0; i < LastActionHotkey; i++) { if (cList::Contains(ActionEditsHotkey[i][l].action)) cList::Del(ActionEditsHotkey[i][l].action, false); if (cList::Contains(ActionEditsHotkey[i][l].number)) cList::Del(ActionEditsHotkey[i][l].number, false); }; }; // add selected ones cOsdItem *hook = hotkeyLevelItem; for (int i = 0; i < LastActionHotkey; i++) { DEBUG_OT_KEYS("hot key assigment menu i=%d hotkeyLevel=%d action=%d (main)", i, hotkeyLevel, temp.mapHotkeyToAction[i][l]); Add(ActionEditsHotkey[i][l].action, false, hook); hook = ActionEditsHotkey[i][l].action; if (temp.mapHotkeyToAction[i][l] == LastAction) { // insert number if selected DEBUG_OT_KEYS("hot key assigment menu i=%d hotkeyLevel=%d action=%d pagenumber=%d", i, hotkeyLevel, temp.mapHotkeyToAction[i][l], tempPageNumberHotkey[i][l]); Add(ActionEditsHotkey[i][l].number, false, hook); hook = ActionEditsHotkey[i][l].number; }; }; } eOSState cTeletextSetupPage::ProcessKey(eKeys Key) { if (Key != kNone) DEBUG_OT_KEYS("called with Key=%d", Key); eOSState state = cMenuSetupPage::ProcessKey(Key); if (Key != kRight && Key!=kLeft) return state; cOsdItem *item = Get(Current()); // OSD config preset if (item == osdPresetMaxItem) { // change of OSD preset max DEBUG_OT_KEYS("osdPresetMaxItem changed osdPresetMax=%d (osdPreset=%d)", temp.osdPresetMax, osdPreset); if (osdPreset > temp.osdPresetMax) { osdPreset = temp.osdPresetMax; // recreate OSD config with reduced osdPreset (e.g. switch from >max to max) SetupRefreshOsdConfig(); }; // replace entry with new maximum cList::Del(osdPresetItem); osdPresetItem = new cMenuEditIntItem(osdPresetString, &osdPreset, 1, temp.osdPresetMax); Add(osdPresetItem, false, osdPresetMaxItem); Display(); return state; }; if (item == osdPresetItem) { // change between configs DEBUG_OT_KEYS("osdPresetItem changed osdPreset=%d", osdPreset); SetupRefreshOsdConfig(); Display(); return state; }; // OSD hotkey if (item == hotkeyLevelMaxItem) { // change of OSD menu level max DEBUG_OT_KEYS("hotkeyLevelMaxItem changed hotkeyLevelMax=%d (hotkeyLevel=%d)", temp.hotkeyLevelMax, hotkeyLevel); if (hotkeyLevel > temp.hotkeyLevelMax) { hotkeyLevel = temp.hotkeyLevelMax; // recreate Hotkey with reduced hotkeyLevel (e.g. switch from >max to max) SetupRefreshHotkeys(); }; // replace entry with new maximum cList::Del(hotkeyLevelItem); hotkeyLevelItem = new cMenuEditIntItem(hotkeyLevelString, &hotkeyLevel, 1, temp.hotkeyLevelMax); Add(hotkeyLevelItem, false, hotkeyLevelMaxItem); Display(); return state; }; if (item == hotkeyLevelItem) { // change between menu levels DEBUG_OT_KEYS("hotkeyLevelItem changed hotkeyLevel=%d", hotkeyLevel); SetupRefreshHotkeys(); Display(); return state; }; // Standard Key change handling for 'Jump to' for (int i=0;iAdd(action); if (s->temp.mapKeyToAction[num] == LastAction) { s->Add(number); }; } void ActionEdit::Init(cTeletextSetupPage* s, int num, int level, bool active, cMenuEditIntItem *p, cMenuEditStraItem * a) { action=a; number=p; if (!active) return; s->Add(action); if (s->temp.mapHotkeyToAction[num][level] == LastAction) { s->Add(number); }; } VDRPLUGINCREATOR(cPluginTeletextosd); // Don't touch this! // vim: ts=3 sw=3 et vdr-plugin-osdteletext-2.3.1/packedstorage.c000066400000000000000000000112231415701714300211300ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) 2003,2004 by Marcel Wiesweg * * * * 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 "packedstorage.h" PackedStorage::PackedStorage(int maxMB) : LegacyStorage(maxMB) { } #define TOC_SIZE 8 //The file structure is simple: // TOC_SIZE*PageAddress contains the numbers of the following pages // TOC_SIZE*TELETEXT_PAGESIZE contains the page data //and the same again. bool PackedStorage::seekTo(PageID page, int desc, bool create) { lseek(desc, 0, SEEK_SET); PageAddress addr[TOC_SIZE]; while (::read(desc, addr, sizeof(addr)) == sizeof(addr)) { lseek(desc, 0, SEEK_CUR); for (int index=0; indexmaxBytes ) freeSpace(); return (StorageHandle)desc; } //no space on disk? make some space available if (errno == ENOSPC) freeSpace(); //second try desc=open(filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (desc==-1 && !wroteError) { //report error to syslog - once! wroteError=true; esyslog("osdteletext: Error opening teletext file %s: %s", filename, strerror(errno)); } if (desc==-1) return StorageHandle(); else if (!seekTo(page, desc, true)) { ::close(desc); return StorageHandle(); } if ( maxBytes && byteCount>maxBytes ) freeSpace(); return (StorageHandle)desc; } StorageHandle PackedStorage::openForReading(PageID page, bool countAsAccess) { int desc; if ( (desc=(int)LegacyStorage::openForReading(page, false))!= -1 ) { if (!seekTo(page, desc, false)) { //this is not an error condition here, may and shall happen! ::close(desc); } else { return (StorageHandle)desc; } } return StorageHandle(); } vdr-plugin-osdteletext-2.3.1/packedstorage.h000066400000000000000000000026341415701714300211430ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) 2003,2004 by Marcel Wiesweg * * * * 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 __PACKEDSTORAGE_H #define __PACKEDSTORAGE_H #include "legacystorage.h" class PackedStorage : public LegacyStorage { public: PackedStorage(int maxMB); virtual void getFilename(char *buffer, int bufLength, PageID page); virtual StorageHandle openForWriting(PageID page); virtual StorageHandle openForReading(PageID page, bool countAsAccess); protected: struct PageAddress { bool operator==(const PageID &id) const { return page==id.page && subPage==id.subPage; } void operator=(const PageID &id) { page=id.page; subPage=id.subPage; } unsigned int page; unsigned int subPage; }; bool seekTo(PageID page, int fd, bool create); void registerFile(PageID page); }; #endif vdr-plugin-osdteletext-2.3.1/pageid.h000066400000000000000000000021641415701714300175560ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) 2003,2004 by Marcel Wiesweg * * * * 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 __PAGEID_H #define __PAGEID_H #include #include #include #include #include #include struct PageID { PageID() { page=subPage=0; } PageID(tChannelID id, int p, int s) { set(id, p, s); } void set(tChannelID id, int p, int s) { channel=id; page=p; subPage=s; } tChannelID channel; unsigned int page; unsigned int subPage; }; #endif vdr-plugin-osdteletext-2.3.1/po/000077500000000000000000000000001415701714300165675ustar00rootroot00000000000000vdr-plugin-osdteletext-2.3.1/po/ca_ES.po000066400000000000000000000074631415701714300201130ustar00rootroot00000000000000# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Marc Rovira Vall , 2003 # Ramon Roca , 2003 # Jordi Vilà , 2003 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-12-11 18:04+0100\n" "PO-Revision-Date: 2008-05-04 15:33+0200\n" "Last-Translator: Jordi Vilà \n" "Language-Team: Catalan \n" "Language: ca\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Switch to" msgstr "" msgid "Channel" msgstr "" msgid "without" msgstr "" msgid "Teletext" msgstr "Teletext" msgid "live" msgstr "" msgid "Switch back to live" msgstr "" msgid "Tuner available" msgstr "" msgid "display current pages" msgstr "" msgid "Tuner busy" msgstr "" msgid "display cached pages" msgstr "" msgid "cached" msgstr "" msgid "Channel Tuning Successful" msgstr "" msgid "Channel Tuning Not Successful" msgstr "" msgid "No Free Tuner Found - Use Cache Only" msgstr "" msgid "*** Config mode is not supported in 24-line mode ***" msgstr "" msgid "Hotkey level change is not supported in 24-line mode" msgstr "" msgid "Hotkey levels are disabled" msgstr "" msgid "Hotkey levels are not active" msgstr "" msgid "OSD presets are disabled" msgstr "" msgid "OSD presets are not active" msgstr "" msgid "Channel (press OK): " msgstr "Canal (premi OK):" msgid "Channels" msgstr "" msgid "with" msgstr "" msgid "Page" msgstr "Pàgina" msgid "in cache" msgstr "" msgid "not found" msgstr "no trobada" msgid "please wait" msgstr "" msgid "Displays teletext on the OSD" msgstr "Visualitza el teletext en l'OSD" msgid "Zoom" msgstr "Zoom" msgid "Half page" msgstr "Mitja pàgina" msgid "Change channel" msgstr "Canvi cadena" msgid "Switch background" msgstr "Canvia el fons" msgid "Config" msgstr "" msgid "Footer Line" msgstr "" msgid "Answer" msgstr "" msgid "Pause" msgstr "" msgid "Hotkey Level+" msgstr "" msgid "Hotkey Level-" msgstr "" msgid "OSD Preset+" msgstr "" msgid "OSD Preset-" msgstr "" msgid "Jump to..." msgstr "Salta a..." msgid "Latin 1" msgstr "" msgid "Latin 2" msgstr "" msgid "Latin 3" msgstr "" msgid "Latin 4" msgstr "" msgid "Cyrillic" msgstr "" msgid "Reserved" msgstr "" msgid "Greek" msgstr "" msgid "Arabic" msgstr "" msgid "Hebrew" msgstr "" msgid "Hotkeys" msgstr "" msgid "None" msgstr "" msgid "Hotkeys+Stdkeys" msgstr "" msgid "Hide mainmenu entry" msgstr "" msgid "Show clock" msgstr "Visualitza l'hora" msgid "Auto-update pages" msgstr "Actualització pàgines automàtica" msgid "G0 code block" msgstr "" msgid "G2 code block" msgstr "" msgid "16-Color Mode" msgstr "" msgid "max" msgstr "" msgid "Presets" msgstr "" msgid "visible" msgstr "" msgid "OSD left (%)" msgstr "" msgid "OSD top (%)" msgstr "" msgid "OSD width (%)" msgstr "" msgid "OSD height (%)" msgstr "" msgid "OSD frame pixel" msgstr "" msgid "Text Font" msgstr "" msgid "Text Vertical Offset" msgstr "" msgid "Background transparency" msgstr "Transparència del fons" msgid "Key bindings" msgstr "" msgid "Levels" msgstr "" msgid "Level" msgstr "" msgid " Page number" msgstr " Nombre de pàgina" msgid "Half Page" msgstr "" msgid "ChangeChan" msgstr "" msgid "SwitchBack" msgstr "" msgid "FooterLine" msgstr "" msgid "HkLevel+" msgstr "" msgid "HkLevel-" msgstr "" msgid "Preset+" msgstr "" msgid "Preset-" msgstr "" msgid "Left" msgstr "" msgid "Top" msgstr "" msgid "Width" msgstr "" msgid "Height" msgstr "" msgid "Frame" msgstr "" msgid "TxVoffset" msgstr "" msgid "BackTrans" msgstr "" #~ msgid "OSD height" #~ msgstr "Altura OSD" #~ msgid "OSD width" #~ msgstr "Amplària OSD" vdr-plugin-osdteletext-2.3.1/po/de_DE.po000066400000000000000000000111541415701714300200710ustar00rootroot00000000000000# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Klaus Schmidinger , 2000 # msgid "" msgstr "" "Project-Id-Version: VDR 2.4.4\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-12-11 18:04+0100\n" "PO-Revision-Date: 2008-05-04 15:33+0200\n" "Last-Translator: Peter Bieringer \n" "Language-Team: German \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Switch to" msgstr "Wechsle zu" msgid "Channel" msgstr "Kanal" msgid "without" msgstr "ohne" msgid "Teletext" msgstr "Videotext" msgid "live" msgstr "aktuellem" msgid "Switch back to live" msgstr "Wechsle zurück zu laufendem" msgid "Tuner available" msgstr "Tuner frei" msgid "display current pages" msgstr "zeige aktuelle Seiten an" msgid "Tuner busy" msgstr "Tuner belegt" msgid "display cached pages" msgstr "zeige gespeicherte Seiten an" msgid "cached" msgstr "gespeicherten" msgid "Channel Tuning Successful" msgstr "Kanal erfolgreich eingestellt" msgid "Channel Tuning Not Successful" msgstr "Kanal nicht erfolgreich eingestellt" msgid "No Free Tuner Found - Use Cache Only" msgstr "Keinen freien Tuner gefunden - benutze nur gespeicherte Seiten" msgid "*** Config mode is not supported in 24-line mode ***" msgstr "*** Konfig-Modus ist im 24-Zeilen-Modus nicht unterstützt ***" msgid "Hotkey level change is not supported in 24-line mode" msgstr "Hotkey Ebenen-Änderung ist im 24-Zeilen-Modus nicht unterstützt" msgid "Hotkey levels are disabled" msgstr "Hotkey Ebenen sind deaktiviert" msgid "Hotkey levels are not active" msgstr "Hotkey Ebenen sind nicht aktiv" msgid "OSD presets are disabled" msgstr "OSD Voreinstellungen sind abgeschaltet" msgid "OSD presets are not active" msgstr "OSD Voreinstellungen sind nicht aktiv" msgid "Channel (press OK): " msgstr "Sender (OK drücken): " msgid "Channels" msgstr "Kanäle" msgid "with" msgstr "mit" msgid "Page" msgstr "Seite" msgid "in cache" msgstr "im Speicher" msgid "not found" msgstr "nicht gefunden" msgid "please wait" msgstr "bitte warten" msgid "Displays teletext on the OSD" msgstr "Zeigt den Videotext auf dem OSD an" msgid "Zoom" msgstr "Vergrößern" msgid "Half page" msgstr "Halbe Seite" msgid "Change channel" msgstr "Kanal wechseln" msgid "Switch background" msgstr "Hintergrund ändern" msgid "Config" msgstr "Konfig" msgid "Footer Line" msgstr "Fusszeile" msgid "Answer" msgstr "Antwort" msgid "Pause" msgstr "Pause" msgid "Hotkey Level+" msgstr "Hotkey Ebene+" msgid "Hotkey Level-" msgstr "Hotkey Ebene-" msgid "OSD Preset+" msgstr "OSD Preset+" msgid "OSD Preset-" msgstr "OSD Preset-" msgid "Jump to..." msgstr "Springe zu..." msgid "Latin 1" msgstr "" msgid "Latin 2" msgstr "" msgid "Latin 3" msgstr "" msgid "Latin 4" msgstr "" msgid "Cyrillic" msgstr "" msgid "Reserved" msgstr "Reserviert" msgid "Greek" msgstr "" msgid "Arabic" msgstr "" msgid "Hebrew" msgstr "" msgid "Hotkeys" msgstr "Hotkeys" msgid "None" msgstr "Keine" msgid "Hotkeys+Stdkeys" msgstr "Hotkeys+Stdkeys" msgid "Hide mainmenu entry" msgstr "Hauptmenüeintrag verstecken" msgid "Show clock" msgstr "Uhr anzeigen" msgid "Auto-update pages" msgstr "Seiten aktualisieren" msgid "G0 code block" msgstr "" msgid "G2 code block" msgstr "" msgid "16-Color Mode" msgstr "16-Farben Modus" msgid "max" msgstr "max" msgid "Presets" msgstr "Voreinstellungen" msgid "visible" msgstr "sichtbar" msgid "OSD left (%)" msgstr "OSD Links (%)" msgid "OSD top (%)" msgstr "OSD Oben (%)" msgid "OSD width (%)" msgstr "OSD Breite (%)" msgid "OSD height (%)" msgstr "OSD Höhe (%)" msgid "OSD frame pixel" msgstr "OSD Rahmen Pixel" msgid "Text Font" msgstr "Zeichensatz" msgid "Text Vertical Offset" msgstr "Text vertikaler Offset" msgid "Background transparency" msgstr "Hintergrund-Transparenz" msgid "Key bindings" msgstr "Tastenzuweisung" msgid "Levels" msgstr "Ebenen" msgid "Level" msgstr "Ebene" msgid " Page number" msgstr " Seitenzahl" msgid "Half Page" msgstr "HalbeSeite" msgid "ChangeChan" msgstr "KanalWechs" msgid "SwitchBack" msgstr "Hintergrund" msgid "FooterLine" msgstr "Fusszeile" msgid "HkLevel+" msgstr "HkEbene+" msgid "HkLevel-" msgstr "HKEbene-" msgid "Preset+" msgstr "Voreinst+" msgid "Preset-" msgstr "Voreinst-" msgid "Left" msgstr "Links" msgid "Top" msgstr "Oben" msgid "Width" msgstr "Breite" msgid "Height" msgstr "Höhe" msgid "Frame" msgstr "Rahmen" msgid "TxVoffset" msgstr "TxVoffset" msgid "BackTrans" msgstr "HintGrTra" vdr-plugin-osdteletext-2.3.1/po/es_ES.po000066400000000000000000000073401415701714300201310ustar00rootroot00000000000000# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Ruben Nunez Francisco , 2002 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-12-11 18:04+0100\n" "PO-Revision-Date: 2008-05-04 15:33+0200\n" "Last-Translator: Ruben Nunez Francisco \n" "Language-Team: Spanish \n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Switch to" msgstr "" msgid "Channel" msgstr "" msgid "without" msgstr "" msgid "Teletext" msgstr "Teletexto" msgid "live" msgstr "" msgid "Switch back to live" msgstr "" msgid "Tuner available" msgstr "" msgid "display current pages" msgstr "" msgid "Tuner busy" msgstr "" msgid "display cached pages" msgstr "" msgid "cached" msgstr "" msgid "Channel Tuning Successful" msgstr "" msgid "Channel Tuning Not Successful" msgstr "" msgid "No Free Tuner Found - Use Cache Only" msgstr "" msgid "*** Config mode is not supported in 24-line mode ***" msgstr "" msgid "Hotkey level change is not supported in 24-line mode" msgstr "" msgid "Hotkey levels are disabled" msgstr "" msgid "Hotkey levels are not active" msgstr "" msgid "OSD presets are disabled" msgstr "" msgid "OSD presets are not active" msgstr "" msgid "Channel (press OK): " msgstr "Canal (pulse OK):" msgid "Channels" msgstr "" msgid "with" msgstr "" msgid "Page" msgstr "Página" msgid "in cache" msgstr "" msgid "not found" msgstr "no encontrada" msgid "please wait" msgstr "" msgid "Displays teletext on the OSD" msgstr "Visualiza el teletexto en el OSD" msgid "Zoom" msgstr "Zoom" msgid "Half page" msgstr "Media página" msgid "Change channel" msgstr "Cambio cadena" msgid "Switch background" msgstr "Cambia el fondo" msgid "Config" msgstr "" msgid "Footer Line" msgstr "" msgid "Answer" msgstr "" msgid "Pause" msgstr "" msgid "Hotkey Level+" msgstr "" msgid "Hotkey Level-" msgstr "" msgid "OSD Preset+" msgstr "" msgid "OSD Preset-" msgstr "" msgid "Jump to..." msgstr "Salta a..." msgid "Latin 1" msgstr "" msgid "Latin 2" msgstr "" msgid "Latin 3" msgstr "" msgid "Latin 4" msgstr "" msgid "Cyrillic" msgstr "" msgid "Reserved" msgstr "" msgid "Greek" msgstr "" msgid "Arabic" msgstr "" msgid "Hebrew" msgstr "" msgid "Hotkeys" msgstr "" msgid "None" msgstr "" msgid "Hotkeys+Stdkeys" msgstr "" msgid "Hide mainmenu entry" msgstr "" msgid "Show clock" msgstr "Visualiza el reloj" msgid "Auto-update pages" msgstr "" msgid "G0 code block" msgstr "" msgid "G2 code block" msgstr "" msgid "16-Color Mode" msgstr "" msgid "max" msgstr "" msgid "Presets" msgstr "" msgid "visible" msgstr "" msgid "OSD left (%)" msgstr "" msgid "OSD top (%)" msgstr "" msgid "OSD width (%)" msgstr "" msgid "OSD height (%)" msgstr "" msgid "OSD frame pixel" msgstr "" msgid "Text Font" msgstr "" msgid "Text Vertical Offset" msgstr "" msgid "Background transparency" msgstr "Transparencia del fondo" msgid "Key bindings" msgstr "" msgid "Levels" msgstr "" msgid "Level" msgstr "" msgid " Page number" msgstr " Número de página" msgid "Half Page" msgstr "" msgid "ChangeChan" msgstr "" msgid "SwitchBack" msgstr "" msgid "FooterLine" msgstr "" msgid "HkLevel+" msgstr "" msgid "HkLevel-" msgstr "" msgid "Preset+" msgstr "" msgid "Preset-" msgstr "" msgid "Left" msgstr "" msgid "Top" msgstr "" msgid "Width" msgstr "" msgid "Height" msgstr "" msgid "Frame" msgstr "" msgid "TxVoffset" msgstr "" msgid "BackTrans" msgstr "" #~ msgid "OSD height" #~ msgstr "Altura OSD" #~ msgid "OSD width" #~ msgstr "Anchura OSD" vdr-plugin-osdteletext-2.3.1/po/fi_FI.po000066400000000000000000000077211415701714300201120ustar00rootroot00000000000000# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Rolf Ahrenberg , 2003 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-12-11 18:04+0100\n" "PO-Revision-Date: 2008-05-04 15:33+0200\n" "Last-Translator: Rolf Ahrenberg \n" "Language-Team: Finnish \n" "Language: fi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Switch to" msgstr "" msgid "Channel" msgstr "" msgid "without" msgstr "" msgid "Teletext" msgstr "Teksti-TV" msgid "live" msgstr "" msgid "Switch back to live" msgstr "" msgid "Tuner available" msgstr "" msgid "display current pages" msgstr "" msgid "Tuner busy" msgstr "" msgid "display cached pages" msgstr "" msgid "cached" msgstr "" msgid "Channel Tuning Successful" msgstr "" msgid "Channel Tuning Not Successful" msgstr "" msgid "No Free Tuner Found - Use Cache Only" msgstr "" msgid "*** Config mode is not supported in 24-line mode ***" msgstr "" msgid "Hotkey level change is not supported in 24-line mode" msgstr "" msgid "Hotkey levels are disabled" msgstr "" msgid "Hotkey levels are not active" msgstr "" msgid "OSD presets are disabled" msgstr "" msgid "OSD presets are not active" msgstr "" msgid "Channel (press OK): " msgstr "Kanava (paina OK):" msgid "Channels" msgstr "" msgid "with" msgstr "" msgid "Page" msgstr "Sivua" msgid "in cache" msgstr "" msgid "not found" msgstr "ei löydy" msgid "please wait" msgstr "" msgid "Displays teletext on the OSD" msgstr "Teksti-TV (OSD)" msgid "Zoom" msgstr "Suurenna" msgid "Half page" msgstr "Puolikas sivu" msgid "Change channel" msgstr "Vaihda kanavaa" msgid "Switch background" msgstr "Vaihda tausta" msgid "Config" msgstr "" msgid "Footer Line" msgstr "" msgid "Answer" msgstr "" msgid "Pause" msgstr "" msgid "Hotkey Level+" msgstr "" msgid "Hotkey Level-" msgstr "" msgid "OSD Preset+" msgstr "" msgid "OSD Preset-" msgstr "" msgid "Jump to..." msgstr "Siirry sivulle..." msgid "Latin 1" msgstr "Latin 1" msgid "Latin 2" msgstr "Latin 2" msgid "Latin 3" msgstr "Latin 3" msgid "Latin 4" msgstr "Latin 4" msgid "Cyrillic" msgstr "kyrillinen" msgid "Reserved" msgstr "varattu" msgid "Greek" msgstr "kreikka" msgid "Arabic" msgstr "arabia" msgid "Hebrew" msgstr "hebrea" msgid "Hotkeys" msgstr "" msgid "None" msgstr "" msgid "Hotkeys+Stdkeys" msgstr "" msgid "Hide mainmenu entry" msgstr "Piilota valinta päävalikosta" msgid "Show clock" msgstr "Näytä kello" msgid "Auto-update pages" msgstr "Automaattinen sivupäivitys" msgid "G0 code block" msgstr "G0-koodilohko" msgid "G2 code block" msgstr "G2-koodilohko" msgid "16-Color Mode" msgstr "" msgid "max" msgstr "" msgid "Presets" msgstr "" msgid "visible" msgstr "" msgid "OSD left (%)" msgstr "" msgid "OSD top (%)" msgstr "" msgid "OSD width (%)" msgstr "" msgid "OSD height (%)" msgstr "" msgid "OSD frame pixel" msgstr "" msgid "Text Font" msgstr "Käytä kirjasinta" msgid "Text Vertical Offset" msgstr "" msgid "Background transparency" msgstr "Taustan läpinäkyvyys" msgid "Key bindings" msgstr "Näppäintoiminnot" msgid "Levels" msgstr "" msgid "Level" msgstr "" msgid " Page number" msgstr " Sivunumero" msgid "Half Page" msgstr "" msgid "ChangeChan" msgstr "" msgid "SwitchBack" msgstr "" msgid "FooterLine" msgstr "" msgid "HkLevel+" msgstr "" msgid "HkLevel-" msgstr "" msgid "Preset+" msgstr "" msgid "Preset-" msgstr "" msgid "Left" msgstr "" msgid "Top" msgstr "" msgid "Width" msgstr "" msgid "Height" msgstr "" msgid "Frame" msgstr "" msgid "TxVoffset" msgstr "" msgid "BackTrans" msgstr "" #~ msgid "OSD height" #~ msgstr "Korkeus" #~ msgid "OSD width" #~ msgstr "Leveys" #~ msgid "OSD horizontal align" #~ msgstr "Pystykeskitys" #~ msgid "OSD vertical align" #~ msgstr "Vaakakeskitys" vdr-plugin-osdteletext-2.3.1/po/fr_FR.po000066400000000000000000000100101415701714300201150ustar00rootroot00000000000000# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Jean-Claude Repetto , 2001 # Olivier Jacques , 2003 # Gregoire Favre , 2003 # Nicolas Huillard , 2005 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-12-11 18:04+0100\n" "PO-Revision-Date: 2009-01-10 19:32+0100\n" "Last-Translator: Nival Michaël\n" "Language-Team: French \n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Switch to" msgstr "" msgid "Channel" msgstr "" msgid "without" msgstr "" msgid "Teletext" msgstr "Teletexte" msgid "live" msgstr "" msgid "Switch back to live" msgstr "" msgid "Tuner available" msgstr "" msgid "display current pages" msgstr "" msgid "Tuner busy" msgstr "" msgid "display cached pages" msgstr "" msgid "cached" msgstr "" msgid "Channel Tuning Successful" msgstr "" msgid "Channel Tuning Not Successful" msgstr "" msgid "No Free Tuner Found - Use Cache Only" msgstr "" msgid "*** Config mode is not supported in 24-line mode ***" msgstr "" msgid "Hotkey level change is not supported in 24-line mode" msgstr "" msgid "Hotkey levels are disabled" msgstr "" msgid "Hotkey levels are not active" msgstr "" msgid "OSD presets are disabled" msgstr "" msgid "OSD presets are not active" msgstr "" msgid "Channel (press OK): " msgstr "Chaine (Appuyer sur OK): " msgid "Channels" msgstr "" msgid "with" msgstr "" msgid "Page" msgstr "Page" msgid "in cache" msgstr "" msgid "not found" msgstr "pas trouvé" msgid "please wait" msgstr "" msgid "Displays teletext on the OSD" msgstr "Affiche le télétexte sur l'OSD" msgid "Zoom" msgstr "Zoom" msgid "Half page" msgstr "Demi-Page" msgid "Change channel" msgstr "Changer la chaîne" msgid "Switch background" msgstr "Change le fond d'écran" msgid "Config" msgstr "" msgid "Footer Line" msgstr "" msgid "Answer" msgstr "" msgid "Pause" msgstr "" msgid "Hotkey Level+" msgstr "" msgid "Hotkey Level-" msgstr "" msgid "OSD Preset+" msgstr "" msgid "OSD Preset-" msgstr "" msgid "Jump to..." msgstr "Aller à..." msgid "Latin 1" msgstr "" msgid "Latin 2" msgstr "" msgid "Latin 3" msgstr "" msgid "Latin 4" msgstr "" msgid "Cyrillic" msgstr "" msgid "Reserved" msgstr "" msgid "Greek" msgstr "" msgid "Arabic" msgstr "" msgid "Hebrew" msgstr "" msgid "Hotkeys" msgstr "" msgid "None" msgstr "" msgid "Hotkeys+Stdkeys" msgstr "" msgid "Hide mainmenu entry" msgstr "" msgid "Show clock" msgstr "Afficher l'heure" msgid "Auto-update pages" msgstr "Mise à jour des pages" msgid "G0 code block" msgstr "" msgid "G2 code block" msgstr "" msgid "16-Color Mode" msgstr "" msgid "max" msgstr "" msgid "Presets" msgstr "" msgid "visible" msgstr "" msgid "OSD left (%)" msgstr "" msgid "OSD top (%)" msgstr "" msgid "OSD width (%)" msgstr "" msgid "OSD height (%)" msgstr "" msgid "OSD frame pixel" msgstr "" msgid "Text Font" msgstr "" msgid "Text Vertical Offset" msgstr "" msgid "Background transparency" msgstr "Fond transparent" msgid "Key bindings" msgstr "Attribution des touches" msgid "Levels" msgstr "" msgid "Level" msgstr "" msgid " Page number" msgstr " Nombre de pages" msgid "Half Page" msgstr "" msgid "ChangeChan" msgstr "" msgid "SwitchBack" msgstr "" msgid "FooterLine" msgstr "" msgid "HkLevel+" msgstr "" msgid "HkLevel-" msgstr "" msgid "Preset+" msgstr "" msgid "Preset-" msgstr "" msgid "Left" msgstr "" msgid "Top" msgstr "" msgid "Width" msgstr "" msgid "Height" msgstr "" msgid "Frame" msgstr "" msgid "TxVoffset" msgstr "" msgid "BackTrans" msgstr "" #~ msgid "OSD height" #~ msgstr "Hauteur OSD" #~ msgid "OSD width" #~ msgstr "Largeur OSD" #~ msgid "OSD horizontal align" #~ msgstr "Alignement horizontal de l'OSD" #~ msgid "OSD vertical align" #~ msgstr "Alignement vertical de l'OSD" vdr-plugin-osdteletext-2.3.1/po/it_IT.po000066400000000000000000000102421415701714300201360ustar00rootroot00000000000000# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Alberto Carraro , 2001 # Antonio Ospite , 2003 # Sean Carlos , 2005 # Davide Cavalca , 2008 # Diego Pierotto , 2008 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-12-11 18:04+0100\n" "PO-Revision-Date: 2010-11-06 19:59+0100\n" "Last-Translator: Diego Pierotto \n" "Language-Team: Italian \n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: Italian\n" "X-Poedit-Country: ITALY\n" "X-Poedit-SourceCharset: utf-8\n" msgid "Switch to" msgstr "" msgid "Channel" msgstr "" msgid "without" msgstr "" msgid "Teletext" msgstr "Teletext" msgid "live" msgstr "" msgid "Switch back to live" msgstr "" msgid "Tuner available" msgstr "" msgid "display current pages" msgstr "" msgid "Tuner busy" msgstr "" msgid "display cached pages" msgstr "" msgid "cached" msgstr "" msgid "Channel Tuning Successful" msgstr "" msgid "Channel Tuning Not Successful" msgstr "" msgid "No Free Tuner Found - Use Cache Only" msgstr "" msgid "*** Config mode is not supported in 24-line mode ***" msgstr "" msgid "Hotkey level change is not supported in 24-line mode" msgstr "" msgid "Hotkey levels are disabled" msgstr "" msgid "Hotkey levels are not active" msgstr "" msgid "OSD presets are disabled" msgstr "" msgid "OSD presets are not active" msgstr "" msgid "Channel (press OK): " msgstr "Canale (premi OK): " msgid "Channels" msgstr "" msgid "with" msgstr "" msgid "Page" msgstr "Pagina" msgid "in cache" msgstr "" msgid "not found" msgstr "non trovata" msgid "please wait" msgstr "" msgid "Displays teletext on the OSD" msgstr "Mostra il teletext in OSD" msgid "Zoom" msgstr "Ingrandisci" msgid "Half page" msgstr "Metà pagina" msgid "Change channel" msgstr "Cambia canale" msgid "Switch background" msgstr "Cambia sfondo" msgid "Config" msgstr "" msgid "Footer Line" msgstr "" msgid "Answer" msgstr "" msgid "Pause" msgstr "" msgid "Hotkey Level+" msgstr "" msgid "Hotkey Level-" msgstr "" msgid "OSD Preset+" msgstr "" msgid "OSD Preset-" msgstr "" msgid "Jump to..." msgstr "Vai a..." msgid "Latin 1" msgstr "" msgid "Latin 2" msgstr "" msgid "Latin 3" msgstr "" msgid "Latin 4" msgstr "" msgid "Cyrillic" msgstr "" msgid "Reserved" msgstr "" msgid "Greek" msgstr "" msgid "Arabic" msgstr "" msgid "Hebrew" msgstr "" msgid "Hotkeys" msgstr "" msgid "None" msgstr "" msgid "Hotkeys+Stdkeys" msgstr "" msgid "Hide mainmenu entry" msgstr "Nascondi voce menu principale" msgid "Show clock" msgstr "Mostra orologio" msgid "Auto-update pages" msgstr "Aggiorn. automatico pagine" msgid "G0 code block" msgstr "" msgid "G2 code block" msgstr "" msgid "16-Color Mode" msgstr "" msgid "max" msgstr "" msgid "Presets" msgstr "" msgid "visible" msgstr "" msgid "OSD left (%)" msgstr "" msgid "OSD top (%)" msgstr "" msgid "OSD width (%)" msgstr "" msgid "OSD height (%)" msgstr "" msgid "OSD frame pixel" msgstr "" msgid "Text Font" msgstr "" msgid "Text Vertical Offset" msgstr "" msgid "Background transparency" msgstr "Trasparenza sfondo" msgid "Key bindings" msgstr "Tasti associati" msgid "Levels" msgstr "" msgid "Level" msgstr "" msgid " Page number" msgstr " Numero pagina" msgid "Half Page" msgstr "" msgid "ChangeChan" msgstr "" msgid "SwitchBack" msgstr "" msgid "FooterLine" msgstr "" msgid "HkLevel+" msgstr "" msgid "HkLevel-" msgstr "" msgid "Preset+" msgstr "" msgid "Preset-" msgstr "" msgid "Left" msgstr "" msgid "Top" msgstr "" msgid "Width" msgstr "" msgid "Height" msgstr "" msgid "Frame" msgstr "" msgid "TxVoffset" msgstr "" msgid "BackTrans" msgstr "" #~ msgid "OSD height" #~ msgstr "Altezza OSD" #~ msgid "OSD width" #~ msgstr "Larghezza OSD" #~ msgid "OSD horizontal align" #~ msgstr "Allineamento orizzontale OSD" #~ msgid "OSD vertical align" #~ msgstr "Allineamento verticale OSD" vdr-plugin-osdteletext-2.3.1/po/pt_PT.po000066400000000000000000000076001415701714300201600ustar00rootroot00000000000000# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Klaus Schmidinger , 2000 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-12-11 18:04+0100\n" "PO-Revision-Date: 2008-05-04 15:33+0200\n" "Last-Translator: Chris Silva \n" "Language-Team: Portuguese \n" "Language: pt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Switch to" msgstr "" msgid "Channel" msgstr "" msgid "without" msgstr "" msgid "Teletext" msgstr "Teletexto" msgid "live" msgstr "" msgid "Switch back to live" msgstr "" msgid "Tuner available" msgstr "" msgid "display current pages" msgstr "" msgid "Tuner busy" msgstr "" msgid "display cached pages" msgstr "" msgid "cached" msgstr "" msgid "Channel Tuning Successful" msgstr "" msgid "Channel Tuning Not Successful" msgstr "" msgid "No Free Tuner Found - Use Cache Only" msgstr "" msgid "*** Config mode is not supported in 24-line mode ***" msgstr "" msgid "Hotkey level change is not supported in 24-line mode" msgstr "" msgid "Hotkey levels are disabled" msgstr "" msgid "Hotkey levels are not active" msgstr "" msgid "OSD presets are disabled" msgstr "" msgid "OSD presets are not active" msgstr "" msgid "Channel (press OK): " msgstr "Sender (Prima OK): " msgid "Channels" msgstr "" msgid "with" msgstr "" msgid "Page" msgstr "Página" msgid "in cache" msgstr "" msgid "not found" msgstr "Não encontrado" msgid "please wait" msgstr "" msgid "Displays teletext on the OSD" msgstr "Mostra o teletexto no OSD" msgid "Zoom" msgstr "Zoom" msgid "Half page" msgstr "Meia Página" msgid "Change channel" msgstr "Mudar canal" msgid "Switch background" msgstr "Mudar fundo" msgid "Config" msgstr "" msgid "Footer Line" msgstr "" msgid "Answer" msgstr "" msgid "Pause" msgstr "" msgid "Hotkey Level+" msgstr "" msgid "Hotkey Level-" msgstr "" msgid "OSD Preset+" msgstr "" msgid "OSD Preset-" msgstr "" msgid "Jump to..." msgstr "Ir para" msgid "Latin 1" msgstr "" msgid "Latin 2" msgstr "" msgid "Latin 3" msgstr "" msgid "Latin 4" msgstr "" msgid "Cyrillic" msgstr "" msgid "Reserved" msgstr "" msgid "Greek" msgstr "" msgid "Arabic" msgstr "" msgid "Hebrew" msgstr "" msgid "Hotkeys" msgstr "" msgid "None" msgstr "" msgid "Hotkeys+Stdkeys" msgstr "" msgid "Hide mainmenu entry" msgstr "" msgid "Show clock" msgstr "Mostrar Relógio" msgid "Auto-update pages" msgstr "Auto actualizar páginas" msgid "G0 code block" msgstr "" msgid "G2 code block" msgstr "" msgid "16-Color Mode" msgstr "" msgid "max" msgstr "" msgid "Presets" msgstr "" msgid "visible" msgstr "" msgid "OSD left (%)" msgstr "" msgid "OSD top (%)" msgstr "" msgid "OSD width (%)" msgstr "" msgid "OSD height (%)" msgstr "" msgid "OSD frame pixel" msgstr "" msgid "Text Font" msgstr "" msgid "Text Vertical Offset" msgstr "" msgid "Background transparency" msgstr "Transparência do Fundo" msgid "Key bindings" msgstr "Tecla alocada" msgid "Levels" msgstr "" msgid "Level" msgstr "" msgid " Page number" msgstr " Número de Página" msgid "Half Page" msgstr "" msgid "ChangeChan" msgstr "" msgid "SwitchBack" msgstr "" msgid "FooterLine" msgstr "" msgid "HkLevel+" msgstr "" msgid "HkLevel-" msgstr "" msgid "Preset+" msgstr "" msgid "Preset-" msgstr "" msgid "Left" msgstr "" msgid "Top" msgstr "" msgid "Width" msgstr "" msgid "Height" msgstr "" msgid "Frame" msgstr "" msgid "TxVoffset" msgstr "" msgid "BackTrans" msgstr "" #~ msgid "OSD height" #~ msgstr "Altura do OSD" #~ msgid "OSD width" #~ msgstr "Largura do OSD" #~ msgid "OSD horizontal align" #~ msgstr "Alinhamento Horizontal do OSD" #~ msgid "OSD vertical align" #~ msgstr "Alinhamento Vertical do OSD" vdr-plugin-osdteletext-2.3.1/po/ru_RU.po000066400000000000000000000105511415701714300201650ustar00rootroot00000000000000# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Vyacheslav Dikonov , 2004 # Oleg Roitburd , 2008 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-12-11 18:04+0100\n" "PO-Revision-Date: 2008-12-30 13:52+0100\n" "Last-Translator: Andrey Pridvorov \n" "Language-Team: Russian \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Switch to" msgstr "" msgid "Channel" msgstr "" msgid "without" msgstr "" msgid "Teletext" msgstr "Телетекст" msgid "live" msgstr "" msgid "Switch back to live" msgstr "" msgid "Tuner available" msgstr "" msgid "display current pages" msgstr "" msgid "Tuner busy" msgstr "" msgid "display cached pages" msgstr "" msgid "cached" msgstr "" msgid "Channel Tuning Successful" msgstr "" msgid "Channel Tuning Not Successful" msgstr "" msgid "No Free Tuner Found - Use Cache Only" msgstr "" msgid "*** Config mode is not supported in 24-line mode ***" msgstr "" msgid "Hotkey level change is not supported in 24-line mode" msgstr "" msgid "Hotkey levels are disabled" msgstr "" msgid "Hotkey levels are not active" msgstr "" msgid "OSD presets are disabled" msgstr "" msgid "OSD presets are not active" msgstr "" msgid "Channel (press OK): " msgstr "Канал (Нажмите ОК)" msgid "Channels" msgstr "" msgid "with" msgstr "" msgid "Page" msgstr "Страница" msgid "in cache" msgstr "" msgid "not found" msgstr "не найдена" msgid "please wait" msgstr "" msgid "Displays teletext on the OSD" msgstr "Показ телетекста в OSD" msgid "Zoom" msgstr "увеличить" msgid "Half page" msgstr "пол-страницы" msgid "Change channel" msgstr "переключить канал" msgid "Switch background" msgstr "Переключить фон" msgid "Config" msgstr "" msgid "Footer Line" msgstr "" msgid "Answer" msgstr "" msgid "Pause" msgstr "" msgid "Hotkey Level+" msgstr "" msgid "Hotkey Level-" msgstr "" msgid "OSD Preset+" msgstr "" msgid "OSD Preset-" msgstr "" msgid "Jump to..." msgstr "перейти к..." msgid "Latin 1" msgstr "Латин. 1" msgid "Latin 2" msgstr "Латин. 2" msgid "Latin 3" msgstr "Латин. 3" msgid "Latin 4" msgstr "Латин. 4" msgid "Cyrillic" msgstr "Кириллич." msgid "Reserved" msgstr "Резерв" msgid "Greek" msgstr "Греческ." msgid "Arabic" msgstr "Арабск." msgid "Hebrew" msgstr "Иврит" msgid "Hotkeys" msgstr "" msgid "None" msgstr "" msgid "Hotkeys+Stdkeys" msgstr "" msgid "Hide mainmenu entry" msgstr "Скрыть в главном меню" msgid "Show clock" msgstr "Показывать часы" msgid "Auto-update pages" msgstr "Автообновление страниц" msgid "G0 code block" msgstr "G0 кодировка" msgid "G2 code block" msgstr "G2 кодировка" msgid "16-Color Mode" msgstr "" msgid "max" msgstr "" msgid "Presets" msgstr "" msgid "visible" msgstr "" msgid "OSD left (%)" msgstr "" msgid "OSD top (%)" msgstr "" msgid "OSD width (%)" msgstr "" msgid "OSD height (%)" msgstr "" msgid "OSD frame pixel" msgstr "" msgid "Text Font" msgstr "Шрифт" msgid "Text Vertical Offset" msgstr "" msgid "Background transparency" msgstr "Прозрачность фона" msgid "Key bindings" msgstr "Привязка кнопок" msgid "Levels" msgstr "" msgid "Level" msgstr "" msgid " Page number" msgstr " Номер страницы" msgid "Half Page" msgstr "" msgid "ChangeChan" msgstr "" msgid "SwitchBack" msgstr "" msgid "FooterLine" msgstr "" msgid "HkLevel+" msgstr "" msgid "HkLevel-" msgstr "" msgid "Preset+" msgstr "" msgid "Preset-" msgstr "" msgid "Left" msgstr "" msgid "Top" msgstr "" msgid "Width" msgstr "" msgid "Height" msgstr "" msgid "Frame" msgstr "" msgid "TxVoffset" msgstr "" msgid "BackTrans" msgstr "" #~ msgid "OSD height" #~ msgstr "Высота меню" #~ msgid "OSD width" #~ msgstr "Ширина меню" #~ msgid "OSD horizontal align" #~ msgstr "Горизонтальное положение OSD" #~ msgid "OSD vertical align" #~ msgstr "Вертикальное положение OSD" vdr-plugin-osdteletext-2.3.1/po/sk_SK.po000066400000000000000000000076631415701714300201550ustar00rootroot00000000000000# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Klaus Schmidinger , 2000 # msgid "" msgstr "" "Project-Id-Version: osdteletext-0.9.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-12-11 18:04+0100\n" "PO-Revision-Date: 2011-02-15 21:11+0100\n" "Last-Translator: Milan Hrala \n" "Language-Team: Slovak \n" "Language: sk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Switch to" msgstr "" msgid "Channel" msgstr "" msgid "without" msgstr "" msgid "Teletext" msgstr "Teletext" msgid "live" msgstr "" msgid "Switch back to live" msgstr "" msgid "Tuner available" msgstr "" msgid "display current pages" msgstr "" msgid "Tuner busy" msgstr "" msgid "display cached pages" msgstr "" msgid "cached" msgstr "" msgid "Channel Tuning Successful" msgstr "" msgid "Channel Tuning Not Successful" msgstr "" msgid "No Free Tuner Found - Use Cache Only" msgstr "" msgid "*** Config mode is not supported in 24-line mode ***" msgstr "" msgid "Hotkey level change is not supported in 24-line mode" msgstr "" msgid "Hotkey levels are disabled" msgstr "" msgid "Hotkey levels are not active" msgstr "" msgid "OSD presets are disabled" msgstr "" msgid "OSD presets are not active" msgstr "" msgid "Channel (press OK): " msgstr "Kanál (stlačte OK): " msgid "Channels" msgstr "" msgid "with" msgstr "" msgid "Page" msgstr "Strana" msgid "in cache" msgstr "" msgid "not found" msgstr "nenájdená" msgid "please wait" msgstr "" msgid "Displays teletext on the OSD" msgstr "Zobrazí teletext na OSD" msgid "Zoom" msgstr "Zväčšenie" msgid "Half page" msgstr "Polovica strany" msgid "Change channel" msgstr "Zmena kanálu" msgid "Switch background" msgstr "Prepnúť na pozadí" msgid "Config" msgstr "" msgid "Footer Line" msgstr "" msgid "Answer" msgstr "" msgid "Pause" msgstr "" msgid "Hotkey Level+" msgstr "" msgid "Hotkey Level-" msgstr "" msgid "OSD Preset+" msgstr "" msgid "OSD Preset-" msgstr "" msgid "Jump to..." msgstr "Skoč na..." msgid "Latin 1" msgstr "" msgid "Latin 2" msgstr "" msgid "Latin 3" msgstr "" msgid "Latin 4" msgstr "" msgid "Cyrillic" msgstr "" msgid "Reserved" msgstr "" msgid "Greek" msgstr "" msgid "Arabic" msgstr "" msgid "Hebrew" msgstr "" msgid "Hotkeys" msgstr "" msgid "None" msgstr "" msgid "Hotkeys+Stdkeys" msgstr "" msgid "Hide mainmenu entry" msgstr "Schovať položku v hlavnom menu" msgid "Show clock" msgstr "Zobraziť hodiny" msgid "Auto-update pages" msgstr "Aktualizácia stránok" msgid "G0 code block" msgstr "" msgid "G2 code block" msgstr "" msgid "16-Color Mode" msgstr "" msgid "max" msgstr "" msgid "Presets" msgstr "" msgid "visible" msgstr "" msgid "OSD left (%)" msgstr "" msgid "OSD top (%)" msgstr "" msgid "OSD width (%)" msgstr "" msgid "OSD height (%)" msgstr "" msgid "OSD frame pixel" msgstr "" msgid "Text Font" msgstr "" msgid "Text Vertical Offset" msgstr "" msgid "Background transparency" msgstr "Priesvitnosť pozadia" msgid "Key bindings" msgstr "Klávesové skratky" msgid "Levels" msgstr "" msgid "Level" msgstr "" msgid " Page number" msgstr " Číslo strany" msgid "Half Page" msgstr "" msgid "ChangeChan" msgstr "" msgid "SwitchBack" msgstr "" msgid "FooterLine" msgstr "" msgid "HkLevel+" msgstr "" msgid "HkLevel-" msgstr "" msgid "Preset+" msgstr "" msgid "Preset-" msgstr "" msgid "Left" msgstr "" msgid "Top" msgstr "" msgid "Width" msgstr "" msgid "Height" msgstr "" msgid "Frame" msgstr "" msgid "TxVoffset" msgstr "" msgid "BackTrans" msgstr "" #~ msgid "OSD height" #~ msgstr "OSD výška" #~ msgid "OSD width" #~ msgstr "OSD šírka" #~ msgid "OSD horizontal align" #~ msgstr "OSD vodorovné zarovnanie" #~ msgid "OSD vertical align" #~ msgstr "OSD zvyslé zarovnanie" vdr-plugin-osdteletext-2.3.1/po/uk_UA.po000066400000000000000000000102321415701714300201310ustar00rootroot00000000000000# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Yarema P. aka Knedlyk , 2008 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-12-11 18:04+0100\n" "PO-Revision-Date: 2009-05-25 20:33+0200\n" "Last-Translator: Yarema P. aka Knedlyk \n" "Language-Team: Ukrainian \n" "Language: uk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Switch to" msgstr "" msgid "Channel" msgstr "" msgid "without" msgstr "" msgid "Teletext" msgstr "Телетекст" msgid "live" msgstr "" msgid "Switch back to live" msgstr "" msgid "Tuner available" msgstr "" msgid "display current pages" msgstr "" msgid "Tuner busy" msgstr "" msgid "display cached pages" msgstr "" msgid "cached" msgstr "" msgid "Channel Tuning Successful" msgstr "" msgid "Channel Tuning Not Successful" msgstr "" msgid "No Free Tuner Found - Use Cache Only" msgstr "" msgid "*** Config mode is not supported in 24-line mode ***" msgstr "" msgid "Hotkey level change is not supported in 24-line mode" msgstr "" msgid "Hotkey levels are disabled" msgstr "" msgid "Hotkey levels are not active" msgstr "" msgid "OSD presets are disabled" msgstr "" msgid "OSD presets are not active" msgstr "" msgid "Channel (press OK): " msgstr "Канал (натисніть ОК): " msgid "Channels" msgstr "" msgid "with" msgstr "" msgid "Page" msgstr "Сторінка" msgid "in cache" msgstr "" msgid "not found" msgstr "не знайдена" msgid "please wait" msgstr "" msgid "Displays teletext on the OSD" msgstr "Показувати телетекст в меню" msgid "Zoom" msgstr "Збільшити" msgid "Half page" msgstr "Пів сторінки" msgid "Change channel" msgstr "Змінити канал" msgid "Switch background" msgstr "Переключити фон" msgid "Config" msgstr "" msgid "Footer Line" msgstr "" msgid "Answer" msgstr "" msgid "Pause" msgstr "" msgid "Hotkey Level+" msgstr "" msgid "Hotkey Level-" msgstr "" msgid "OSD Preset+" msgstr "" msgid "OSD Preset-" msgstr "" msgid "Jump to..." msgstr "Перейти до..." msgid "Latin 1" msgstr "" msgid "Latin 2" msgstr "" msgid "Latin 3" msgstr "" msgid "Latin 4" msgstr "" msgid "Cyrillic" msgstr "" msgid "Reserved" msgstr "" msgid "Greek" msgstr "" msgid "Arabic" msgstr "" msgid "Hebrew" msgstr "" msgid "Hotkeys" msgstr "" msgid "None" msgstr "" msgid "Hotkeys+Stdkeys" msgstr "" msgid "Hide mainmenu entry" msgstr "" msgid "Show clock" msgstr "Показувати годинник" msgid "Auto-update pages" msgstr "Автооновлення сторінок" msgid "G0 code block" msgstr "" msgid "G2 code block" msgstr "" msgid "16-Color Mode" msgstr "" msgid "max" msgstr "" msgid "Presets" msgstr "" msgid "visible" msgstr "" msgid "OSD left (%)" msgstr "" msgid "OSD top (%)" msgstr "" msgid "OSD width (%)" msgstr "" msgid "OSD height (%)" msgstr "" msgid "OSD frame pixel" msgstr "" msgid "Text Font" msgstr "" msgid "Text Vertical Offset" msgstr "" msgid "Background transparency" msgstr "Ступінь прозорості фону" msgid "Key bindings" msgstr "Призначення клавіш" msgid "Levels" msgstr "" msgid "Level" msgstr "" msgid " Page number" msgstr " Номер сторінки" msgid "Half Page" msgstr "" msgid "ChangeChan" msgstr "" msgid "SwitchBack" msgstr "" msgid "FooterLine" msgstr "" msgid "HkLevel+" msgstr "" msgid "HkLevel-" msgstr "" msgid "Preset+" msgstr "" msgid "Preset-" msgstr "" msgid "Left" msgstr "" msgid "Top" msgstr "" msgid "Width" msgstr "" msgid "Height" msgstr "" msgid "Frame" msgstr "" msgid "TxVoffset" msgstr "" msgid "BackTrans" msgstr "" #~ msgid "OSD height" #~ msgstr "Висота OSD" #~ msgid "OSD width" #~ msgstr "Ширина OSD" #~ msgid "OSD horizontal align" #~ msgstr "Горизонтальне положення OSD" #~ msgid "OSD vertical align" #~ msgstr "Вертикальне положення OSD" vdr-plugin-osdteletext-2.3.1/rootdir.c000066400000000000000000000015721415701714300200040ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) 2003,2004 by Marcel Wiesweg * * * * 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 "rootdir.h" const char *RootDir::root = "/var/cache/vdr/vtx"; void RootDir::setRootDir(const char *newRoot) { root=newRoot; } const char *RootDir::getRootDir() { return root; } vdr-plugin-osdteletext-2.3.1/rootdir.h000066400000000000000000000015671415701714300200150ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) 2003,2004 by Marcel Wiesweg * * * * 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 __ROOTDIR_H #define __ROOTDIR_H class RootDir { public: static void setRootDir(const char *); static const char *getRootDir(); protected: static const char *root; }; #endif vdr-plugin-osdteletext-2.3.1/setup.c000066400000000000000000000031301415701714300174520ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) < 2021 by TODO * * Copyright (c) 2021 by Peter Bieringer (extenions) * * * * 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 "setup.h" const char *st_modesHotkey[] = { // 1:1 relation between st_modes[] in osdteletext.c + eTeletextAction in setup.h + st_modesHotkey in setup.c // maximum 10 chars used in line25 hotkey // trNOOP("Zoom"), trNOOP("Half Page"), trNOOP("ChangeChan"), trNOOP("SwitchBack"), trNOOP("Config"), trNOOP("FooterLine"), trNOOP("Answer"), trNOOP("Pause"), trNOOP("HkLevel+"), trNOOP("HkLevel-"), trNOOP("Preset+"), trNOOP("Preset-"), trNOOP("Jump to...") // has to stay always the last one }; const char *config_modes[] = { // maximum 9 chars, 10th is -/+ trNOOP("Left"), trNOOP("Top"), trNOOP("Width"), trNOOP("Height"), trNOOP("Frame"), trNOOP("Text Font"), trNOOP("TxVoffset"), trNOOP("BackTrans"), }; // vim: ts=3 sw=3 et vdr-plugin-osdteletext-2.3.1/setup.h000066400000000000000000000116221415701714300174640ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) < 2021 by TODO * * Copyright (c) 2021 by Peter Bieringer (extenions) * * * * 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 __SETUP_H #define __SETUP_H #include // max for setup #define HOTKEY_LEVEL_MAX_LIMIT 9 // maximum supported by SetupStore parser: 9, required minimum: 1 #define HOTKEY_LEVEL_MAX_LIMIT_STRING "9" // as string to be displayed in online help #define OSD_PRESET_MAX_LIMIT 9 // maximum supported by SetupStore parser: 9, required minimum: 1 #define OSD_PRESET_MAX_LIMIT_STRING "9" // as string to be displayed in online help // min/max for setup #define OSDleftPctMin 0 #define OSDleftPctMax 90 #define OSDtopPctMin 0 #define OSDtopPctMax 90 #define OSDwidthPctMin 10 #define OSDwidthPctMax 100 #define OSDheightPctMin 10 #define OSDheightPctMax 100 #define OSDframePixMin 0 #define OSDframePixMax 100 #define txtVoffsetMin -10 #define txtVoffsetMax +10 #define BackTransMin 0 #define BackTransMax 255 // There are two places to be kept in sync with these enums: // TeletextBrowser::TranslateKey and // 1:1 relation between st_modes[] in osdteletext.c + eTeletextAction in setup.h + st_modesHotkey in setup.c enum eTeletextAction { Zoom, HalfPage, SwitchChannel, DarkScreen, Config, LineMode24, ToggleConceal, TogglePause, HotkeyLevelPlus, HotkeyLevelMinus, OsdPresetPlus, OsdPresetMinus, LastAction // has to stay always as the last one (special flag for 'jump to pages') }; //and 100-899 => jump to page enum eTeletextActionConfig { Left, Top, Width, Height, Frame, Font, Voffset, BackTrans, LastActionConfig, // has to stay always the last one }; enum eTeletextActionValueType { Pct, Pix, Int, Str, None, }; // values stored in setup.c: extern const char *st_modesHotkey[]; extern const char *config_modes[]; enum ActionKeys { // keep in sync: static const ActionKeyName st_actionKeyNames in osdteletext.c ActionKeyFastRew, ActionKeyFastFwd, ActionKeyStop, ActionKeyOk, ActionKeyPlay, LastActionKey }; enum ActionHotkeys { // keep in sync: static const ActionKeyName st_actionHotkeyNames in osdteletext.c ActionHotkeyRed, ActionHotkeyGreen, ActionHotkeyYellow, ActionHotkeyBlue, LastActionHotkey }; enum HotkeyFlag { HotkeyNormal, HotkeyYellowValue, HotkeyGreenYellowValue }; enum InfoLineFlag { InfoLine1, InfoLine2 }; enum HintLinesMode { HintLinesHotkeys = 0, HintLinesNone = 1, HintLinesHotkeysAndStdkeys = 2 }; //Default values are set in menu.c, setup menu, parsing and storing can be found in osdteletext.c class TeletextSetup { public: TeletextSetup(); bool migrationFlag_2_2; int osdConfig[(int) eTeletextActionConfig::LastActionConfig][OSD_PRESET_MAX_LIMIT]; int mapKeyToAction[(int) ActionKeys::LastActionKey]; // see enum ActionKeys int mapHotkeyToAction[(int) ActionHotkeys::LastActionHotkey][HOTKEY_LEVEL_MAX_LIMIT]; // see enum ActionHotkeys and HotkeyLevelMax int configuredClrBackground; // legacy TODO remove >= 2.3.0 int showClock; int autoUpdatePage; int osdPresetMax; int hotkeyLevelMax; int HideMainMenu; cStringList txtFontNames; int txtG0Block; int txtG2Block; const char *txtBlock[11]; // see osdteletext.c int colorMode4bpp; int lineMode24; const char *lineMode[3]; // see osdteletext.c // current value of osdPreset int osdPreset; }; // shortcut to OSD config value of current preset #define TTSETUPPRESET(type) ttSetup.osdConfig[type][ttSetup.osdPreset] // shortcut to OSD config value of current preset converted to TCOLOR value incl. negate #define TTSETUPPRESET_TCOLOR(type) ((tColor) (((uint32_t) (255 - (ttSetup.osdConfig[type][ttSetup.osdPreset] & 0xff))) << 24)) // shortcut to OSD config value of current preset converted to font name #define TTSETUPPRESET_FONTNAME(type) ttSetup.txtFontNames[TTSETUPPRESET(type)] // Teletext display lines // ttSetup.lineMode24 == HintLinesHotkeys : 25 // ttSetup.lineMode24 == HintLinesNone : 24 // ttSetup.lineMode24 == (others) : 27 #define TT_DISPLAY_LINES ((ttSetup.lineMode24 == HintLinesNone) ? 24 : ((ttSetup.lineMode24 == HintLinesHotkeys) ? 25 : 27)) extern TeletextSetup ttSetup; #endif // vim: ts=3 sw=3 et vdr-plugin-osdteletext-2.3.1/storage.c000066400000000000000000000111741415701714300177650ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) 2003,2004 by Marcel Wiesweg * * * * 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 "storage.h" int Storage::doCleanUp() { DIR *top=opendir(root); int pagesDeleted=0; if (top) { struct dirent *chandir; struct stat chandirstat; char fullPath[PATH_MAX]; while ((chandir = readdir(top)) != NULL) { if (strcmp(chandir->d_name, "..")==0 || strcmp(chandir->d_name, ".")==0) continue; snprintf(fullPath, PATH_MAX, "%s/%s", root, chandir->d_name); if (stat(fullPath, &chandirstat)==0) { if (S_ISDIR(chandirstat.st_mode)) { pagesDeleted+=cleanSubDir(fullPath); } } } closedir(top); } else { esyslog("osdteletext: Error opening teletext storage directory \"%s\": %s", root, strerror(errno)); } return pagesDeleted; } int Storage::cleanSubDir(const char *dir) { static bool reportedError=false; //avoid filling up syslog DIR *d=opendir(dir); bool hadError=false; int bytesDeleted=0; if (d) { struct dirent *txtfile; struct stat txtfilestat; char fullPath[PATH_MAX]; int filesize; while ((txtfile = readdir(d)) != NULL) { int len=strlen(txtfile->d_name); //check that the file end with .vtx5 to avoid accidents and disasters if (strcmp(txtfile->d_name+len-5, ".vtx5")==0) { snprintf(fullPath, PATH_MAX, "%s/%s", dir, txtfile->d_name); stat(fullPath, &txtfilestat); filesize=actualFileSize(txtfilestat.st_size); int ret=unlink(fullPath); if (ret==0) bytesDeleted+=filesize; else hadError=ret; } } closedir(d); rmdir(dir); } else { if (!reportedError) { esyslog("osdteletext: Error opening teletext storage subdirectory \"%s\": %s", dir, strerror(errno)); reportedError=true; } } if (hadError && !reportedError) { esyslog("osdteletext: Error removing teletext storage subdirectory \"%s\": %s", dir, strerror(hadError)); reportedError=true; } return bytesDeleted; } Storage::Storage() : byteCount(0), failedFreeSpace(false) { } Storage::~Storage() { } void Storage::freeSpace() { //there might be a situation where only the current directory is left and //occupies the whole space. We cannot delete anything. Don't waste time scanning. if (failedFreeSpace) return; //printf("freeSpace()\n"); time_t min=time(0); char minDir[PATH_MAX]; char fullPath[PATH_MAX]; DIR *top=opendir(getRootDir()); if (top) { int haveDir=0; struct dirent *chandir; struct stat chandirstat; while ((chandir = readdir(top)) != NULL) { if (strcmp(chandir->d_name, "..")==0 || strcmp(chandir->d_name, ".")==0) continue; snprintf(fullPath, PATH_MAX, "%s/%s", getRootDir(), chandir->d_name); if (stat(fullPath, &chandirstat)==0) { if (S_ISDIR(chandirstat.st_mode)) { if (chandirstat.st_ctime < min && strcmp(fullPath, currentDir)) { min=chandirstat.st_ctime; strcpy(minDir, fullPath); haveDir++; } } } } closedir(top); //if haveDir, only current directory present, which must not be deleted if (haveDir>=2) byteCount-=cleanSubDir(minDir); else failedFreeSpace=true; } } bool Storage::exists(const char* file) { struct stat s; return (stat(file, &s)==0); } void Storage::getFilename(char *buffer, int bufLength, PageID page) { snprintf(buffer, bufLength, "%s/%s/%03x_%02x.vtx5", getRootDir(), *page.channel.ToString(), page.page, page.subPage); } void Storage::prepareDirectory(tChannelID chan) { currentDir = cString::sprintf("%s/%s", root, *chan.ToString()); if (!MakeDirs(currentDir, 1)) { esyslog("osdteletext: Error preparing directory for channel \"%s\"", *chan.ToString()); return; } failedFreeSpace=false; } vdr-plugin-osdteletext-2.3.1/storage.h000066400000000000000000000060241415701714300177700ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) 2003,2004 by Marcel Wiesweg * * Copyright (c) 2021 by Peter Bieringer (extenions) * * * * 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 __STORAGE_H #define __STORAGE_H #include "rootdir.h" #include "pageid.h" #define TELETEXT_PAGESIZE sizeof(TelePageData) struct StorageHandle { public: StorageHandle() { handle=-1; } StorageHandle(const StorageHandle &s) { handle=s.handle; } StorageHandle(int h) { handle=h; } StorageHandle &operator=(int h) { handle=h; return *this; } StorageHandle &operator=(const StorageHandle &s) { handle=s.handle; return *this; } operator bool() const { return handle!=-1; } operator int() const { return handle; } private: int handle; }; struct TelePageData { unsigned char pageheader[12]; // 12 chars (extracted from 8 chars of line X/0) unsigned char pagebuf[25*40]; // 25 lines with 40 chars X/0-24 unsigned char pagebuf_X25[40]; // 1 line with 40 chars (since 2.0.0 / VTX5) unsigned char pagebuf_X26[16*40]; // max 16 lines with 40 chars (since 2.0.0 / VTX5) unsigned char pagebuf_X27[16*40]; // max 16 lines with 40 chars (since 2.0.0 / VTX5) unsigned char pagebuf_X28[16*40]; // max 16 lines with 40 chars (since 2.0.0 / VTX5) unsigned char pagebuf_M29[16*40]; // max 16 lines with 40 chars (since 2.0.0 / VTX5) }; enum StorageSystem { StorageSystemLegacy, StorageSystemPacked }; class Storage : public RootDir { public: virtual ~Storage(); enum StorageSystem { StorageSystemLegacy, StorageSystemPacked }; //must be called before the first call to instance() //must be called before operation starts. Set all options (RootDir, maxStorage) before. virtual void cleanUp() = 0; virtual void getFilename(char *buffer, int bufLength, PageID page); virtual void prepareDirectory(tChannelID chan); virtual StorageHandle openForWriting(PageID page) = 0; virtual StorageHandle openForReading(PageID page, bool countAsAccess) = 0; virtual ssize_t write(const void *ptr, size_t size, StorageHandle stream) = 0; virtual ssize_t read(void *ptr, size_t size, StorageHandle stream) = 0; virtual void close(StorageHandle stream) = 0; protected: Storage(); int cleanSubDir(const char *dir); int doCleanUp(); virtual int actualFileSize(int netFileSize) { return netFileSize; } void freeSpace(); bool exists(const char* file); long byteCount; cString currentDir; private: bool failedFreeSpace; }; #endif vdr-plugin-osdteletext-2.3.1/tables.h000066400000000000000000000102161415701714300175740ustar00rootroot00000000000000/* This file is copied from Ralph Metzler's vbidecode package. -*- c++ -*- */ /* tables.h - some data conversion tables for vbidecode */ #ifndef _TABLES_H #define _TABLES_H unsigned char invtab[256] = { 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, }; unsigned char unhamtab[256] = { 0x01, 0xff, 0x81, 0x01, 0xff, 0x00, 0x01, 0xff, 0xff, 0x02, 0x01, 0xff, 0x0a, 0xff, 0xff, 0x07, 0xff, 0x00, 0x01, 0xff, 0x00, 0x80, 0xff, 0x00, 0x06, 0xff, 0xff, 0x0b, 0xff, 0x00, 0x03, 0xff, 0xff, 0x0c, 0x01, 0xff, 0x04, 0xff, 0xff, 0x07, 0x06, 0xff, 0xff, 0x07, 0xff, 0x07, 0x07, 0x87, 0x06, 0xff, 0xff, 0x05, 0xff, 0x00, 0x0d, 0xff, 0x86, 0x06, 0x06, 0xff, 0x06, 0xff, 0xff, 0x07, 0xff, 0x02, 0x01, 0xff, 0x04, 0xff, 0xff, 0x09, 0x02, 0x82, 0xff, 0x02, 0xff, 0x02, 0x03, 0xff, 0x08, 0xff, 0xff, 0x05, 0xff, 0x00, 0x03, 0xff, 0xff, 0x02, 0x03, 0xff, 0x03, 0xff, 0x83, 0x03, 0x04, 0xff, 0xff, 0x05, 0x84, 0x04, 0x04, 0xff, 0xff, 0x02, 0x0f, 0xff, 0x04, 0xff, 0xff, 0x07, 0xff, 0x05, 0x05, 0x85, 0x04, 0xff, 0xff, 0x05, 0x06, 0xff, 0xff, 0x05, 0xff, 0x0e, 0x03, 0xff, 0xff, 0x0c, 0x01, 0xff, 0x0a, 0xff, 0xff, 0x09, 0x0a, 0xff, 0xff, 0x0b, 0x8a, 0x0a, 0x0a, 0xff, 0x08, 0xff, 0xff, 0x0b, 0xff, 0x00, 0x0d, 0xff, 0xff, 0x0b, 0x0b, 0x8b, 0x0a, 0xff, 0xff, 0x0b, 0x0c, 0x8c, 0xff, 0x0c, 0xff, 0x0c, 0x0d, 0xff, 0xff, 0x0c, 0x0f, 0xff, 0x0a, 0xff, 0xff, 0x07, 0xff, 0x0c, 0x0d, 0xff, 0x0d, 0xff, 0x8d, 0x0d, 0x06, 0xff, 0xff, 0x0b, 0xff, 0x0e, 0x0d, 0xff, 0x08, 0xff, 0xff, 0x09, 0xff, 0x09, 0x09, 0x89, 0xff, 0x02, 0x0f, 0xff, 0x0a, 0xff, 0xff, 0x09, 0x88, 0x08, 0x08, 0xff, 0x08, 0xff, 0xff, 0x09, 0x08, 0xff, 0xff, 0x0b, 0xff, 0x0e, 0x03, 0xff, 0xff, 0x0c, 0x0f, 0xff, 0x04, 0xff, 0xff, 0x09, 0x0f, 0xff, 0x8f, 0x0f, 0xff, 0x0e, 0x0f, 0xff, 0x08, 0xff, 0xff, 0x05, 0xff, 0x0e, 0x0d, 0xff, 0xff, 0x0e, 0x0f, 0xff, 0x0e, 0x8e, 0xff, 0x0e, }; unsigned char cct2vtx_table[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0xef, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f }; #endif vdr-plugin-osdteletext-2.3.1/teletext2.ttf000066400000000000000000003077741415701714300206320ustar00rootroot00000000000000 PFFTM[OS/2X`cmapj 6cvt !yPgaspglyfL0@Hheadch6hhea$hmtxn ^locagutT Xmaxp8 name_([postt]18_<ַZַZ8X  8ZXXx@.X1 *@:PfEd  8Z  X!XXd2222dddddddddddddddd2d22ddddddddddd22ddddd2d22d2ddd22ddddddddd2dddddddd222ddd2dddd2d2dd2dd2222d222ddddddd2ddddd2ddddddddddd2dd2222222ddddddddddddd2ddddd2d2d2d2dddddddddd2dddddddddddddddddddd22ddd22ddddddddddddddd2dddddddd22dddddddddddddd2d2d2ddddddddddddd22dddddddddddd2d2d22222222222222222222222ddd222d22d2d2222dd2ddd2d2222d22ddd2ddd22d2dd2ddd2d2d22d222dddddd2ddd2222d2dd2ddd2dddddd22dddddddddd222dd2dddddddd222ddddd22222d2222^22222d22222dd222222222ddd2dddd2dd2d222222d2d22d2d22d2d2,,,,,,,,,,,,,,2d^d,2,22dddd,,,,,,,,,,,,,,2ddd2d^d,2,2d22d2d222222222dddd22^d,2,^2,,,,2d^d,2,22ddd22^d,2,^2d22d2d222222222dddd2d22222222222222d2d22d2dd,2222dd2d22d22222dd222d2d2222dd222,2d22222,@@)Q_     0 !"!&!^!&j?_ )Qp     0 !"!&![!&j_wwE5A@?=+<9iJ   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`absefjyql^wkthxm}don~cUYZWX;z[HSrOPQ{TRI!y****<Z@Rp*FX~2Z*Z<Tj8`"V *Jh   6 T v  & @ ` ~  > \ | * T |  @ r 4Pb|b:f>l,Pr@l ,PrBp*Lt.Pp8f HnDl<l:f Bn<jHp . T z !!2!N!b!!!!","V"v"""""##,#F#f###$$($V$~$$$% %.%V%%%&&&&P&t&&&''D'n'''((L(z(((()):)b))))**B*n***++4+h+++,$,L,t,,,--6-f---...".4.D.R.b.v...........................///8/T/p/p////0$0P0v000011@1V111122:2V2t2t22233B3f33344F4n4445505X5t555566F6f6666777>7R7l77788(8L8r88889 909H9v9999: :0:N:|:::;;4;V;f;;;;<<@>0>R>j>>>??,?N?^?|???@@6@V@n@@@@@AA&APAzAAAAABB:BTBvBBBC C2CLCnCCCCDD(DJDtDDDEE0ELE^EtEEEEEEEFF$FJFZFlFFFFGG,GJGZGvGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGHHHHH(H6HJH^HpHHHII.ITIIJ JRJJJJKKxZxtxxxxxytyyyyyzzz(zBz\zvzzzzzz{{{H{{||(|B|\|||||}}0}H}r}}}~~6~p~~~~$J^r,BVrҀ$6H`xā*nډ0Dbʊڊ 2H`zʋދ,L\lŒތ$>Xr̍0NNNNf:z*8Djؐ&Jx֒,RfBdƓ6TȔ"HܕBnƖ"^Ι(Hn.Dhƛ2dddd2dddddddddddd&!##33#!5!5#53535!d22222p^22dddddddddd&3####3533##5!53535353,d2222d22d2222dddddddddddd&!!!3#!5#533!d,222dddddddd,d&3##33#!5#3535335d222222222dddddd,ddd&!######53535353535!d22222d22222dddddddddddd&!3#3#!5#535#5;3535^222222222dddddd&!3#####53535#5#5;35^22222d22222ddddddddd,3#3#ddddd, 3#3##53ddd2d2dddd&3###333#5#5#5#535353dddddddddddddddddddddddddd!!!!dppddd23333####5353535#5#5#2dddddddddddddddddddddddddd!3###53535##533#,22ddd2d2dddddddddd d2&!!3#5#53535##3!!5#5#35335^22222,2222dd ddddpddddd2&3333#5!#3535;##!5#5#5222dd222222,22dddpddddddddd& !3#3#!3535d2222pddddXd&!3#5##3353#!5#5#353,2d22d22222dddddddddd,dd& !33##!353#5d^2222d22ddddX d,dd& !!3#!!d^>dddd& !!3##ddddd&!3#5#35#53#!5#3^2dd222ddd dddd& 333###ddddd,D,d !#3!53#dpd ddd& 3#!5#533d22dddddd&33535353###333#5#5#5##dd22dd2dd2dd22ddddddddddddddd&3!!dd^>d2&3335353####5#5##22d2d22d22dddddDdddd 2&3333333#5#5#5#5#5##222222d22222ddddddDddddd d& !3#!5#;3^22222d dd d& !3#!#35d22ddddXd8&!3##3#5#5#5#;3533^222d2222dd2d dddddd ddd&!3##33#5#5#5##35d22222d22ddddddddddXd&!3#5#!3#!5#5335!5#53^2d,222d22ddddddddd2&!###2ddXd& 333#!5#ddd22Xdd2&3333535353#####5#5#5#5#2d22d22d2222d2222dddddddd2&335353333##5#5###5#2d22d22d2d2d2d2 dd ddddd+3335353###333#5#5###5353535#5#5#dd2d2d222222d2d2d222222ddddddddddddddddddddd2&3333535353######5#5#5#2d22d22d2222d2222dddddddddd,dddd!#####3!53535353535#d22222p22222ddddddddddddd 3#3#dd dDdd3333333#5#5#5#5#5#5#dd222222d222222ddddddddddddd^ 3#53#dd |dd333#5#5###5353Ȗ22d222d22ddddddddd2&3!!2 d 333#5#5#d22d22ddddd2&!33!5#535!5!35d^22>22,2ddddddddd& 33533#!#3dd222p2dddd,d&!3#5#!!5#3^2d^p22ddddd,d& 3!5#3533#35#5dp2222Dd,dddd& !3!!!5#;35^2,222dddd,ddd33#5#3###53532ddddddd2dddd,dd&3353#!5!5!5#5;35#52d2,2222dd ddddddd&33533####dd22d2dddpd 3#33!53#dd2dd2ddpdd,d&3#3#!5#533#ddd22dddd ddddd&335353##33#5#5##dd2dddd2dpddddddddd 33!53#ddddd2&33533#####222ddddddddpppd&33533####dd22d2ddddpdd& !3#!5#;3^22222ddd,,d&33533##5###33dd2222d22dddddddd,d&3353#5##5#;3535#52dd222222dddd,dddd&33533#5###dd22d2dddddddd&!!!3#!5!5!5#53^,22,22dddddddddd&33#353##5##53dd22ddddddd,dd&33533#5##5#dd2dd22pd, ddd2&3333535353#####5#5#5#5#2d22d22d2222d2222ddddddddddddddd2&33333533###5##5#5#2d22d22d22ddd22d,d,dddddd2&#3335353##33#5#5###53535#5#22d2d22d2d2d22ddddddddddddddddddd&!3333535353######535#5#5#dd22222d22222d222dddddddddddddddd&!###3!5353535#dd2d>d2dddddddddd 3##33#5##533,d22d2222 dddd,d,^3#ddD 333###5335##2222d22d dddd,d,d&3353##5##53dd2dd2ddddddd^3#3#dddddd 28&333#5#3##5#5#3533d2ddd22ddddddd,dd,d&%!3#5#33#3353##5##535#535#53,2d2dd2dd2ddddd22ddddddddddddddddddX3353#3#3#5##535#535#35ddd2222dd2222dXddddddddddddd3335353###3##5#535#5#5#dd2d2d222ddddd222ddddddddddddd^3#3#dddddd #'!3#5#33#3#!5#5335#5#535#5335,2d22222d22222 ddddddddddddddd 3#73#dddd ddd2X 3!33##!5#5#3531#3!53#533#5#353##5#3^2222222222^22222222 dd dddddd ddddddddddd,d&!33!5#53535#35!!,22p222>ddddddddd2dX'3##33#5#5#535373##33#5#5#5353d2222d2222d2222d2222Xdddddddddddddddddddd!#5!dddd,!!dpd2X -1!33##!5#5#3531#3!53#533#3#5##35^2222222222^22222d22 dd dddddd ddddddddd !!^ dd 33##5#5;3522222ddddddddd 33##5#53!!ddpddpd2^33##3!5353535#2222222ddddddddd2,33#3##535#535#22222Ȗddddddddddd3##53,d2d2ddd283333#5###2dd2d2dppddd28X!#####5#5;35d2ddd222dD d,^3#ddd8^;#53d2d^3##53dd22 ,d& !3#!5#;3!!,22222pddd,, dddX'333###53535#5#7333###53535#5#dd2222d2222d2222d2222Xddddddddddddddddddd2X%17335353535353########53535##3#5#5353531#3522222222222222222d2d2222d dddddddddddddddd dddddd2X5335353535353##33##3#5353535#####53535##222222222222d222222222d2 dddddddddddddddddddddddd2&+9=33#3535353##3#5#5###53535#535#535###35335#53#222d22222d22222dd,2222d2222ddddddddd dddddddddddddddddddd3#3##353#!5#5353dddd2d222ddddddddddd& 33333#5##353535##35#5d2d22dd2222222 ddddpdddddddd& 3#333#5##3535353#35#5^d2222dd22d2d22 ddddpdddddddd& 33#5##53!3#5##;352d2d2d^2dd22 ddddddpddd& 3353##5##53!3#5##;35dd2dd2^2dd22 ddddddddpddd& 3#73#333#5##35;#35#5dddd22dd22222 ddddddpdddddd& #33#33#5##3535#5;35#35#52222dd2222222 ddddpddddddddd2&!#3#3!##35;#35Ȗdd2222dddd,dddd8&#!3#5##3353####535#5#5#353,2d22d2d2d2d2222dddddddddddddd,dd& 333!3#!!35#d2^>2 ddddddXdd& 3#3!3#!!353^d2^>2 ddddddXdd& 333!3#!!35;352d^>d222 ddddddXdddd& 3#73#!!3#!!dddd^> dddddddd 333#3!53#535#d2dddddd2 dddpdddd 3#3#3!53#5353,d2dddddd2 dddpdddd 33#5##53!#3!53#2ddd22,dddd dddddddd, 3#73#!#3!53#dddd,dddd dddddpdd2&!33##!#5373#353#5d^222222ddd22dddd,ddd,dd& %3353#3#5#5#5#5##;33333#5dd222222d2222222 ddddddddpddddddd& 3333#!5#3535#3d22222d2 dddpddddpd& 3#33#!5#353533^d2d22222 dddpddddpd& 3333#!5#3535;3532222222222 dddpddddddpd& 3353#3#!5#35#5;353dd22222222dd dddpddddddpd& 3#73#!3#!5#;3dddd^22222 dddddpddp3353##33#5##53535#5#ddd2222ddd2222dddddddddddddd&#3#3#!#535#35!353535##3d222d222,222222ddpddddddddddddd,d& 33#5#333#!5#d2d2dd22 dddd  ddd& 3##53333#!5#,d2d2dd22 dddd  ddd& 333#!5#35;#3#52d22d22dd dd dddd dd& 3#73#333#!5#dddddd22 dddd  dd2& '3##53#3333535353######5#5#5#,d2d2d22d22d2222d2222 ddddddddddddd,dddd& 3#33##3#53#35d222222 dddddddXd&33#3##535#535###35322d2Ȗd22d22ddddddXd2& 33#5#!33!5#535!5!35d2d2d^22>22,2 ddddddddddd2& 3##53!33!5#535!5!35,d2d2^22>22,2 ddddddddddd2& 33#5##53!33!5#535!5!35Ȗ2d2d2d^22>22,2 ddddddddddddd2& #3353##5##53!33!5#535!5!35dd2dd22^22>22,2 ddddddddddddddd2& 3#73#!33!5#535!5!35dddd^22>22,2 ddddddddddd2& #33#333!5#535!5!535#5;353522222>22,d222d dddddddddddddd dd2&33533#3!5#53535#33535d22Ȗp22dddddddddddddddd8&!3#5#!###535#5#3^2d^2d2d22ddddddddd,d& 33#5#!3!!!5#;35d2d2d^2,222 ddddddd,ddd& 3##53!3!!!5#;35,d2d2^2,222 ddddddd,ddd& 33#5##53!3!!!5#;352d2d2d^2,222 ddddddddd,ddd& 3#73#!3!!!5#;35dddd^2,222 ddddddd,dd 33#5#33!53#d2d2dd2 dddpdd, 3##5333!53#,d2d2ddd2 dddpdd, 33#5##5333!53#2d2d22dd2 dddddpdd, 3#73#33!53#dddddd2 dddpdd,dX 33#3!5#3535#533^dd2p22d ddd d,ddd,d& 3353##5##5333533####dd2dd22d22d2d ddddddddddpdd& 33#5#!3#!5#;3d2d22^22222 dddddd,,d& 3##53!3#!5#;3^d2d2^22222 dddddd,,d& 33#5##53!3#!5#;32d2d2d^22222 dddddddd,,d& 3353##5##53!3#!5#;3dd2dd2^22222 dddddddddd,,d& 3#73#!3#!5#;3dddd^22222 dddddd,,d 3#!!3#ddpddddddd2&X#333###5#5#3533535353##3^d222d222222d22Xdddddd,dddddddd,d& 33#5#33533#5##5#d2d2d2dd22 dddpd, dddd& 3##5333533#5##5#,d2d2d2dd22 dddpd, dddd& 33#5##5333533#5##5#2d2d2d2dd22 dddddpd, dddd& 3#73#33533#5##5#ddddd2dd22 dddpd, dddd& )3##533333535353######535#5#5#^d2d2d22222d22222d222 dddddddddddddddddd8& 333###3d22ddddX,2 )3#73#3333535353######535#5#5#dddddd22222d22222d222 ddddddddddddddddddd& !!333#5##35;#35#5^222dd22222 ddddpddddd2& !!!33!5#535!5!35d^^22>22,2 dddddddddd& 3353##5#!3#5##;35dd22^2dd22 ddddddpdd2& 3353##5#!33!5#535!5!35ddd22^22>22,2 dddddddddddddd8&X333#3#535##35;#35#522222d22222Xddpddddddd28&!33#3#5#5#535!5!35d^22222,2ddddddddddd& #3#33#5##3353#!5#5#53535353^d2d2d22d22222d2 dddddddddddddddd& 3##53!3#5#!!5#3,d2d2^2d^p22 dddddddd,d& !%333#5##3353#!5#5#5353535;35,22d22d222222222 dddddddddddddddd& 33#5##53!3#5#!!5#32d2d2d^2d^p22 dddddddddd,d& 3#!3#5##3353#!5#5#5353,ddd,2d22d22222 dddddddddddddd& 3#!3#5#!!5#3ddd^2d^p22 dddddd,d& '3353#33#5##3353#!5#5#5353535#d2d2d2d22d2222222 dddddddddddddddddd& 3353##5#!3#5#!!5#3d2d222^2d^p22 dddddddddd,d& 3353#333##!35#3535#5d2d2d2222d2222 ddddddddXdpddd& 33533!5#3533##5#35#5d2ddp222222 dddDd,dd,ddd2&!33##!#5373#353#5d^222222ddd22dddd,ddd,ddX33#!5#535!5#5335d22p22,dddd dddd& !!3#7!!3#!!^22d^> ddddddddd& !!!3!!!5#;35^^2,222 ddddd,ddd& 3353#3!3#!!35#dd2d^>d2 ddddddddXdd& 3353##5#!3!!!5#;35dd22^2,222 ddddddddd,ddd& 3#!!3#!!dd^> ddddddd& 3#!3!!!5#;35ddd^2,222 ddddd,ddd8&X!!3#!#3#5#d^2Xddddddd8&!3!!#3#5#5#;35^2,2d222dddddd,ddd& 3353#3!3#!!35#d2d2^>2 ddddddddXdd& 3353##5#!3!!!5#;35d2d222^2,222 ddddddddd,ddd& !3333#5#35#53#!5#3535;35222dd2222222 dddddpddddddddd& #33#5##533353#!5!5!5#5;35#52d2d2d2d2,2222 ddddddd ddddddd& !3353#33#5#35#53#!5#3535#dd222dd22222 dddddddpddddddd& #3353##5#3353#!5!5!5#5;35#5dd222d2,2222 ddddddd ddddddd& 3#!3#5#35#53#!5#3ddd^2dd222 dddddpddddd& 3#3353#!5!5!5#5;35#5ddd2d2,2222 ddd ddddddd8&X!3#5#35#53####535#5#3^2dd22d2d22Xdddpddddddddd& 3##533353#!5!5!5#5;35#5,d2d22d2,2222 ddddd ddddddd& 333###35;#35#52dddd22dd dd,Xdddd& 33#5##3533####3532d2d22d2dd2 dddddd,dXd2X33533#####5335ddd22dd22ddddd ,dddd2&33#3533#####53dddd22d2d22dddd,ddd 3353##3!53#5#5;35dd2dddd222d dddpdddddd 3353##5##5333!53#d2d2d2d2dd2 dddddddpdd, !!!#3!53#,,dddd dddpdd  !!33!53#,2dd2 dpdd,d 3353#!5#!#3!53#ddd222,dddd dddddddd,d 3353#!5#33!53#ddd22ddd2 dddddpdd,8X!#3#3#5#53#,ddd2dddXdpdddd83#33#3#5#53#dd2dd2dd2ddpdddd, 3#!#3!53#ddd,dddd dddpdd 33!53#Ȗdd2pdd,2& 3#3#53#%3##5#53322222d22d2d ddddddd2&3#%3#333#53##5!53#dd,dddd22d2ddddpdd ddd,d& 333#!5#533#5##532d22dd2d2 dd dddddddd& 33#5##533#!5#533#2d2d2d22dd dddddpdddd,d8&'33535353###333###53535#5#5##dd22dd2dd2d2d2dd22ddddddddddddddddddd8&335353##33###53535#5##dd2dddd2d2d2dpdddddddddddddd&335353##33#5#5##ddd2dddd2dddddddddddd&  3##533!!^d2d2d^> dddd d 3#3!53#5353,d2dddd2 dddddd8& 3!###535#dd^2d2ddddd833###535#53#dd2d2dddddddddd& 3!!3##53dd^>d2d2dddd& 33!53#%3##53ddd,d2d2ddddddd& 3!!3#dd^>dddd 33!53#3#ddddd DddXdd&3353###!!5#5353dd2d222^>d22dddddddd3353###3!535#53535#2d222ddd22dddddddddddd& 3##53333333#5#5#5#5##^d2d22222d2222d ddddddddddddpd& 3##5333533####^d2d2d22d2d ddddddpdd8&X333333###53535#5#5#5##d2222d2d2d2222dXddddddddddddpd8&33533####;##53dd22d2dd2d2dddpddddd& #3353##33333#5#5#5#5##35#d2d22222d2222d2 ddddddddddddpXdd& 3353##5#33533####d2d22dd22d2d ddddddddpd2& 33#5#33533####2d2d22d22d2d ddddddpdd8&3333333##535#5#5#5#5##dd22222d2Ȗ22222dddddddddddddpd8&33533##53###dd222Ȗ2dddd dddd& !!!3#!5#;3^^22222 dddpddpd& !!!3#!5#;3^^22222 dddd,,d& 3353#33#!5#3535#3dd222222222 dddddpddddpd& 3353##5#!3#!5#;3dd22^22222 dddddddd,,d& 3#35353#3#!5#353533d2d2d22222222 dddddpddddpd& 3##5373##53!3#!5#;3d2d2d2d2^22222 dddddddddd,,2&!#3#3!5#5#35;#33ddp2222222dddddd,ddd2& !3#3!5#;3335d2Ȗp222ddddddd,,ddd& 3#33##3#5#5##35335,d2222d2d2d ddddddddXdd& 3##5333533#5###^d2d2d22d2d dddddddddd8&!!3##33#5#5#5##353##53d22222d22ddd2d2ddddddddXdddd8&33533#5###;##53dd22d2dd2d2dddddddddd& !3353#33##3#5#5##35#35d2d2222d2dd22 ddddddddddXdd& 3353##5#33533#5###d2d22dd22d2d dddddddddddd& 3#3!!3#!5#5335!5#535353,d2,222d22d2 dddddddddddddd& 3##53!!!3#!5!5!5#53,d2d2^,22,22 ddddddddddddd& #333!!3#!5#5335!5#53535;3522,222d222222 dddddddddddddddd& 33#5##53!!!3#!5!5!5#532d2d2d^,22,22 ddddddddddddddd8&!!3#5#!3###535#5#5335!5#53^2d,22d22d22dddddddddddd8&!!!3###535#5!5!5#53^,22d2,22dddddddddddd& #3353#3!!3#!5#5335!5#53535#d2d2d,222d22d2 dddddddddddddddd& 3353##5#!!!3#!5!5!5#53d2d222^,22,22 dddddddddddddd28& !#3#535##22d2dddXd8&33#353###535#5##53dd222d2ddddddddd,d2& 3353#3###535#ddd2dȖ2 ddddd ddd& 3353##3#353##5##535#ddd2dd22dd2 dddddddddd,d2&!#3###535#2ddddddd,dd&33#3#353##5#5#535#53dd22dddddddddddddddd& 3353#3#!5#35;#3#5Ȗ2d2d222222 dddd dddd dd& 3353##5##5333533#5##5#Ȗ2d22d2dd2dd22 dddddddpd, dddd& !!333#!5#^2dd22 dd  ddd& !!33533#5##5#^2d2dd22 dpd, dddd& 3353#3#!5#35#3dd2d22d22 dddd dddd d& 3353##5#33533#5##5#dd222d2dd22 dddddpd, dddd& 333#!5#35;353##52d22d2222 dd dddddd ddd& 33##5#5;3533533#5##5#222222d2dd22 dddddddpd, dddd& 3##3#5353#3#!5#353d2d22d2222d2 dd dddd dddd& 3##5373##5333533#5##5#d2d2d2d2d2dd22 dddddddpd, dddd8&333##3#5#5#ddd22d2Xddddd8&33533#5##3#5#5#dd2dd222d2pd, ddddd2& '333##5#5###5#35;#3535333#52d2d2d2d2d22d22d22d ddpddddddpddd2& '33#5##5333333533###5##5#5#2ddd2d22d22d22ddd22 dddddd,d,ddddddd #33#5##533335353####5#5#5#2ddd2dd2d2d222d222 ddddddddddddddd& -33#5##533333535353######535#5#5#2d2d2d22222d22222d222 ddddddddddddddddddddd 3#73#3335353#####5#5#ddddd2d2d222d222 ddddddddddd,ddd 3#3####3!535353535#5353,d2d222p2222Ȗ2 dddddddddddddddd& 3##53!###3!5353535#,d2d2d2d>d2d ddddddddddddd 3#!####3!535353535#ddd222p2222 dddddddddddddd& 3#!###3!5353535#ddd2d>d2d ddddddddddd #3353#3####3!535353535#535#d2d2dd222p2222Ȗ2 dddddddddddddddddd& 3353##5#!###3!5353535#d2d22dd2d>d2d ddddddddddddddd33#5#3#53#53532dd22222ddd dd,ddd!##3##3!53535#53535#d2222p2222dddddddddddddd& #3353#333#5##353535##35#5d2d2222dd2222222 ddddddpddddddd2& 3353##5#!33!5#535!5!35d2d222^22>22,2 dddddddddddddd8&!3!!###535#5#;35^2,d2d2222dddddddd,dd2&'3353##33#5##5#5#535;#33535#52d2222d2222222222dddddddddddddddddddX 33#5##532d2d2 dddddX 3353##5#d2d22 ddddd !!^ dX 3##53,d2d2 dddX^ 33#5#d2d2 ddd8!!^dd8^;##53d2d2dddX 3353##5#dd22 ddddd^ 3#dd d 33##5#5;3522222d ddddddd8;3#d2ddX 3353##5##53Ȗ2d22d2 dddddddX 3##5373##53d2d2d2d2 dddddddX3#ddX#3#73333#5!#3535;##!5#5#5dd222dd222222,22dddpdddddddd&3#7!#5#3#353!dd22pddd&3#7333###dddddd,D,&3#7!#3!53#ddpd dd&#33535333###5#5##7#3353#5d22222222d2222dddddddd,dddd,d&3#73335353###3#53#5#5#ddd2d2d22222222ddddddddd,ddX+33535!33##3#53535#5##33#535#5#5#d22,2222d222222d22dddddddddddddddd  3#'3#%3#33!53#dddd,ddȖdd2 dddddpdd,2&3333#5!#3535;##!5#5#5222dd222222,22dddpdddddddd2!3#3#!53#3353522222p22dddd2& !#5!#53#22Ԗ22dd2&3333!3535;##!#5#5222 222222,22dddpdddd,dd2!#5#3#353!53#222>22dddd2!#####353!53535353535##2222222>222222dddddddddddddd2&333#3###53#2Ȗ22Ȗ22,d d,d2& !3#!5#;!5!5d22p222,,d dd !#3!53#,ddddd dd2&'3#3535353###333#5#5#5#3#53#22d22d2222d22d222dddddddddddddddd2&3333##5#5####35353222d22d22d222dddpddddpdd2&3335353####5#5##22d2d22d22dddddDdddd 2&333333#3#5#5#5#5##53#2222222222222ddddd dddddpd2& !#5!#!!3!53!22p2d,d22 ddddddd2& !3#!5#;!d22p222,d dd 2&!#3###53#222Ȗ22d dXd2& !3#!3#5335d2222ddddd2&!#5#33##353!5353535#5#5#2222222 2d22d2ddddddddddddd2&!#5#3#53##22222d ddd2&#3333535353####3#535#5#5#5#2d22d22d2222222222ddddddddddddddd2&!3##3#535#5#;333d2222222dddddddddd,,,2&+3335353###333#5#5###5353535#5#5#22d22222222d2222222ddddddddddddddddd2&33333##3#535#5#2ddddd2222pppdddddd2& '!33##3#5353#5##33#535#5#353,2222d222222d2222 dddddd,dddddd,d 3#73#!#3!53#dddd,dddd dddddpddd #3#73#3335353###3#535#5#5#ddddd2d2d22222222 dddddddddddddddd& #3##533353##33#5##5#;3,d2d2dd2222dd222 ddddddddddddd,,d 3##53!!3#!!5#535#53^d2d2^,2222 dddddddddddd2 3##5333533####53#,d2d2d22d222 dddddd dd, 3##5333!53#,d2d2ddd2 dddpdd,2&  3#'3#%3#333#!5##dddd^ddpd222 dddddppdd,2&3353#33#5##5#;3535#5d2d222dd22222dddddddd,dddd33#3##535#5#535##322d2Ȗ2ddd2dddddddD2&%3333535353######53535#5#5##222222d22222222222dddddddddddddddddd2!!333#!5#53535#5#35222222222ddddddddddd!!3#!!5#3^,22dddddd,8&X33##333##535#5#5#53535#2222Ȗ2222dXddddddddddddddd233533####53#2d22d222ddd dd,d!3#!5#535#5;3535,2222222d ddd 33!53#Ȗdd2pdd,2&335353##33#5#5##53#2ddd2ddddd22dddddddddd,2&#3333333#5#5###535353535#5#22222222d222222ddddddddddddddd2&33333#5##5###22d2222d2d,dddd2&3335353#####5#5#5#5#22d22222d2222dddddddddddd33#3##33#5#5#53535#535#d22d222222dddddddddddddddd& !3#!5#;3^22222ddd,,2& !#####22dd2dpp& !3###;35,22d22ddd!#33#!535#5#53,2222dddddddddd& !#3#!5#;35#5d222222dddd,dd !#3##d2dd2& 333#!5##2d222ppdd,dX333###5#5#535335335dd22ddd22d22d2Xdddddd2&#3335353##33#5#5###53535#5#22d22dd22d22dd2ddddddddddddddddd2&335333###5#5#2ddddd2d2,dd2&3#3535333#533##5##5#3dd222d222d22d22ddddd,dddddd,3#73#33!53#dddddd2ddddpdd,2&3#73#333#!5##ddddd222ddddppdd,d& 3##53!3#!5#;3^d2d2^22222 dddddd,,2& 3##53333#!5##^d2d2Ԗd222 dddppdd,2& '3##533#3535333#533##5##5#3,d2d2d222d222d22d22 dddddddd,dddddd,d& 333!3#!!35#d2^>2 ddddddXdd& 3#73#!!3#!!dddd^> dddddddd&!#3533###5353####,d2222d222ddddddddd,dXd& 3#3!#353^d2d2 ddd Xd2&#!3#5##3#3353#!5#5#535#5353^2d22d2222222dddddddddddddddddd&!3#5#!3#!5#5335!5#53^2d,222d22dddddddddd !#3!53#dpd dd 3#73#!#3!53#dddd,dddd dddddpddd& 3#!5#533d22ddddd2X333####5333522d22dddXd2X33333####352dd22d^d,dd,,&!#3533#####,d22d2dddddpdXd& #3##53#33535353###33#5#5##,dd2d2d2d2ddddd dddpddddddddddd2& !333#######335353535#5#d2d22222d2222d2 dddddddXpdddddd #3353#!5#3335353####5#5#5#ddd22d2d2d222d222 ddddddddddddddd8 333##5#ddddXD2&3333#5!#3535;##!5#5#5222dd222222,22dddpddddddddd& !!!3#!35d,22pdddd,d& !3#3#!3535d2222pddddXd!!#ddd2& 33#5!#53;3dddd22ddd d& !!3#!!d^>ddd2&33333#3#####35#2dddddddddddddd,,d,,,dd&!3#3#!5#5335#535##53^22222dd2ddddddddd2&335353535353#######2d22222d22222 dddddDddddd2& %3353#3#######335353535#5#dd2dd22222d22222 dddddddddXpdddddd&33535353###333#5#5#5##dd2d2d2dd2d2d2dddddddddddddd2 3###533ddd2DXd2&3335353####5#5##22d2d22d22dddddDdddd 2& 3!3#!#2d,ddd,D,d& !3#!5#;3^22222d dd d!###dddDXd& !3#!#35d22ddddXd&!3#5##3353#!5#5#353,2d22d22222dddddddddd,dd!###dddXd& 333!5!5!5#ddd>^2,Ddd2&333###5#5#353333d22d22ddddddpddddddppd+3335353###333#5#5###5353535#5#5#dd2d2d222222d2d2d222222dddddddddddddddddddddd& 3333#5!dddddXdd& 333#!5#dddd2,D,d2& 33333!2ddddd XXD2&333333#5!2d2d2dddpXXd2& 3!3!#352,2>2dX2& 333#!3#352d22ddԖddD,d& 3!3!35dd,2>dd,2&#!33#3##!5#533535#535#5##53d^2222222d22d2dddddddddddddddddd&3353533##5#5##3dd222222dddd ddX d&!#####53535#5#5;35d222Ȗ2222D,ddddddd2&!33!5#535!5!35d^22>22,2ddddddddd&!#333#!5#53535#5#3522222d22dddddddddd& !3#3#!3535d2222pddddddddddd!##d^ddp2& 33#5!#53;3dddd22dpdd,,d& !3!!!5#;35^2,222dddd,ddd3353353#3#5##5##535#dd2d2dddd2d2dddddd&!3#3#!5#5335#535##53^22222dd2dddddddddddddd&3353535353######dd2222d2222pdddd ddddd&#3353#3######35#35353535dd2dd2222d222222dddd ddddddpddddd&335353##33#5#5##dd2dddd2dddddddddd2 !###533,dd2 pd,2&3335353####5#5##22d2d22d22ddddd ,ddddd& 3353#5##ddddd d& !3#!5#;3^22222ddd,,d!###ddd pd8&33533##5###33dd2222d22dddddXddd,d&!3#5#!!5#3^2d^p22ddddd,d!###dddpd&!3333535353######535#5#5#dd22222d22222d222ddddddddddddddddX333###5#5#353333dd22ddd22d22d2Xdddddd,dd,,3353##33#5##53535#5#ddd2222ddd2222dddddddddddddd& 3333#5!dddddppdd& 3353#5!5#dddd2 d2& 33333!2ddddd pp 2&333333#5!2d2d2dddppppd2& 3!3#!#352,22p2dddddd& 333##3#'35dd22^dddddd ddd& 3!3#!735dd,22pdddddd2!3#!5#5335#535##53d,dd2dd2ddddddddddd&3353533##5#5##3dd222222dddddddd,d&!#5###535#5#5;35d2d222 ddddddddd& 33#5#!3!!!5#;35d2d2d^2,222 ddddddd,ddd& 3#73#!3!!!5#;35dddd^2,222 ddddddd,dd33#3533##535####53dddd222d22dddddddddd&  3##53!!#^d2d2d ddddpd&!3#5#3#353#!5#3,2dd2dddddddddddd,d&!!!3#!5!5!5#53^,22,22ddddddddd 3#33!53#dd2dd2ddpdd, 3#73#33!53#dddddd2 dddpdd,d&3#3#!5#533#ddd22dddd dddd2X333####5333522d22ddddpd,dd2X335333##5##%352dd22d^dddddd2&33#3533#####53ddd22d2ddddddd,ddd& 3##53335353##33#5#5##,d2d2d2dddd2d ddddddddddddd& 33#5#3353535353######d2d2d2222d2222 dddpdddd ddddd& -3353##5#3333535353######535#5#5#dd222d22222d22222d222 ddddddddddddddddddddd 333##5#ddddp ddd!33333#53#3#5#5#5#5##35#dd2222222d2222d22dddd,dpdddddp2&X !3!5!!2d ,X dd!####5353535#,d22d22dD,ddd2&!##!2dddX2 !#!3#2dddDXp3##ddDX3###dd2dX2!###2ddDX2 33#5353!2dd2>ddD,3##ddp,d8!#!dd| 2 !#!5!!22p^dd2 3!###5353!2d^22d2 d dddd2!!32>dDX 2335333#53#5####35#2d2222d22d22dddd ddddpd^83##^d2| 3#53#dDd2!3###5#5#35#3#335322222222222dpdddd,dddd23353#53##!53#dd2222d2dd ddd28 !##3#2dd| d2 !!5!#3#2>^dDdd28333535#53####5#22d222d22ddpdpdd!33335#53##33!535#5#5#5#5#dd22d22222p22222dddddddddddddd28 !###5353!3#222d22dd dddddD2!#!2dDX2&33333#!5#2ddddd2p2XXdd2& !###53#ddd2DXd28X,3#!5#5353353&2dddd2,pddd8X!33#5#5#3#!5#5335#533#73#^222d222d22dddddddddddddpdddd8,d 73###5353d22d22ddddddX 3##533#,d2d22ddXdd!3#5#33#5#5#533#,2d2ddd22dddddddddd dX,!!X,d3#3#dddd  3#3#53,d222 ddd 3##535#2d22 ddd 3#3#5373#3#53d222d222 ddddddd 3##535#73##535#2d22Ȗ2d22 ddddddd2X #'+/333535353####3#5##535353535#7353#'353352222d222222d22222dȖ2d dddddddddddddddddpdddd2& !#35!#3#3!#2,d,Ȗ ddddd,X3###3#3322,22Xp, X2& !335353###5#####2,222222222d2d dddd,dd 2& '!33##3#5353#5##33#535#5#353,2222d222222d2222 dddddd,dddddd,d2&'+/335353535353##3######53535##35352222222222222222d2^ddd dddddddd ddddddddddd2X/3733#3535353##3#######53535#535#535#3535222d2222222222222dddddddddddddd dddddddddddddddd2&+/373#3353535353##3######53535#535#35335352Ȗ22222222222222dd2dddddddddddd dddddddddddddddd2&1593####53535#%3##3######5353535353535335352222d22d2222222222222222dddddddddddd ddddddddddddddd2dXX3#!!3#5#5#5353d2,2dddddXdddddddddd83333#5####535353d222d2d2d222dddddXddddd&X333###535!5!5#dddddd2,2Xdddddddddd 3353####5#5#5#533d2d222d222d2 ddddddddddd 333#5#5###5#5353,2d2222222 dddd dddd28X,3#!5#5353353&2dddd2,pddd8X!33#5#5#3#!5#5335#533#73#^222d222d22dddddddddddddpdddd8,d 73###5353d22d22ddddddX 3##533#,d2d22ddXdd!3#5#33#5#5#533#,2d2ddd22dddddddddd dddX#3#73#;33#5#!5#535353#3535dddddd22d2222Ȗ22dddddddddddddddddd^ 3#3#5353Ȗdd22dddddX333#5##53533#d2d2ddddddddddX 3!53#!5#3#dd2 2ddddddXX3#73#333#5##53532ddddd2d2XddddddddddddX3#73#!3!53#!5#dddddd2 2ddddddX33!5#d2 ddd^3#dd 33#!5!5#3#d22,2dddddddd2d&3#73#!33#!5#535;#!5#5dddd,22dd2222,2ddddddddddddddddX3#73#33#!5!5#2ddddd22,2Xdddddddddd 33#5##5333#!5!5#dddddddd22,2ddddddddddX!333!5!5#5##533#d,22d2d2ddddddddddddpddX!333!5!5#5##53d,22d2d2ddddddddddX3#!333!5!5#5##53ddd,22d2d2ddddddddddddX3333!535#5#^d222p22ddddddddX3#3333!535#5#,dd2d222p22dddddddddd8X,33###!5!535#2222,22,ddddddddd8XX3#33###!5!535#dd2222,22XddddddddddX,3353353##5##5#ddd222,ddddddddddX 33#5##533353353##5##5#ddddddddd222dddddddddddddddX33#!5#53353531#35^22 2dd2d2ddddddddddX3#33#!5#53353531#35dd222 2dd2d2ddddddddddddX33533#!53537#35d222d22dddddddddX33533#!53533##35d222d2dd22ddddddddd&33#5##!!53532d2^dddddddddd&3#33#5##!!5353dd22d2^ddddddddddddX 33#5##53333#5##5353dddddd2d2d2ddddddddddddX!3#3#5#!53535#3#d,d2dddddddddddddpddX!3#3#5#!53535#d,d2ddddddddddddX3#!3#3#5#!53535#ddd,d2ddddddddddddd2&33533#3##5##5#535#5335ddddddddddddddddddddddX5!!Xdd3#33#!535#5;35,dd22dp222ddddddddddd3#73#33#!535#5;35dddd2dp222dddddddddddddX3##333!5!5#5#5353^d2^dddddddddddddddd^3#!53d2 ddd 33!5##535;3522dd2ddddddddX3#33#!5!5#dddd22,2Xdddddddd&X#3333##5##535#5313535#35#5Ȗd2222d222222Xddddddddddddddddd8X33###!5!535#5#5;35,2222,2222ddddddddddd8X,33#5#33#!5#5353!5#5#53^2dd222p222,222,dddddddddddd 33#!5!5#3#73#d22,2dddddddddddddX 33#5##533!53#!5#dddddddd2 2ddddddd28XX#!33#5##!53#!5#353535##3#2^dd2^d2>22dddddXdddddddd,ddddd28XX!33#5##!53#!5#353535##2^dd2^d2>22dddXdddddddd,dddd28X #3#!33#5##!53#!5#353535##dd^dd2^d2>22ddd dddddddddd,ddddX333#5##53533#73#d2d2dddddddddddddd3#33#!5#535335#5#53Ȗ2d2222222dddddddddddX!##3!5##535#5#335d^222222ddddddddddddX3#!##3!5##535#5#335dd^222222ddddddddddddddX3#33#3#5##535#5;35dd222d222ddddddddddddddX3#33!3#!5#5#5;35dd22d2–222ddddp,ddddddddX3#73#33#3#5##535#5;35dddd22d222ddddddddddddddddX%)3#73#33##!5#5#53533!535#5#5;35,ddddd222p22222,2222ddddddddddddddddddddX3!53!3#3#5353d2Ԗdd22dddddddX 33#5#!53d2 dddd2X 3#!5#5353!d2pd22^ddddX!33#5##5##535;35,2d22d2ddddddddddddd8X 33###35;35^22dd22ddddddddXX3#333#5##5353dddd2d2Xddddddddd2X3#;3##!5#5#53533353^dd2222222222dddddddddd&!333333#3!53535#5#5#5#35d2222d222d2222dddddpdddddddpdd2&!!2 8&X3#3##!!5#53535#53Ȗ2,22222Xdddddddd!!3#d^dddd  3#3#53533#dd22dd dddddp8X !%3#3#535333###!53535#5#5;35dd22d22222222 dddddddddddddddd83#3#3#5353dddd22 ddddddd 3#3#535333#!5!5#Ȗdd222d22,2 ddddddddddX %3#3#535333#5#5#3#!5#5335#53dd222222d222d22 dddddddddddddd8333!5!5#5##533#%3+3#22 2d22dd,dddddddddddpdddd8X3333!5!5#5##533#%3+3#d2dd^2d2dd,dddddddddddddpdddd28XX+!33#5##!53#!5#353535##3353##5#2^dd2^d2>22ddd,222222Xdddddddd,ddddddddd8 33#!5!5#3#%3+3#d22,2dd,ddddddddddddd8X333#5##53533#%3+3#d2d2dd,ddddddddddddddd8X 3!53#!5#3#%3+3#dd2 2ddd,ddddddddddd8X 3+3#%3#33###!5!535#dddd,dd2222,22dddddddddddddX3##53%3##333!5!5#5#5353ddd,Ȗddd2ddddddddddddddddddd^3#Ȗ^3#ddD2!##333#5#5#5#3d^2222d2222dddddddd,2& 3353353!#2dddddpddddd d3#33##3!535#5#532d222222ddddddddd2&!33##!5#5#535;#33535#5,2222222222222dddddddddddddddd!#!ddDX2&3333535353#####5#5#5#5#2d22d22d2222d2222ddddddd2&33333#5#5#5####53535353d2222d22d22d2222dddddddd 33##5#5;352d222ddddd8X#3#!#33#5#5###!!5#53535#5#,dd^2d2dd222,22222ddddddddddddddd8& 3#3#3##!!5#53535#53,dd2Ȗ2,22222 ddddddddd2&'33335353533#5#5#####53535#5#5#2d22222d2d22222d2222dddddd dddddddddd8X#33#3#3##5#5#535;353535#52222222d22dddddddddddddddXX333#5#!5#535353#3535d22d2222Ȗ22Xddddddddddddd2d&!33#!5#535;#!5#5,222p22222,2ddddddddddd, !!, ,X !!,, X !!X d,!!,pd, !!, DdX !!!!,,, pdX !!!X p,dX!!,,pdX !!!!,, p,dX !!,, DdX !!!X DdX!!XpdX !!!,, pdX !!!,,, DdX !!X D8,d5!!,d8, !!!!,, p8X !!!!,,, p8X !!!!X, p8,!!,D8, !!, 8X !!!!,,, D8X !!!X D8X!!!!,,,p,8X !!!!!!,,, p,8X !!!!,,, D,8X !!!!!X, D,8X!!!Xp8X !!!!,, p8X !!!!,,, D8X !!!X DX 3# ,X& 3#, X& 3#%3#, 3# 3#3# d& 3#3#, d&  3#%3#3#, d,&3#,& 3#3#, d,& 3#3#, d&  3#%3#3#, d&3#3#,,&  3#3#3#, d,&  3#3#3#,, d,X  3#%!!3#3#,,, d,d53#d 3#3# & 3#3#, &  3#%3#3#, 3#3#d  3#3#3# dd&  3#3#3#, dd&  3#%3#3#3#, dd&3#3#,d&  3#3#3#, dd&  3#3#3#, dd&  3#%3#3#3#, dd& 3#3#3#,,d&  3#3#3#3#, d,d&  3#3#3#3#,, d,d&  3#%3#3#3#3#,, d,d,8Xd%!!,,d8X !!!!,,, p,8X !!!!,,, p8X !!!!X,, p8X!!!!,,p,8X !!!!,, D,8X !!!!!!,,,, p,8X !!!!!X, p,,8X!!,,D8X !!!!,, D,8X !!,, 8X !!!X 8X!!!XD,8X !!!!,, D,8X !!!!,,, ,8X !!!X ,8Xd5!!Xd8X !!!!,X p8X !!!!,,X p8X !!!!XX p8X!!!,,p8X !!!,, D8X !!!!!,,,, p8X !!!!X, p8X!!!,,,D,8X !!!!!,,, D,8X !!!,,, ,8X !!!!X, ,8X!!XD8X !!!,, D8X !!!,,, 8X !!X ,&d%3#,d& 3#3#, ,& 3#3#, &  3#%3#3#, &3#3#,d&  3#3#3#, dd&  3#3#3#,, dd&  3#%3#3#3#,, dd,&3#3#,d&  3#3#3#, dd,&  3#3#3#, dd&  3#%3#3#3#, dd& 3#3#3#,,d&  3#3#3#3#, d,d&  3#3#3#3#,, d,d&  3#%3#3#3#3#,, d,d&d53#%3#,d&  3#3#%3#, &  3#3#%3#,, &  3#%3#3#%3#,, & 3#3#%3#,d&  3#3#3#%3#, dd&  3#3#3#%3#,, dd&  3#%3#3#3#%3#,, dd& 3#3#%3#,,d&  3#3#3#%3#,, dd&  3#3#3#%3#,, dd&  3#%3#3#3#%3#,, dd& 3#3#3#%3#,,,d&  3#3#3#3#%3#,, d,d&  3#3#3#3#%3#,,, d,d&  3#%3#3#3#3#%3#,,, d,d8d5333#d2ddddd8d5333! dddd8, 333333!222222dddddd8& 333333!2ddddddddddd8, 333333!222222ddd8& 3333333333!22222d2222 dddddddddd8X !!35353^2dd dd8X 3!35353d dd8X !!35353535353,,222222 ddddd8X 3!35353535353&2ddd2dd ddddd8X !!535353535353,,222222 ddd8X 3!3535353&22ȖD,ddd28X !!535353535#5#5#5#2&22222222 ddddddd8X 3333335353535353!22222d22222 ddddddddddd8 3#ddd 8X 7_w33533533#3#3#3#3#5##5##5#535#535#535#535#3#3#3#3#3533535#535#535#535##533#3#3#5#535#535#dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd^8Xd%3#5353&2dddddd8Xd%3!5353– Ȗddd,8X 3!5353535353&222222ddddd28X 3!5353535353&2dddddddddd,8X 3!5353535353&222222|ddd28X 3!535353535353535353&22222d2222 ddddddddd8X !333!^dd2 dddD8X 3333!dȖ dddD8X !333333!,222222 ddddddp8X 3333333!2ddddd2 ddddddp8X !333333!,222222 dddd8X 33333!2Ȗ2dddd8& !####3333!&22222222 dddddddd8X !#5#5#5#5#5######X22222d22222 dddddddddd8 3#dd 8X !!X 2dX 33!3d p8X!###Xdp,8X 33##dd p8^ 3##3dd ,8^ #3####3333#5#5#5#5#53535353Ȗd222222d22222222 ddddddddddddddd8X #33333#####535353535#5#5#5#22222222d222222d ddddddddddddddd8X'3333335353535353#####5#5#5#5#22222d2222222222222ddddddddddddddddddX '33333#5#5#5#5#5######53535353222222222d222222222 ddddddddddddddddd^ 3######53535353Ȗd222222222 dddddddddX 33333#5#5#5#5#5#222222222d ddddddddd8^333333#5#5#5#5#22222d2222dddddddddd8X3#####5353535353&22222d2222ddddddddd8X 33###3dd p,d 33##5#532222dddX!33##!5#5#353,d22dd22dddpdddddX!33##!5#5#35;#3353#5,d22dd22d2ddddddpddddddpddd8^ 3#dd X!!X8X!##^dp8^!##^dX 33!d p^ 3!53d 8X 33##dd pp8^ 3##53dd 8X!###XdpX 33!53d p8X 33###53dd ppX333###5#53ddddddXdddddXX33##5#5#5353,ddddddXdddd83333###535353d222d222dddd dddd833####5#5#5#53d222d222 dddddddd8X!#33#5#5###!!5#53535#5#^2d2dd222,22222dddddddddddddd&X !###33#d,dddddXd ddX 3# ,X& 3#, X& 3#%3#, 3# 3#3# d& 3#3#, d&  3#%3#3#, d,&3#,& 3#3#, d,& 3#3#, d&  3#%3#3#, d&3#3#,,&  3#3#3#, d,&  3#3#3#,, d,X  3#%!!3#3#,,, d,d53#d 3#3# & 3#3#, &  3#%3#3#, 3#3#d  3#3#3# dd&  3#3#3#, dd&  3#%3#3#3#, dd&3#3#,d&  3#3#3#, dd&  3#3#3#, dd&  3#%3#3#3#, dd& 3#3#3#,,d&  3#3#3#3#, d,d&  3#3#3#3#,, d,d&  3#%3#3#3#3#,, d,d, !!, ,X !!,, X !!X d,!!,pd, !!, DdX !!!!,,, pdX !!!X p,dX!!,,pdX !!!!,, p,dX !!,, DdX !!!X DdX!!XpdX !!!,, pdX !!!,,, DdX !!X D8,d5!!,d8, !!!!,, p8X !!!!,,, p8X !!!!X, p8,!!,D8, !!, 8X !!!!,,, D8X !!!X D8X!!!!,,,p,8X !!!!!!,,, p,8X !!!!,,, D,8X !!!!!X, D,8X!!!Xp8X !!!!,, p8X !!!!,,, D8X !!!X D,&d%3#,d& 3#3#, ,& 3#3#, &  3#%3#3#, &3#3#,d&  3#3#3#, dd&  3#3#3#,, dd&  3#%3#3#3#,, dd,&3#3#,d&  3#3#3#, dd,&  3#3#3#, dd&  3#%3#3#3#, dd& 3#3#3#,,d&  3#3#3#3#, d,d&  3#3#3#3#,, d,d&  3#%3#3#3#3#,, d,d&d53#%3#,d&  3#3#%3#, &  3#3#%3#,, &  3#%3#3#%3#,, & 3#3#%3#,d&  3#3#3#%3#, dd&  3#3#3#%3#,, dd&  3#%3#3#3#%3#,, dd& 3#3#%3#,,d&  3#3#3#%3#,, dd&  3#3#3#%3#,, dd&  3#%3#3#3#%3#,, dd& 3#3#3#%3#,,,d&  3#3#3#3#%3#,, d,d&  3#3#3#3#%3#,,, d,d&  3#%3#3#3#3#%3#,,, d,d,8Xd%!!,,d8X !!!!,,, p,8X !!!!,,, p8X !!!!X,, p8X!!!!,,p,8X !!!!,, D,8X !!!!!!,,,, p,8X !!!!!X, p,,8X!!,,D8X !!!!,, D,8X !!,, 8X !!!X 8X!!!XD,8X !!!!,, D,8X !!!!,,, ,8X !!!X ,8Xd5!!Xd8X !!!!,X p8X !!!!,,X p8X !!!!XX p8X!!!,,p8X !!!,, D8X !!!!!,,,, p8X !!!!X, p8X!!!,,,D,8X !!!!!,,, D,8X !!!,,, ,8X !!!!X, ,8X!!XD8X !!!,, D8X !!!,,, 8X !!X 2dX 33!3d p8X!###Xdp,8X 33##dd p8^ 3##3dd ,8^ #3####3333#5#5#5#5#53535353Ȗd222222d22222222 ddddddddddddddd8X #33333#####535353535#5#5#5#22222222d222222d ddddddddddddddd8X'3333335353535353#####5#5#5#5#22222d2222222222222ddddddddddddddddddX '33333#5#5#5#5#5######53535353222222222d222222222 ddddddddddddddddd^ 3######53535353Ȗd222222222 dddddddddX 33333#5#5#5#5#5#222222222d ddddddddd8^333333#5#5#5#5#22222d2222dddddddddd8X3#####5353535353&22222d2222ddddddddd8X 33###3dd p,d 33##5#532222dddX!33##!5#5#353,d22dd22dddpdddddX!33##!5#5#35;#3353#5,d22dd22d2ddddddpddddddpddd8^ 3#dd X!!X8X!##^dp8^!##^dX 33!d p^ 3!53d 8X 33##dd pp8^ 3##53dd 8X!###XdpX 33!53d p8X 33###53dd ppX333###5#53ddddddXdddddXX33##5#5#5353,ddddddXdddd83333###535353d222d222dddd dddd833####5#5#5#53d222d222 dddddddd8d5333#d2ddddd8d5333! dddd8, 333333!222222dddddd8& 333333!2ddddddddddd8, 333333!222222ddd8& 3333333333!22222d2222 dddddddddd8X !!35353^2dd dd8X 3!35353d dd8X !!35353535353,,222222 ddddd8X 3!35353535353&2ddd2dd ddddd8X !!535353535353,,222222 ddd8X 3!3535353&22ȖD,ddd28X !!535353535#5#5#5#2&22222222 ddddddd8X 3333335353535353!22222d22222 ddddddddddd8 3#ddd 8X 7_w33533533#3#3#3#3#5##5##5#535#535#535#535#3#3#3#3#3533535#535#535#535##533#3#3#5#535#535#dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd^8Xd%3#5353&2dddddd8Xd%3!5353– Ȗddd,8X 3!5353535353&222222ddddd28X 3!5353535353&2dddddddddd,8X 3!5353535353&222222|ddd28X 3!535353535353535353&22222d2222 ddddddddd8X !333!^dd2 dddD8X 3333!dȖ dddD8X !333333!,222222 ddddddp8X 3333333!2ddddd2 ddddddp8X !333333!,222222 dddd8X 33333!2Ȗ2dddd8& !####3333!&22222222 dddddddd8X !#5#5#5#5#5######X22222d22222 dddddddddd8 3#dd 8X !!X  3##33#,d2d2ddd,pdd& 3##535#73##535#ddd2ddd2ddddddd2&33533#3##5##5#535#5335ddd2ddddd2dd2ddddddddddX +3;333#5##33####5#5#533535#5#535353#3535#3535,d2dd2222d2dd2222d2d222d2 dddddddddddddddddddddddddddddd2&/373335353####353##5#5###535353535##5;3535d2d2d2d22d22d2d2d22d2222dddddddddddddddddddddddpddX'-133##333#5#!5#53535#535;#3535#35;#22222ddd2d222222d2ddddddddddddddddddddddddd 3##535#,ddd2ddd3##3#5#353,ddd2d2ddpddd33###5353#2d2ddddpddddX#'+3353##3#5###5##53535#5335;3535,ddddddd22ddddddd22222ddddddddddddddddX3#3###535#5353,d22d22Xddddddddd2 73##535#22d22dddd,!!dpd273#2dd2&3#######535353535353d2d22d2d2d22d2ddddddddddddd2X!3###!5#5335;##35335^2222222222222dddddd,dddd,d 3###53#53^d22d22d,d2X!3####3!53535353535##53^222d>2dd2d2ddddddddddddddd2X!##33##!5!535#53535!2d2222p^22dddddddddddddd23####353##5!5353535353^d2d22d2d222d2dddddddddddd2X!!33##!5#533535!532222d22dddddddddd2&!3##33##!5#53535353#3535,d2d222222d2d22dddddddddddddddX!######53535353535!d22d2d2d22dddddddddddd2X#+!3##3##!5#53535#535;#3535#3535^22222222222222222ddddddddddddddddddddddX#!3######53535#5#535;#3535^2222d2d2d222222ddddddddddddddddd,3#3#dd2dddd, 3#3##53dd2d2d2ddddX3###333#5#5#5#535353–ddd2dd2ddddddddddddddddd!!!!dppddd3333####5353535#5#5#dd2dddddd2dddddddddddddd&!3####5353535##533#,222ddd22d2ddddddddddddd d8X !!5#5#5#Xd2d ddd8X !#5#5#5#XdȖ ddd8X !!5#5#5#5#5#5#X222222 dddddd8X !#5#5#5#5#5#5#X2ddddd2 dddddd8X !!5#5#5#5#5#5#X222222 ddd28X !#5#5#5#5#5#5#5#5#5#2&22222d2222 ddddddddd 3###dd2 ddd !###Ȗ ddd, !######,222222 dddddd& !######&dd2ddd dddddd, !######,222222 ddddX !####XȖ2 pddd8 33333#####2222222222 dddddddd2,& !#####5#5#5#5#22222d2222 ddddddddd8X !###!X2dd Dddd8X !####Xd Dddd8X !######!X222222 pdddddd8X !#######X2ddddd2 pdddddd8X !######!X222222 dddd8& !##########&2222d22222 dddddddddd^X 3#5#5#^2dd dddX !#5#5#d dd,X !#5#5#5#5#5#,,222222 ddddd2X !#5#5#5#5#5#2&2ddddd ddddd,X !#5#5#5#5#5#,,222222 |dddX !#5#5#5#5#X2Ȗ2 Ddddd^8X 3#5#5#5#5#53535353&2222222222 ddddddd28&,33333!53535353d2222 2222,ddddddddd,&d%3#,d& 3#3#, ,& 3#3#, &  3#%3#3#, &3#3#,d&  3#3#3#, dd&  3#3#3#,, dd&  3#%3#3#3#,, dd,&3#3#,d&  3#3#3#, dd,&  3#3#3#, dd&  3#%3#3#3#, dd& 3#3#3#,,d&  3#3#3#3#, d,d&  3#3#3#3#,, d,d&  3#%3#3#3#3#,, d,d&d53#%3#,d&  3#3#%3#, &  3#3#%3#,, &  3#%3#3#%3#,, & 3#3#%3#,d&  3#3#3#%3#, dd&  3#3#3#%3#,, dd&  3#%3#3#3#%3#,, dd& 3#3#%3#,,d&  3#3#3#%3#,, dd&  3#3#3#%3#,, dd&  3#%3#3#3#%3#,, dd& 3#3#3#%3#,,,d&  3#3#3#3#%3#,, d,d&  3#3#3#3#%3#,,, d,d&  3#%3#3#3#3#%3#,,, d,d8d5333#d2ddddd8d5333! dddd8, 333333!222222dddddd8& 333333!2ddddddddddd8, 333333!222222ddd8& 3333333333!22222d2222 dddddddddd8X !!35353^2dd dd8X 3!35353d dd8X !!35353535353,,222222 ddddd8X 3!35353535353&2ddd2dd ddddd8X !!535353535353,,222222 ddd8X 3!3535353&22ȖD,ddd28X !!535353535#5#5#5#2&22222222 ddddddd8X 3333335353535353!22222d22222 ddddddddddd8 3#ddd 8X 7_w33533533#3#3#3#3#5##5##5#535#535#535#535#3#3#3#3#3533535#535#535#535##533#3#3#5#535#535#dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd^8Xd%3#5353&2dddddd8Xd%3!5353– Ȗddd,8X 3!5353535353&222222ddddd28X 3!5353535353&2dddddddddd,8X 3!5353535353&222222|ddd28X 3!535353535353535353&22222d2222 ddddddddd8X !333!^dd2 dddD8X 3333!dȖ dddD8X !333333!,222222 ddddddp8X 3333333!2ddddd2 ddddddp8X !333333!,222222 dddd8X 33333!2Ȗ2dddd8& !####3333!&22222222 dddddddd8X !#5#5#5#5#5######X22222d22222 dddddddddd8 3#dd 8X !!X 2dX 33!3d p8X!###Xdp,8X 33##dd p8^ 3##3dd ,8^ #3####3333#5#5#5#5#53535353Ȗd222222d22222222 ddddddddddddddd8X #33333#####535353535#5#5#5#22222222d222222d ddddddddddddddd8X'3333335353535353#####5#5#5#5#22222d2222222222222ddddddddddddddddddX '33333#5#5#5#5#5######53535353222222222d222222222 ddddddddddddddddd^ 3######53535353Ȗd222222222 dddddddddX 33333#5#5#5#5#5#222222222d ddddddddd8^333333#5#5#5#5#22222d2222dddddddddd8X3#####5353535353&22222d2222ddddddddd8X 33###3dd p,d 33##5#532222dddX!33##!5#5#353,d22dd22dddpdddddX!33##!5#5#35;#3353#5,d22dd22d2ddddddpddddddpddd8^ 3#dd X!!X8X!##^dp8^!##^dX 33!d p^ 3!53d 8X 33##dd pp8^ 3##53dd 8X!###XdpX 33!53d p8X 33###53dd ppX333###5#53ddddddXdddddXX33##5#5#5353,ddddddXdddd83333###535353d222d222dddd dddd833####5#5#5#53d222d222 dddddddd8X !!5#5#5#Xd2d ddd8X !#5#5#5#XdȖ ddd8X !!5#5#5#5#5#5#X222222 dddddd8X !#5#5#5#5#5#5#X2ddddd2 dddddd8X !!5#5#5#5#5#5#X222222 ddd28X !#5#5#5#5#5#5#5#5#5#2&22222d2222 ddddddddd 3###dd2 ddd !###Ȗ ddd, !######,222222 dddddd& !######&dd2ddd dddddd, !######,222222 ddddX !####XȖ2 pddd8 33333#####2222222222 dddddddd2,& !#####5#5#5#5#22222d2222 ddddddddd8X !###!X2dd Dddd8X !####Xd Dddd8X !######!X222222 pdddddd8X !#######X2ddddd2 pdddddd8X !######!X222222 dddd8& !##########&2222d22222 dddddddddd^X 3#5#5#^2dd dddX !#5#5#d dd,X !#5#5#5#5#5#,,222222 ddddd2X !#5#5#5#5#5#2&2ddddd ddddd,X !#5#5#5#5#5#,,222222 |dddX !#5#5#5#5#X2Ȗ2 Ddddd^8X 3#5#5#5#5#53535353&2222222222 ddddddd28&,33333!53535353d2222 2222,ddddddddd 3##33#,d2d2ddd,pdd& 3##535#73##535#ddd2ddd2ddddddd2&33533#3##5##5#535#5335ddd2ddddd2dd2ddddddddddX +3;333#5##33####5#5#533535#5#535353#3535#3535,d2dd2222d2dd2222d2d222d2 dddddddddddddddddddddddddddddd2&/373335353####353##5#5###535353535##5;3535d2d2d2d22d22d2d2d22d2222dddddddddddddddddddddddpddX'-133##333#5#!5#53535#535;#3535#35;#22222ddd2d222222d2ddddddddddddddddddddddddd 3##535#,ddd2ddd3##3#5#353,ddd2d2ddpddd33###5353#2d2ddddpddddX#'+3353##3#5###5##53535#5335;3535,ddddddd22ddddddd22222ddddddddddddddddX3#3###535#5353,d22d22Xddddddddd2 73##535#22d22dddd,!!dpd273#2dd2&3#######535353535353d2d22d2d2d22d2ddddddddddddd2X!3###!5#5335;##35335^2222222222222dddddd,dddd,d 3###53#53^d22d22d,d2X!3####3!53535353535##53^222d>2dd2d2ddddddddddddddd2X!##33##!5!535#53535!2d2222p^22dddddddddddddd23####353##5!5353535353^d2d22d2d222d2dddddddddddd2X!!33##!5#533535!532222d22dddddddddd2&!3##33##!5#53535353#3535,d2d222222d2d22dddddddddddddddX!######53535353535!d22d2d2d22dddddddddddd2X#+!3##3##!5#53535#535;#3535#3535^22222222222222222ddddddddddddddddddddddX#!3######53535#5#535;#3535^2222d2d2d222222ddddddddddddddddd,3#3#dd2dddd, 3#3##53dd2d2d2ddddX3###333#5#5#5#535353–ddd2dd2ddddddddddddddddd!!!!dppddd3333####5353535#5#5#dd2dddddd2dddddddddddddd&!3####5353535##533#,222ddd22d2ddddddddddddd dX#'!3###3535###3!!5#5#5335335^2222d22,222d2dddd,ddddddddd,d&333##5!#5353535;##!5#5222dd22d22d2,2ddddddd2X#!3##3##!5337#3535#3535222222p22d2222ddddddd,ddddddddddX!3#5##353#!5#353,2ddd22d2ddddpddddd2& !3##!5337##353^2d222d22ddpdd,dddd2X!!#3##!!53322^>22ddddddd,2X!!#3###53322d22ddddd,2X!!3#5###3535#53##!5#53353^2d222d222222dddddddddddd,d2X3#35353###535###533d22d22d22d22dddd,2&!###3!535335#22p22dddddd,d2X3###!5#533533d2222d22dddddd,2X#335353###33#5#5###53;35ddddddddd22d2222ddddddddd,dd2 3##!!533d22^>22dd,X#3335353###53###5#5###533d2d222d222d222d22dddd,dddd,X#33333353###5#5#5#5###533d22222d2222222d22ddd,ddd,2X!3###!5#5335;##35335^2222222222222dddddd,dddd,d2X!3##!##5337#35352222d22d22ddddd,ddddd28X+!3####3#5#5#5#5335;##35335335^22222d22222222dd222dddddddddd,dddddd,d2X!!3###3#5#5###5337#353522222d22d22d22ddddddd,ddddd2X#!3#5##!3##!5#533535!5#5353^2d2,2222d2222ddddddddddddddddddX!####5335#d22d22dd,d2X3##353353###!5#533d2222d222222dd,dddd,dX333535353#####5#5#dd2d2ddd2d2d22pdddddd2X!3#3535333353###5#5###3dd222d222d2dd2d2d2dd,dddd2&'3335353###33#5#5###5353535#5#d2d2d2d222d2d2d2d222ddddddddddddddddddX333535353######535#5#5#dd2dd2d2d222d2222ddddddddddd2&!#####3!53535353535#2d22dp2d22dddddddddddddd 3###3#33,d22d22 dd,,33333#5#5#5#5#d2222d2222dddddd 3###535335#22d22d d,d33#5###53532d2ddd2ddddd1!! d,33#5#,d2d2d!3#3!5#535!5!35d^222>2d,ddddddddd2&333##!53;3##3535#5d222p2222222ddd,dddddd2&!3#5##!!5#5353^2d2^p222ddddddd2X3##!5#535353353#3535#5d22p22222222dddddddddd2&!3!!!5#535;35^2p,2222dddddddd&33#5##3###535#535353,2dd2dd2d2dd22dddddddddddd&3353##!5!5!;35#52d22,222ddddd,dd2&333##535####53;35d22d222d2222ddd,ddd3#3#3!53535#,ddd2dd22dddddd2X3#3##!5#533535#dd222d2ddddddd2&3#35353##33#5#5##533d22dd2d2d22ddddddddd,d3##3!535335#22dd22ddddd,d&33533##535###535###532222d2d2d2d2d2ddd2&33533##535####53dd222d222d2ddddd2&!3##!5#535;#3535^222222222ddddddd2&33533###5##37#3535dd22222d222dddddd,dd2&3353##5##5#535;#3535#52d2d222222d2ddddddddd2&33533#5####53dd22d22d2dddddddd!!!#!5!5#5#53^,2,22dddddddd33##353##5#535#53dd2d222ddddddddd2&3#3533##5##5#53dd2dd2d222dd,dddd2&3333535353#####5#5#5#2d22d22d22d2d222ddddddddddddd2&33535333###5##5#7352d22dddd2ddd22pd,dddddddd&!3335353##3#5#5###53535#5#22d2d2d2d2dd2ddddddddddddddddd&3333535353######53#5#dd22222d22d22d22ddddddddddddd,d2&!###3!5353535#dd2>dddddddddddd 3###3#3#5#535#535353^d2222d222222 ddddddddd 3###533,d22d22,d 33#3####5353535#535#Ȗ222222d2222d dddddddddX3353##5##53dd2dd2ddddddd 3#3##53,dd2d2d2dd8&#333#5##3##5#5#535353#3535,dd2dd2d222Ȗ2d2ddddddddddd2X!3#5#3#353##5##535#5353,2ddddd2dddd2ddddddddddd2&X3353#3#3#5##53;35ddd2d2dd222Xddddddddd,&3335353###3##5#535#5#d2d2d2d2dd2d22ddddddddddd3##533##53,d2d22d2d2ddd2& #!3#5#33##!5#5335#5#53335,2d2222d222 ddddddddddd,dd& 3#73#dddd dddX +17;!3#5!###3!53533###!5#5#53353533#5+33#73#^222222^222222222222d2dd2d22 ddddddddd,dddddd,dddddd&!3#3!5#535!5+3#35!!,222p22,22>dddddddddddd2dX3353##3#5#535##3#5#5353dddd22d22d22d22dXdddddddddddd!#5!dddd,!!dpdX =A!3#5!###3!5#535###53353#3533###!5#5#533535335^222222^d2222222222222222222 ddddddddddddd,dd,dddddd,dddd& !!3#^22 ddd 33##5;352d22dddddd2 33##5#53!!,dddpddpd2^33##3!5353535#d2d222dddddddddd2^33#3##535#535#d2d22Ȗdddddddddd,3##53^d2d2ddd83#3533#3#5###32d22d22d2d2dd,dddd28X%!###335####35#5#535;#353522d22d22d222222d2p,ddpdddddddd,^3#3#22dddd8,;#53d2d3##3,d2d2dX!3##!5#535;#3535!!,222222222ppddddddd d2dX33#3535#533###5##53535#d22d22d22ddddd22Xdddddddddddd2X9=3####53535#35#%3##533##335#5353##5#535#535335d22222222222222222d222d2222d2pddddd,ddddddddddddddddddddd2X73####53535#35#%3##53333##3#5353535##5353d222222222222222d2d22d222pddddd,ddddddddddddddddddd2&!)7;?3333##5#5###53535#535#535#%3##533#3535#5#53+35d222d22222dd2222d2d222222dddddddddddddddddddddddddddd23#3###353#!5#535353,dd2dd22d2222dddddddddddddd< n% % = : Z  x J   )Copyright (c) 2018, Tobias,,,Copyright (c) 2018, Tobias,,,teletext2teletext2MediumMediumFontForge 2.0 : teletext2 : 24-2-2018FontForge 2.0 : teletext2 : 24-2-2018teletext2teletext21.01.0teletext2teletext22  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghjikmlnoqprsutvwxzy{}|~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~uni007Funi00A0uni00ADuni00B2uni00B3uni00B9AmacronamacronAbreveabreveAogonekaogonek Ccircumflex ccircumflex Cdotaccent cdotaccentDcarondcaronDcroatEmacronemacronEbreveebreve Edotaccent edotaccentEogonekeogonekEcaronecaron Gcircumflex gcircumflex Gdotaccent gdotaccentuni0122uni0123 Hcircumflex hcircumflexHbarhbarItildeitildeImacronimacronIbreveibreveIogonekiogonekIJij Jcircumflex jcircumflexuni0136uni0137 kgreenlandicLacutelacuteuni013Buni013CLcaronlcaronLdotldotNacutenacuteuni0145uni0146Ncaronncaron napostropheEngengOmacronomacronObreveobreve Ohungarumlaut ohungarumlautRacuteracuteuni0156uni0157RcaronrcaronSacutesacute Scircumflex scircumflexuni0162uni0163TcarontcaronTbartbarUtildeutildeUmacronumacronUbreveubreveUringuring Uhungarumlaut uhungarumlautUogonekuogonek Wcircumflex wcircumflex Ycircumflex ycircumflexZacutezacute Zdotaccent zdotaccentlongsuni01B5uni01CDuni01CEuni0229uni0251uni02C9uni02CAuni02CBuni02CDuni02CFuni0370uni0371uni0372uni0373uni0374uni0375uni0376uni0377uni0378uni0379uni037Auni037Buni037Cuni037Duni037Euni037Funi0380uni0381uni0382uni0383tonos dieresistonos Alphatonos anoteleia EpsilontonosEtatonos Iotatonosuni038B Omicrontonosuni038D Upsilontonos OmegatonosiotadieresistonosAlphaBetaGammauni0394EpsilonZetaEtaThetaIotaKappaLambdaMuNuXiOmicronPiRhouni03A2SigmaTauUpsilonPhiChiPsiuni03A9 IotadieresisUpsilondieresis alphatonos epsilontonosetatonos iotatonosupsilondieresistonosalphabetagammadeltaepsilonzetaetathetaiotakappalambdauni03BCnuxiomicronrhosigma1sigmatauupsilonphichipsiomega iotadieresisupsilondieresis omicrontonos upsilontonos omegatonosuni03CFuni0400uni0401uni0402uni0403uni0404uni0405uni0406uni0407uni0408uni0409uni040Auni040Buni040Cuni040Duni040Euni040Funi0410uni0411uni0412uni0413uni0414uni0415uni0416uni0417uni0418uni0419uni041Auni041Buni041Cuni041Duni041Euni041Funi0420uni0421uni0422uni0423uni0424uni0425uni0426uni0427uni0428uni0429uni042Auni042Buni042Cuni042Duni042Euni042Funi0430uni0431uni0432uni0433uni0434uni0435uni0436uni0437uni0438uni0439uni043Auni043Buni043Cuni043Duni043Euni043Funi0440uni0441uni0442uni0443uni0444uni0445uni0446uni0447uni0448uni0449uni044Auni044Buni044Cuni044Duni044Euni044Funi0450uni0451uni0452uni0453uni0454uni0455uni0456uni0457uni0458uni0459uni045Auni045Buni045Cuni045Duni045Euni045Funi05D0uni05D1uni05D2uni05D3uni05D4uni05D5uni05D6uni05D7uni05D8uni05D9uni05DAuni05DBuni05DCuni05DDuni05DEuni05DFuni05E0uni05E1uni05E2uni05E3uni05E4uni05E5uni05E6uni05E7uni05E8uni05E9uni05EAuni05EBuni05ECuni05EDuni05EEuni05EFuni0600uni0601uni0602uni0603uni0604uni0605uni0606uni0607uni0608uni0609uni060Auni060Buni060Cuni060Duni060Euni060Funi0610uni0611uni0612uni0613uni0614uni0615uni0616uni0617uni0618uni0619uni061Auni061Buni061Cuni061Duni061Euni061Funi2016uni20A0uni20AA oneeighth threeeighths fiveeighths seveneighths arrowleftarrowup arrowright arrowdown musicalnoteuniE600uniE601uniE602uniE603uniE604uniE605uniE606uniE607uniE608uniE609uniE60AuniE60BuniE60CuniE60DuniE60EuniE60FuniE610uniE611uniE612uniE613uniE614uniE615uniE616uniE617uniE618uniE619uniE61AuniE61BuniE61CuniE61DuniE61EuniE61FuniE620uniE621uniE622uniE623uniE624uniE625uniE626uniE627uniE628uniE629uniE62AuniE62BuniE62CuniE62DuniE62EuniE62FuniE630uniE631uniE632uniE633uniE634uniE635uniE636uniE637uniE638uniE639uniE63AuniE63BuniE63CuniE63DuniE63EuniE63FuniE640uniE641uniE642uniE643uniE644uniE645uniE646uniE647uniE648uniE649uniE64AuniE64BuniE64CuniE64DuniE64EuniE64FuniE650uniE651uniE652uniE653uniE654uniE655uniE656uniE657uniE658uniE659uniE65AuniE65BuniE65CuniE65DuniE65EuniE65FuniE660uniE661uniE662uniE663uniE664uniE665uniE666uniE667uniE668uniE669uniE66AuniE66BuniE66CuniE66DuniE66EuniE66FuniE670uniE671uniE672uniE673uniE674uniE675uniE676uniE677uniE678uniE679uniE67AuniE67BuniE67CuniE67DuniE67EuniE67FuniE680uniE681uniE682uniE683uniE684uniE685uniE686uniE687uniE688uniE689uniE68AuniE68BuniE68CuniE68DuniE68EuniE68FuniE690uniE691uniE692uniE693uniE694uniE695uniE696uniE697uniE698uniE699uniE69AuniE69BuniE69CuniE69DuniE69EuniE69FuniE6A0uniE6A1uniE6A2uniE6A3uniE6A4uniE6A5uniE6A6uniE6A7uniE6A8uniE6A9uniE6AAuniE6ABuniE6ACuniE6ADuniE6AEuniE6AFuniE6B0uniE6B1uniE6B2uniE6B3uniE6B4uniE6B5uniE6B6uniE6B7uniE6B8uniE6B9uniE6BAuniE6BBuniE6BCuniE6BDuniE6BEuniE6BFuniE6C0uniE6C1uniE6C2uniE6C3uniE6C4uniE6C5uniE6C6uniE6C7uniE6C8uniE6C9uniE6CAuniE6CBuniE6CCuniE6CDuniE6CEuniE6CFuniE6D0uniE6D1uniE6D2uniE6D3uniE6D4uniE6D5uniE6D6uniE6D7uniE6D8uniE6D9uniE6DAuniE6DBuniE6DCuniE6DDuniE6DEuniE6DFuniE6E0uniE6E1uniE6E2uniE6E3uniE6E4uniE6E5uniE6E6uniE6E7uniE6E8uniE6E9uniE6EAuniE6EBuniE6ECuniE6EDuniE6EEuniE6EFuniE6F0uniE6F1uniE6F2uniE6F3uniE6F4uniE6F5uniE6F6uniE6F7uniE6F8uniE6F9uniE6FAuniE6FBuniE6FCuniE6FDuniE6FEuniE6FFuniE700uniE701uniE702uniE703uniE704uniE705uniE706uniE707uniE708uniE709uniE70AuniE70BuniE70CuniE70DuniE70EuniE70FuniE710uniE711uniE712uniE713uniE714uniE715uniE716uniE717uniE718uniE719uniE71AuniE71BuniE71CuniE71DuniE71EuniE71FuniE720uniE721uniE722uniE723uniE724uniE725uniE726uniE727uniE728uniE729uniE72AuniE72BuniE72CuniE72DuniE72EuniE72FuniE730uniE731uniE732uniE733uniE734uniE735uniE736uniE737uniE738uniE739uniE73AuniE73BuniE73CuniE73DuniE73EuniE73FuniE75FuniE800uniEE00uniEE01uniEE02uniEE03uniEE04uniEE05uniEE06uniEE07uniEE08uniEE09uniEE0AuniEE0BuniEE0CuniEE0DuniEE0EuniEE0FuniEE10uniEE11uniEE12uniEE13uniEE14uniEE15uniEE16uniEE17uniEE18uniEE19uniEE1AuniEE1BuniEE1CuniEE1DuniEE1EuniEE1FuniEE20uniEE21uniEE22uniEE23uniEE24uniEE25uniEE26uniEE27uniEE28uniEE29uniEE2AuniEE2BuniEE2CuniEE2DuniEE2EuniEE2FuniEE30uniEE31uniEE32uniEE33uniEE34uniEE35uniEE36uniEE37uniEE38uniEE39uniEE3AuniEE3BuniEE3CuniEE3DuniEE3EuniEE3FuniEE40uniEE41uniEE42uniEE43uniEE44uniEE45uniEE46uniEE47uniEE48uniEE49uniEE4AuniEE4BuniEE4CuniEE4DuniEE4EuniEE4FuniEE50uniEE51uniEE52uniEE53uniEE54uniEE55uniEE56uniEE57uniEE58uniEE59uniEE5AuniEE5BuniEE5CuniEE5DuniEE5EuniEE5FuniEE60uniEE61uniEE62uniEE63uniEE64uniEE65uniEE66uniEE67uniEE68uniEE69uniEE6AuniEE6BuniEE6CuniEE6DuniEE6EuniEE6FuniEE70uniEE71uniEE72uniEE73uniEE74uniEE75uniEE76uniEE77uniEE78uniEE79uniEE7AuniEE7BuniEE7CuniEE7DuniEE7EuniEE7FuniEE80uniEE81uniEE82uniEE83uniEE84uniEE85uniEE86uniEE87uniEE88uniEE89uniEE8AuniEE8BuniEE8CuniEE8DuniEE8EuniEE8FuniEE90uniEE91uniEE92uniEE93uniEE94uniEE95uniEE96uniEE97uniEE98uniEE99uniEE9AuniEE9BuniEE9CuniEE9DuniEE9EuniEE9FuniEEA0uniEEA1uniEEA2uniEEA3uniEEA4uniEEA5uniEEA6uniEEA7uniEEA8uniEEA9uniEEAAuniEEABuniEEACuniEEADuniEEAEuniEEAFuniEEB0uniEEB1uniEEB2uniEEB3uniEEB4uniEEB5uniEEB6uniEEB7uniEEB8uniEEB9uniEEBAuniEEBBuniEEBCuniEEBDuniEEBEuniEEBFuniEEC0uniEEC1uniEEC2uniEEC3uniEEC4uniEEC5uniEEC6uniEEC7uniEEC8uniEEC9uniEECAuniEECBuniEECCuniEECDuniEECEuniEECFuniEED0uniEED1uniEED2uniEED3uniEED4uniEED5uniEED6uniEED7uniEED8uniEED9uniEEDAuniEEDBuniEEDCuniEEDDuniEEDEuniEEDFuniEEE0uniEEE1uniEEE2uniEEE3uniEEE4uniEEE5uniEEE6uniEEE7uniEEE8uniEEE9uniEEEAuniEEEBuniEEECuniEEEDuniEEEEuniEEEFuniEEF0uniEEF1uniEEF2uniEEF3uniEEF4uniEEF5uniEEF6uniEEF7uniEEF8uniEEF9uniEEFAuniEEFBuniEEFCuniEEFDuniEEFEuniEEFFuniEF00uniEF01uniEF02uniEF03uniEF04uniEF05uniEF06uniEF07uniEF08uniEF09uniEF0AuniEF0BuniEF0CuniEF0DuniEF0EuniEF0FuniEF10uniEF11uniEF12uniEF13uniEF14uniEF15uniEF16uniEF17uniEF18uniEF19uniEF1AuniEF1BuniEF1CuniEF1DuniEF1EuniEF1FuniEF20uniEF21uniEF22uniEF23uniEF24uniEF25uniEF26uniEF27uniEF28uniEF29uniEF2AuniEF2BuniEF2CuniEF2DuniEF2EuniEF2FuniEF30uniEF31uniEF32uniEF33uniEF34uniEF35uniEF36uniEF37uniEF38uniEF39uniEF3AuniEF3BuniEF3CuniEF3DuniEF3EuniEF3FuniEF40uniEF41uniEF42uniEF43uniEF44uniEF45uniEF46uniEF47uniEF48uniEF49uniEF4AuniEF4BuniEF4CuniEF4DuniEF4EuniEF4FuniEF50uniEF51uniEF52uniEF53uniEF54uniEF55uniEF56uniEF57uniEF58uniEF59uniEF5AuniEF5BuniEF5CuniEF5DuniEF5EuniEF5FuniEF60uniEF61uniEF62uniEF63uniEF64uniEF65uniEF66uniEF67uniEF68uniEF69uniEF6AuniEF6BuniEF6CuniEF6DuniEF6EuniEF6FuniEF70uniEF71uniEF72uniEF73uniEF74uniEF75uniEF76uniEF77uniEF78uniEF79uniEF7AuniEF7BuniEF7CuniEF7DuniEF7EuniEF7FuniEF80uniEF81uniEF82uniEF83uniEF84uniEF85uniEF86uniEF87uniEF88uniEF89uniEF8AuniEF8BuniEF8CuniEF8DuniEF8EuniEF8FuniEF90uniEF91uniEF92uniEF93uniEF94uniEF95uniEF96uniEF97uniEF98uniEF99uniEF9AuniEF9BuniEF9CuniEF9DuniEF9EuniEF9FuniEFA0uniEFA1uniEFA2uniEFA3uniEFA4uniEFA5uniEFA6uniEFA7uniEFA8uniEFA9uniEFAAuniEFABuniEFACuniEFADuniEFAEuniEFAFuniEFB0uniEFB1uniEFB2uniEFB3uniEFB4uniEFB5uniEFB6uniEFB7uniEFB8uniEFB9uniEFBAuniEFBBuniEFBCuniEFBDuniEFBEuniEFBFuniEFC0uniEFC1uniEFC2uniEFC3uniEFC4uniEFC5uniEFC6uniEFC7uniEFC8uniEFC9uniEFCAuniEFCBuniEFCCuniEFCDuniEFCEuniEFCFuniEFD0uniEFD1uniEFD2uniEFD3uniEFD4uniEFD5uniEFD6uniEFD7uniEFD8uniEFD9uniEFDAuniEFDBuniEFDCuniEFDDuniEFDEuniEFDFuniEFE0uniEFE1uniEFE2uniEFE3uniEFE4uniEFE5uniEFE6uniEFE7uniEFE8uniEFE9uniEFEAuniEFEBuniEFECuniEFEDuniEFEEuniEFEFuniEFF0uniEFF1uniEFF2uniEFF3uniEFF4uniEFF5uniEFF6uniEFF7uniEFF8uniEFF9uniEFFAuniEFFBuniEFFCuniEFFDuniEFFEuniEFFFEַZַZvdr-plugin-osdteletext-2.3.1/txtfont.c000066400000000000000000006320261415701714300200340ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) < 2021 by TODO * * Copyright (c) 2021 by Peter Bieringer (extenions) * * * * 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 "txtfont.h" unsigned int TXT_Mask[11]= { 0x0000, // ************ **** 0x39C0, // **###**###** **** 0x39C0, // **###**###** **** 0x0000, // ************ **** 0x39C0, // **###**###** **** 0x39C0, // **###**###** **** 0x0000, // ************ **** 0x39C0, // **###**###** **** 0x39C0, // **###**###** **** 0x0000 // ************ **** }; unsigned int TXT_Font[][11]= { { // 0x20 = Leerzeichen 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x21 = ! 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x22 = " 0x0000, // ************ **** 0x39C0, // **###**###** **** 0x18C0, // ***##***##** **** 0x3180, // **##***##*** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x23 = # = NC 0x0000, // ************ **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x7FE0, // *##########* **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x7FE0, // *##########* **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x0000 // ************ **** }, { // 0x24 = $ = NC 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x6660, // *##**##**##* **** 0x6600, // *##**##***** **** 0x3FC0, // **########** **** 0x0660, // *****##**##* **** 0x6660, // *##**##**##* **** 0x3FC0, // **########** **** 0x0600, // *****##***** **** 0x0000, // ************ **** }, { // 0x25 = % 0x0000, // ************ **** 0x70C0, // *###****##** **** 0xD980, // ##*##**##*** **** 0x7300, // *###**##**** **** 0x0600, // *****##***** **** 0x0CE0, // ****##**###* **** 0x19B0, // ***##**##*## **** 0x30E0, // **##****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x26 = & 0x0000, // ************ **** 0x1E00, // ***####***** **** 0x3300, // **##**##**** **** 0x3300, // **##**##**** **** 0x1E00, // ***####***** **** 0x3330, // **##**##**## **** 0x61C0, // *##****###** **** 0x3F30, // **######**## **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x27 = ' 0x0000, // ************ **** 0x0700, // *****###**** **** 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x28 = ( 0x0000, // ************ **** 0x0700, // *****###**** **** 0x0C00, // ****##****** **** 0x1800, // ***##******* **** 0x1800, // ***##******* **** 0x1800, // ***##******* **** 0x0C00, // ****##****** **** 0x0700, // *****###**** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x29 = ) 0x0000, // ************ **** 0x0E00, // ****###***** **** 0x0300, // ******##**** **** 0x0180, // *******##*** **** 0x0180, // *******##*** **** 0x0180, // *******##*** **** 0x0300, // ******##**** **** 0x0E00, // ****###***** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x2A = * 0x0000, // ************ **** 0x0600, // *****##***** **** 0x6660, // *##**##**##* **** 0x36C0, // **##*##*##** **** 0x0F00, // ****####**** **** 0x36C0, // **##*##*##** **** 0x6660, // *##**##**##* **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x2B = + 0x0000, // ************ **** 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x2C = , 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3800, // **###******* **** 0x1800, // ***##******* **** 0x3000, // **##******** **** }, { // 0x2D = - 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x2E = . 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1800, // ***##******* **** 0x1800, // ***##******* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x2F = / 0x0000, // ************ **** 0x00C0, // ********##** **** 0x0180, // *******##*** **** 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x0C00, // ****##****** **** 0x1800, // ***##******* **** 0x3000, // **##******** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x30 = 0 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x31 = 1 0x0000, // ************ **** 0x0700, // *****###**** **** 0x1F00, // ***#####**** **** 0x0700, // *****###**** **** 0x0700, // *****###**** **** 0x0700, // *****###**** **** 0x0700, // *****###**** **** 0x0700, // *****###**** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x32 = 2 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x30E0, // **##****###* **** 0x00E0, // ********###* **** 0x01C0, // *******###** **** 0x0780, // *****####*** **** 0x1E00, // ***####***** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x33 = 3 0x0000, // ************ **** 0x3FE0, // **#########* **** 0x00C0, // ********##** **** 0x0080, // *******##*** **** 0x07E0, // *****######* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x34 = 4 0x0000, // ************ **** 0x00E0, // ********###* **** 0x03C0, // ******####** **** 0x0700, // *****###**** **** 0x1C00, // ***###****** **** 0x38E0, // **###***###* **** 0x3FE0, // **#########* **** 0x00E0, // ********###* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x35 = 5 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3FC0, // **########** **** 0x00E0, // ********###* **** 0x30E0, // **##****###* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x36 = 6 0x0000, // ************ **** 0x0700, // *****###**** **** 0x0E00, // ****###***** **** 0x1C00, // ***###****** **** 0x3FC0, // **########** **** 0x3860, // **###****##* **** 0x3860, // **###****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x37 = 7 0x0000, // ************ **** 0x7FE0, // *##########* **** 0x01C0, // *******###** **** 0x0380, // ******###*** **** 0x0700, // *****###**** **** 0x0E00, // ****###***** **** 0x1C00, // ***###****** **** 0x3800, // **###******* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x38 = 8 0x0000, // ************ **** 0x0F80, // ****#####*** **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x0F80, // ****#####*** **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x0F80, // ****#####*** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x39 = 9 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x30E0, // **##****###* **** 0x30E0, // **##****###* **** 0x1FC0, // ***#######** **** 0x0380, // ******###*** **** 0x0700, // *****###**** **** 0x0E00, // ****###***** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x3A = : 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x0000, // ************ **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x3B = ; 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x1800, // ***##******* **** }, { // 0x3C = < 0x0000, // ************ **** 0x00E0, // ********###* **** 0x0380, // ******###*** **** 0x0E00, // ****###***** **** 0x3800, // **###******* **** 0x0E00, // ****###***** **** 0x0380, // ******###*** **** 0x00E0, // ********###* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x3D = = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x3E = > 0x0000, // ************ **** 0x7000, // *###******** **** 0x1C00, // ***###****** **** 0x0700, // *****###**** **** 0x01C0, // *******###** **** 0x0700, // *****###**** **** 0x1C00, // ***###****** **** 0x7000, // *###******** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x3F = ? 0x0000, // ************ **** 0x1F80, // ***######*** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x0180, // *******##*** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x40 = § = NC 0x0000, // ************ **** 0x1F80, // ***######*** **** 0x30C0, // **##****##** **** 0x3000, // **##******** **** 0x1F80, // ***######*** **** 0x30C0, // **##****##** **** 0x1F80, // ***######*** **** 0x00C0, // ********##** **** 0x30C0, // **##****##** **** 0x1F80 // ***######*** **** }, { // 0x41 = A 0x0000, // ************ **** 0x0F00, // ****####**** **** 0x1980, // ***##**##*** **** 0x30C0, // **##****##** **** 0x6060, // *##******##* **** 0x7FE0, // *##########* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x42 = B 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x43 = C 0x0000, // ************ **** 0x0FC0, // ****######** **** 0x1860, // ***##****##* **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x1860, // ***##****##* **** 0x0FC0, // ****######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x44 = D 0x0000, // ************ **** 0x3F80, // **#######*** **** 0x30C0, // **##****##** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x30C0, // **##****##** **** 0x3F80, // **#######*** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x45 = E 0x0000, // ************ **** 0x3FE0, // **#########* **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3F80, // **#######*** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x46 = F 0x0000, // ************ **** 0x3FE0, // **#########* **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3F80, // **#######*** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x47 = G 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x33E0, // **##**#####* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x48 = H 0x0000, // ************ **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x7FE0, // *##########* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x49 = I 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4A = J 0x0000, // ************ **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4B = K 0x0000, // ************ **** 0x30E0, // **##****###* **** 0x3180, // **##***##*** **** 0x3700, // **##*###**** **** 0x3C00, // **####****** **** 0x3700, // **##*###**** **** 0x3180, // **##***##*** **** 0x30E0, // **##****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4C = L 0x0000, // ************ **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4D = M 0x0000, // ************ **** 0x70E0, // *###****###* **** 0x79E0, // *####**####* **** 0x6F60, // *##*####*##* **** 0x6660, // *##**##**##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4E = N 0x0000, // ************ **** 0x7060, // *###*****##* **** 0x7860, // *####****##* **** 0x6C60, // *##*##***##* **** 0x6660, // *##**##**##* **** 0x6360, // *##***##*##* **** 0x61E0, // *##****####* **** 0x60E0, // *##*****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4F = O 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x50 = P 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x51 = Q 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3360, // **##**##*##* **** 0x1FC0, // ***#######** **** 0x0180, // *******##*** **** 0x00E0 // ********###* **** }, { // 0x52 = R 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x3300, // **##**##**** **** 0x31C0, // **##***###** **** 0x30E0, // **##****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x53 = S 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x1FC0, // ***#######** **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x54 = T 0x0000, // ************ **** 0x7FE0, // *##########* **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x55 = U 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x56 = V 0x0000, // ************ **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x1980, // ***##**##*** **** 0x0F00, // ****####**** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x57 = W 0x0000, // ************ **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6F60, // *##*####*##* **** 0x39C0, // **###**###** **** 0x30C0, // **##****##** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x58 = X 0x0000, // ************ **** 0x30C0, // **##****##** **** 0x1980, // ***##**##*** **** 0x0F00, // ****####**** **** 0x0600, // *****##***** **** 0x0F00, // ****####**** **** 0x1980, // ***##**##*** **** 0x30C0, // **##****##** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x59 = Y 0x0000, // ************ **** 0x6060, // *##******##* **** 0x30C0, // **##****##** **** 0x1980, // ***##**##*** **** 0x0F00, // ****####**** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5A = Z 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0180, // *******##*** **** 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x0C00, // ****##****** **** 0x1800, // ***##******* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5B = Ä = NC 0x18C0, // ***##***##** **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5C = Ö = NC 0x18C0, // ***##***##** **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5D = Ü = NC 0x18C0, // ***##***##** **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5E = ^ = NC 0x0600, // *****##***** **** 0x0F00, // ****####**** **** 0x1980, // ***##**##*** **** 0x30C0, // **##****##** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5F = _ = NC 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x7FE0 // *##########* **** }, { // 0x60 = ° = NC 0x0000, // ************ **** 0x0000, // *****####*** **** 0x0000, // ****##**##** **** 0x0000, // *****####*** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x61 = a 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x7F80, // *########*** **** 0x00C0, // ********##** **** 0x3FC0, // **########** **** 0x60C0, // *##*****##** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x62 = b 0x0000, // ************ **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x37C0, // **##*#####** **** 0x3860, // **###****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x63 = c 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0FE0, // ****#######* **** 0x1800, // ***##******* **** 0x3000, // **##******** **** 0x1800, // ***##******* **** 0x0FE0, // ****#######* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x64 = d 0x0000, // ************ **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x1F60, // ***#####*##* **** 0x30E0, // **##****###* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FE0, // ***########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x65 = e 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3000, // **##******** **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x66 = f 0x0000, // ************ **** 0x07E0, // *****######* **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x3F80, // **#######*** **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x67 = g 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1F60, // ***#####*##* **** 0x30E0, // **##****###* **** 0x3060, // **##*****##* **** 0x30E0, // **##****###* **** 0x1F60, // ***#####*##* **** 0x0060, // *********##* **** 0x1FC0 // ***#######** **** }, { // 0x68 = h 0x0000, // ************ **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x37C0, // **##*#####** **** 0x3860, // **###****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x69 = i 0x0000, // ************ **** 0x0E00, // ****###***** **** 0x0000, // ************ **** 0x0E00, // ****###***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x1F80, // ***######*** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x6A = j 0x0000, // ************ **** 0x00E0, // ********###* **** 0x0000, // ************ **** 0x01E0, // *******####* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x3060, // **##*****##* **** 0x1FC0 // ***#######** **** }, { // 0x6B = k 0x0000, // ************ **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x30E0, // **##****###* **** 0x3180, // **##***##*** **** 0x3E00, // **#####***** **** 0x3180, // **##***##*** **** 0x30E0, // **##****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x6C = l 0x0000, // ************ **** 0x1E00, // ***####***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x6D = m 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x6DC0, // *##*##*###** **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x6E = n 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x37C0, // **##*#####** **** 0x3860, // **###****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x6F = o 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x70 = p 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x37C0, // **##*#####** **** 0x3860, // **###****##* **** 0x3060, // **##*****##* **** 0x3860, // **###****##* **** 0x37C0, // **##*#####** **** 0x3000, // **##******** **** 0x3000 // **##******** **** }, { // 0x71 = q 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1EC0, // ***####*##** **** 0x31C0, // **##***###** **** 0x30C0, // **##****##** **** 0x31C0, // **##***###** **** 0x1EC0, // ***####*##** **** 0x00C0, // ********##** **** 0x01E0 // *******####* **** }, { // 0x72 = r 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x33E0, // **##**#####* **** 0x3C00, // **####****** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x73 = s 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3000, // **##******** **** 0x1FC0, // ***#######** **** 0x0060, // *********##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x74 = t 0x0000, // ************ **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x3F80, // **#######*** **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x07E0, // *****######* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x75 = u 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x30E0, // **##****###* **** 0x1F60, // ***#####*##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x76 = v 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x6060, // *##******##* **** 0x30C0, // **##****##** **** 0x1980, // ***##**##*** **** 0x0F00, // ****####**** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x77 = w 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x6060, // *##******##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x36C0, // **##*##*##** **** 0x2980, // ***##**##*** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x78 = x 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x70E0, // *###****###* **** 0x1980, // ***##**##*** **** 0x0F00, // ****####**** **** 0x1980, // ***##**##*** **** 0x70E0, // *###****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x79 = y 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x18C0, // ***##***##** **** 0x0D80, // ****##*##*** **** 0x0700, // *****###**** **** 0x0600, // *****##***** **** 0x0C00, // ****##****** **** 0x3800 // **###******* **** }, { // 0x7A = z 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3FE0, // **#########* **** 0x0180, // *******##*** **** 0x0700, // *****###**** **** 0x0C00, // ****##****** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x7B = ä = NC 0x0000, // ************ **** 0x3180, // **##***##*** **** 0x0000, // ************ **** 0x7F80, // *########*** **** 0x00C0, // ********##** **** 0x3FC0, // **########** **** 0x60C0, // *##*****##** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x7C = ö = NC 0x0000, // ************ **** 0x18C0, // ***##***##** **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x7D = ü = NC 0x0000, // ************ **** 0x10C0, // ***##***##** **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x30E0, // **##****###* **** 0x1F60, // ***#####*##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x7E = ß = NC 0x0000, // ************ **** 0x0F80, // ****#####*** **** 0x18C0, // ***##***##** **** 0x30C0, // **##****##** **** 0x3380, // **##**###*** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x33C0, // **##**####** **** 0x3000, // **##******** **** 0x3000 // **##******** **** }, { // 0x7F = Block 0x0000, // ************ **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x80 = 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x63E0, // *##***#####* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x63E0, // *##***#####* **** 0x3000, // **##******** **** 0x1FC0, // ***#######** **** 0x0000 // ************ **** }, { // 0x81 = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0xFFF0, // ############ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x82 = 0x0000, // ************ **** 0x3000, // **##******** **** 0x7000, // *###******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3180, // **##***##*** **** 0x0300, // ******##**** **** 0x0660, // *****##**##* **** 0x07E0, // *****######* **** 0x0060 // *********##* **** }, { // 0x83 = 0x0000, // ************ **** 0x0FC0, // ****######** **** 0x1860, // ***##****##* **** 0x0C00, // ****##****** **** 0x3F00, // **######**** **** 0x0C00, // ****##****** **** 0x3E60, // **#####**##* **** 0x33C0, // **##**####** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x84 = 0x0700, // *****###**** **** 0x0D80, // ****##*##*** **** 0x0700, // *****###**** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x30E0, // **##****###* **** 0x1F60, // ***#####*##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x85 = 0x06C0, // *****##*##** **** 0x0380, // ******###*** **** 0x0000, // ************ **** 0x0FE0, // ****#######* **** 0x1800, // ***##******* **** 0x3000, // **##******** **** 0x1800, // ***##******* **** 0x0FE0, // ****#######* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x86 = 0x0D80, // ****##*##*** **** 0x0700, // *****###**** **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3000, // **##******** **** 0x1FC0, // ***#######** **** 0x0060, // *********##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x87 = 0x0D80, // ****##*##*** **** 0x0700, // *****###**** **** 0x0000, // ************ **** 0x33E0, // **##**#####* **** 0x3C00, // **####****** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x88 = 0x0000, // ************ **** 0x3980, // ***##**##*** **** 0x3980, // ***##**##*** **** 0x3980, // ***##**##*** **** 0x3980, // ***##**##*** **** 0x3980, // ***##**##*** **** 0x3980, // ***##**##*** **** 0x3980, // ***##**##*** **** 0x3980, // ***##**##*** **** 0x0000 // ************ **** }, { // 0x89 = 0x0000, // ************ **** 0x7C00, // *#####****** **** 0x0C00, // ****##****** **** 0x3800, // **###******* **** 0x0C00, // ****##****** **** 0x7980, // *####**##*** **** 0x0300, // ******##**** **** 0x0660, // *****##**##* **** 0x07E0, // *****######* **** 0x0060 // *********##* **** }, { // 0x8A = 0x0000, // ************ **** 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x8B = 0x0000, // ************ **** 0x0000, // ************ **** 0x0600, // *****##***** **** 0x1C00, // ***###****** **** 0x7FF0, // *########### **** 0x1C00, // ***###****** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x8C = 0x0000, // ************ **** 0x3000, // **##******** **** 0x7000, // *###******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x33C0, // **##**####** **** 0x0660, // *****##**##* **** 0x00C0, // ********##** **** 0x0300, // ******##**** **** 0x07E0 // *****######* **** }, { // 0x8D = 0x0000, // ************ **** 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0380, // ******###*** **** 0xFFE0, // ###########* **** 0x0380, // ******###*** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x8E = 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0F00, // ****####**** **** 0x1F80, // ***######*** **** 0x36C0, // **##*##*##** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600 // *****##***** **** }, { // 0x8F = 0x0D80, // ****##*##*** **** 0x0700, // *****###**** **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3000, // **##******** **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x90 = 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x3000, // **##******** **** 0x3F80, // **#######*** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x91 = 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3000, // **##******** **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x92 = 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x18C0, // ***##***##** **** 0x0D80, // ****##*##*** **** 0x0700, // *****###**** **** 0x0600, // *****##***** **** 0x0C00, // ****##****** **** 0x3800 // **###******* **** }, { // 0x93 = 0x0D80, // ****##*##*** **** 0x0700, // *****###**** **** 0x0000, // ************ **** 0x3FE0, // **#########* **** 0x0180, // *******##*** **** 0x0700, // *****###**** **** 0x0C00, // ****##****** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x94 = 0x0000, // ************ **** 0x6060, // *##******##* **** 0x30C0, // **##****##** **** 0x1F80, // ***######*** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x1F80, // ***######*** **** 0x30C0, // **##****##** **** 0x6060, // *##******##* **** 0x0000 // ************ **** }, { // 0x95 = 0x001B, // *******##*## **** 0x0C0E, // ****##**###* **** 0x0C00, // ****##****** **** 0x3F80, // **#######*** **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x07E0, // *****######* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x96 = 0xFFC0, // ##########** **** 0x0060, // *********##* **** 0x3E30, // **#####***## **** 0x4730, // *#***###**## **** 0x4730, // *#***###**## **** 0x7F30, // *#######**## **** 0x3E30, // **#####***## **** 0x0060, // *********##* **** 0xFFC0, // ##########** **** 0x0000 // ************ **** }, { // 0x97 = 0xFFC0, // ##########** **** 0x0860, // ****#****##* **** 0x1C30, // ***###****## **** 0x0030, // **********## **** 0x7F30, // *#######**## **** 0x0030, // **********## **** 0x1C30, // ***###****## **** 0x0860, // ****#****##* **** 0xFFC0, // ##########** **** 0x0000 // ************ **** }, { // 0x98 = 0x0000, // ************ **** 0x18C0, // ***##***##** **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x99 = 0x0E00, // ****###***** **** 0x1B00, // ***##*##**** **** 0x0E00, // ****###***** **** 0x7F80, // *########*** **** 0x00C0, // ********##** **** 0x3FC0, // **########** **** 0x60C0, // *##*****##** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x9A = 0x0000, // ************ **** 0x18C0, // ***##***##** **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x30E0, // **##****###* **** 0x1F60, // ***#####*##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x9B = 0x18C0, // ***##***##** **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x9C = 0x18C0, // ***##***##** **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x9D = 0x0700, // *****###**** **** 0x0700, // *****###**** **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x9E = 0x18C0, // ***##***##** **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x9F = _ 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x7FE0 // *##########* **** }, { // 0xA0 = 0x20a 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xA1 = 0x21a 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xA2 = 0x22a 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xA3 = 0x23a 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xA4 = 0x24a 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xA5 = 0x25a 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xA6 = 0x26a 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ ****11 }, { // 0xA7 = 0x27a 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xA8 = 0x28a 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xA9 = 0x29a 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xAA = 0x2Aa 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xAB = 0x2Ba 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xAC = 0x2Ca 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xAD = 0x2Da 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xAE = 0x2Ea 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xAF = 0x2Fa 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xB0 = 0x30a 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00 // ######****** **** }, { // 0xB1 = 0x31a 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00 // ######****** **** }, { // 0xB2 = 0x32a 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00 // ######****** **** }, { // 0xB3 = 0x33a 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00 // ######****** **** }, { // 0xB4 = 0x34a 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00 // ######****** **** }, { // 0xB5 = 0x35a 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00 // ######****** **** }, { // 0xB6 = 0x36a 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00 // ######****** **** }, { // 0xB7 = 0x37a 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00 // ######****** **** }, { // 0xB8 = 0x38a 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00 // ######****** **** }, { // 0xB9 = 0x39a 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00 // ######****** **** }, { // 0xBA = 0x3Aa 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00 // ######****** **** }, { // 0xBB = 0x3Bb 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00 // ######****** **** }, { // 0xBC = 0x3Ca 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00 // ######****** **** }, { // 0xBD = 0x3Da 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00 // ######****** **** }, { // 0xBE = 0x3Ea 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00 // ######****** **** }, { // 0xBF = 0x3Fa 0xFFFF, // ############ **** 0xFFFF, // ############ **** 0xFFFF, // ############ **** 0xFFFF, // ############ **** 0xFFFF, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00 // ######****** **** }, { // 0xC0 = 0x0600, // *****##***** **** 0x0C00, // ****##****** **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x6060, // *##******##* **** 0x7FE0, // *##########* **** 0x6000, // *##********* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xC1 = 0x0600, // *****##***** **** 0x0300, // ******##**** **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x30E0, // **##****###* **** 0x1F60, // ***#####*##* **** 0x0000 // ************ **** }, { // 0xC2 = 0x0C00, // ****##****** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x7F80, // *########*** **** 0x00C0, // ********##** **** 0x3FC0, // **########** **** 0x60C0, // *##*****##** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xC3 = 0x0000, // ************ **** 0x0FC0, // ****######** **** 0x1860, // ***##****##* **** 0x0C00, // ****##****** **** 0x3F00, // **######**** **** 0x0C00, // ****##****** **** 0x3E60, // **#####**##* **** 0x33C0, // **##**####** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xC4 = 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x6660, // *##**##**##* **** 0x6600, // *##**##***** **** 0x3FC0, // **########** **** 0x0660, // *****##**##* **** 0x6660, // *##**##**##* **** 0x3F60, // **########** **** 0x06C0, // *****##***** **** 0x0000 // ************ **** }, { // 0xC5 = 0x3CC0, // **####**##** **** 0x6780, // *##**####*** **** 0x0000, // ************ **** 0x7F80, // *########*** **** 0x00C0, // ********##** **** 0x3FC0, // **########** **** 0x60C0, // *##*****##** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xC6 = 0x3C60, // **####***##* **** 0x67C0, // *##**#####** **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xC7 = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xC8 = 0x0600, // *****##***** **** 0x0300, // ******##**** **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xC9 = 0x0600, // *****##***** **** 0x0300, // ******##**** **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3000, // **##******** **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xCA = 0x0C00, // ****##****** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0E00, // ****###***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x1F80, // ***######*** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xCB = 0x0000, // ************ **** 0x0780, // *****####*** **** 0x0CC0, // ****##**##** **** 0x0780, // *****####*** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xCC = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0FE0, // ****#######* **** 0x1800, // ***##******* **** 0x3000, // **##******** **** 0x1800, // ***##******* **** 0x0FE0, // ****#######* **** 0x0300, // ******##**** **** 0x0E00 // ****###***** **** }, { // 0xCD = 0x0000, // ************ **** 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0310, // ******###*** **** 0xFFE0, // ###########* **** 0x0310, // ******###*** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xCE = 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0F00, // ****####**** **** 0x1F80, // ***######*** **** 0x36C0, // **##*##*##** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600 // *****##***** **** }, { // 0xCF = 0x0000, // ************ **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x7FE0, // *##########* **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x7FE0, // *##########* **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x0000 // ************ **** }, { // 0xD0 = 0x0C00, // ****##****** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x7F80, // *########*** **** 0x00C0, // ********##** **** 0x3FC0, // **########** **** 0x60C0, // *##*****##** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xD1 = 0x0600, // *****##***** **** 0x0300, // ******##**** **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3000, // **##******** **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xD2 = 0x0E00, // ****###***** **** 0x1B00, // ***##*##**** **** 0x0000, // ************ **** 0x7F80, // *########*** **** 0x00C0, // ********##** **** 0x3FC0, // **########** **** 0x60C0, // *##*****##** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xD3 = 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3000, // **##******** **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xD4 = 0x0000, // ************ **** 0x1980, // ***##**##*** **** 0x0000, // ************ **** 0x0E00, // ****###***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x1F80, // ***######*** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xD5 = 0x1E60, // ***####**##* **** 0x33C0, // **##**####** **** 0x1F80, // ***######*** **** 0x30C0, // **##****##** **** 0x6060, // *##******##* **** 0x7FE0, // *##########* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xD6 = 0x1E60, // ***####**##* **** 0x33C0, // **##**####** **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xD7 = 0x0000, // ************ **** 0x0FC0, // ****######** **** 0x1860, // ***##****##* **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x1860, // ***##****##* **** 0x0FC0, // ****######** **** 0x0300, // ******##**** **** 0x0E00 // ****###***** **** }, { // 0xD8 = 0x0700, // *****###**** **** 0x0D80, // ****##*##*** **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xD9 = 0x0700, // *****###**** **** 0x0D80, // ****##*##*** **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x30E0, // **##****###* **** 0x1F60, // ***#####*##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xDA = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0FE0, // ****#######* **** 0x1800, // ***##******* **** 0x3000, // **##******** **** 0x1800, // ***##******* **** 0x0FE0, // ****#######* **** 0x0300, // ******##**** **** 0x0E00 // ****###***** **** }, { // 0xDB = 0x0000, // ************ **** 0x18C0, // ***##***##** **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3000, // **##******** **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xDC = 0x0700, // *****###**** **** 0x0D80, // ****##*##*** **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3000, // **##******** **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xDD = 0x0600, // *****##***** **** 0x0300, // ******##**** **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x30E0, // **##****###* **** 0x1F60, // ***#####*##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xDE = 0x0F00, // ****####**** **** 0x1980, // ***##**##*** **** 0x0000, // ************ **** 0x0E00, // ****###***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x1F80, // ***######*** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xDF = 0x0000, // ************ **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x7FE0, // *##########* **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x7FE0, // *##########* **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x0000 // ************ **** }, { // 0xE0 = 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xE1 = 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0600, // *****##***** **** 0x1800, // ***##******* **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x1F00, // ***######*** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xE2 = 0x0000, // ************ **** 0x18C0, // ***##***##** **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x30E0, // **##****###* **** 0x1F60, // ***#####*##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xE3 = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0FE0, // ****#######* **** 0x1800, // ***##******* **** 0x3000, // **##******** **** 0x1800, // ***##******* **** 0x0FE0, // ****#######* **** 0x0300, // ******##**** **** 0x0E00 // ****###***** **** }, { // 0xE4 = 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x6660, // *##**##**##* **** 0x6600, // *##**##***** **** 0x3FC0, // **########** **** 0x0660, // *****##**##* **** 0x6660, // *##**##**##* **** 0x3FC0, // **########** **** 0x0600, // *****##***** **** 0x0000 // ************ **** }, { // 0xE5 = 0x0000, // ************ **** 0x3F80, // **#######*** **** 0x6180, // *##****##*** **** 0x6180, // *##****##*** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x7FE0, // *##########* **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xE6 = 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xE7 = 0x1E60, // ***####**##* **** 0x33C0, // **##**####** **** 0x3860, // **###****##* **** 0x3C60, // **####***##* **** 0x3660, // **##*##**##* **** 0x3360, // **##**##*##* **** 0x31E0, // **##***####* **** 0x30E0, // **##****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xE8 = 0x1E60, // ***####**##* **** 0x33C0, // **##**####** **** 0x0000, // ************ **** 0x37C0, // **##*#####** **** 0x3860, // **###****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xE9 = 0x0600, // *****##***** **** 0x0300, // ******##**** **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3000, // **##******** **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xEA = 0x0C00, // ****##****** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x7F80, // *########*** **** 0x00C0, // ********##** **** 0x3FC0, // **########** **** 0x60C0, // *##*****##** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xEB = 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x7F80, // *########*** **** 0x00C0, // ********##** **** 0x3FC0, // **########** **** 0x60C0, // *##*****##** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xEC = 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3000, // **##******** **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xED = 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0E00, // ****###***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x1F80, // ***######*** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xEE = 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xEF = 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x30E0, // **##****###* **** 0x1F60, // ***#####*##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xF0 = 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xF1 = 0x0C00, // ****##****** **** 0x0600, // *****##***** **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xF2 = 0x0C00, // ****##****** **** 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x3000, // **##******** **** 0x3F00, // **######**** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xF3 = 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xF4 = 0x19C0, // ***##**##*** **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xF5 = 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xF6 = 0x0600, // *****##***** **** 0x0300, // ******##**** **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xF7 = 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xF8 = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3DC0, // **####*###** **** 0x0660, // *****##**##* **** 0x3FE0, // **#########* **** 0x6600, // *##**##***** **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xF9 = 0x0000, // ************ **** 0x0FE0, // ****#######* **** 0x1B00, // ***##*##**** **** 0x3300, // **##**##**** **** 0x7FC0, // *#########** **** 0x6300, // *##***##**** **** 0x6300, // *##***##**** **** 0x63E0, // *##***#####* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xFA = 0x0000, // ************ **** 0x0300, // ******##**** **** 0x0FC0, // ****######** **** 0x0180, // *******##*** **** 0x1FC0, // ***#######** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x1F80, // ***######*** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xFB = 0x0000, // ************ **** 0x3F80, // **#######*** **** 0x30C0, // **##****##** **** 0x3060, // **##*****##* **** 0x7C60, // *#####***##* **** 0x3060, // **##*****##* **** 0x30C0, // **##****##** **** 0x3F80, // **#######*** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0xFC = 0x0000, // ************ **** 0x0000, // ************ **** 0x0180, // *******##*** **** 0x3FC0, // **########** **** 0x6360, // *##***##*##* **** 0x6660, // *##**##**##* **** 0x6C60, // *##*##***##* **** 0x3FC0, // **########** **** 0x1800, // ***##******* **** 0x0000 // ************ **** }, { // 0xFD = 0x0060, // *********##* **** 0x3FC0, // **########** **** 0x61E0, // *##****####* **** 0x6360, // *##***##*##* **** 0x6660, // *##**##**##* **** 0x6C60, // *##*##***##* **** 0x7860, // *####****##* **** 0x3FC0, // **########** **** 0x6000, // *##********* **** 0x0000 // ************ **** }, { // 0xFE = 0x0000, // ************ **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3F80, // **#######*** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x3F80, // **#######*** **** 0x3000, // **##******** **** 0x3000 // **##******** **** }, { // 0xFF = 0x3C00, // **####****** **** 0x1800, // ***##******* **** 0x1F80, // ***######*** **** 0x18C0, // ***##***##** **** 0x18C0, // ***##***##** **** 0x1F80, // ***######*** **** 0x1800, // ***##******* **** 0x3C00, // **####****** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x60a = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0 // ******###### **** }, { // 0x61a = 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0 // ******###### **** }, { // 0x62a = 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0 // ******###### **** }, { // 0x63a = 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0 // ******###### **** }, { // 0x64a = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0 // ******###### **** }, { // 0x65a = 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0 // ******###### **** }, { // 0x66a = 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0 // ******###### **** }, { // 0x67a = 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0 // ******###### **** }, { // 0x68a = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0 // ******###### **** }, { // 0x69a = 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0 // ******###### **** }, { // 0x6Aa = 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0 // ******###### **** }, { // 0x6Ba = 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0 // ******###### **** }, { // 0x6Ca = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0 // ******###### **** }, { // 0x6Da = 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0 // ******###### **** }, { // 0x6Ea = 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0 // ******###### **** }, { // 0x6Fa = 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0 // ******###### **** }, { // 0x70a = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0 // ############ **** }, { // 0x71a = 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0 // ############ **** }, { // 0x72a = 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0 // ############ **** }, { // 0x73a = 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0 // ############ **** }, { // 0x74a = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0 // ############ **** }, { // 0x75a = 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0 // ############ **** }, { // 0x76a = 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0 // ############ **** }, { // 0x77a = 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0 // ############ **** }, { // 0x78a = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0 // ############ **** }, { // 0x79a = 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0 // ############ **** }, { // 0x7Aa = 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0 // ############ **** }, { // 0x7Ba = 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0 // ############ **** }, { // 0x7Ca = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0 // ############ **** }, { // 0x7Da = 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFC00, // ######****** **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0 // ############ **** }, { // 0x7Ea = 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0x03F0, // ******###### **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0 // ############ **** }, { // 0x7Fa = 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** 0xFFF0, // ############ **** } }; unsigned int TXT_Font_Cyrillic[][11]= { // Serbian/Croatian { // 0x20 = Leerzeichen 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x21 = ! 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x22 = " 0x0000, // ************ **** 0x39C0, // **###**###** **** 0x18C0, // ***##***##** **** 0x3180, // **##***##*** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x23 = # = NC 0x0000, // ************ **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x7FE0, // *##########* **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x7FE0, // *##########* **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x0000 // ************ **** }, { // 0x24 = $ = NC 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x6660, // *##**##**##* **** 0x6600, // *##**##***** **** 0x3FC0, // **########** **** 0x0660, // *****##**##* **** 0x6660, // *##**##**##* **** 0x3FC0, // **########** **** 0x0600, // *****##***** **** 0x0000, // ************ **** }, { // 0x25 = % 0x0000, // ************ **** 0x70C0, // *###****##** **** 0xD980, // ##*##**##*** **** 0x7300, // *###**##**** **** 0x0600, // *****##***** **** 0x0CE0, // ****##**###* **** 0x19B0, // ***##**##*## **** 0x30E0, // **##****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x26 = & 0x0000, // ************ **** 0x1E00, // ***####***** **** 0x3300, // **##**##**** **** 0x3300, // **##**##**** **** 0x1E00, // ***####***** **** 0x3330, // **##**##**## **** 0x61C0, // *##****###** **** 0x3F30, // **######**## **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x27 = ' 0x0000, // ************ **** 0x0700, // *****###**** **** 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x28 = ( 0x0000, // ************ **** 0x0700, // *****###**** **** 0x0C00, // ****##****** **** 0x1800, // ***##******* **** 0x1800, // ***##******* **** 0x1800, // ***##******* **** 0x0C00, // ****##****** **** 0x0700, // *****###**** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x29 = ) 0x0000, // ************ **** 0x0E00, // ****###***** **** 0x0300, // ******##**** **** 0x0180, // *******##*** **** 0x0180, // *******##*** **** 0x0180, // *******##*** **** 0x0300, // ******##**** **** 0x0E00, // ****###***** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x2A = * 0x0000, // ************ **** 0x0600, // *****##***** **** 0x6660, // *##**##**##* **** 0x36C0, // **##*##*##** **** 0x0F00, // ****####**** **** 0x36C0, // **##*##*##** **** 0x6660, // *##**##**##* **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x2B = + 0x0000, // ************ **** 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x2C = , 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3800, // **###******* **** 0x1800, // ***##******* **** 0x3000, // **##******** **** }, { // 0x2D = - 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x2E = . 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1800, // ***##******* **** 0x1800, // ***##******* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x2F = / 0x0000, // ************ **** 0x00C0, // ********##** **** 0x0180, // *******##*** **** 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x0C00, // ****##****** **** 0x1800, // ***##******* **** 0x3000, // **##******** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x30 = 0 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x31 = 1 0x0000, // ************ **** 0x0700, // *****###**** **** 0x1F00, // ***#####**** **** 0x0700, // *****###**** **** 0x0700, // *****###**** **** 0x0700, // *****###**** **** 0x0700, // *****###**** **** 0x0700, // *****###**** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x32 = 2 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x30E0, // **##****###* **** 0x00E0, // ********###* **** 0x01C0, // *******###** **** 0x0780, // *****####*** **** 0x1E00, // ***####***** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x33 = 3 0x0000, // ************ **** 0x3FE0, // **#########* **** 0x00C0, // ********##** **** 0x0080, // *******##*** **** 0x07E0, // *****######* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x34 = 4 0x0000, // ************ **** 0x00E0, // ********###* **** 0x03C0, // ******####** **** 0x0700, // *****###**** **** 0x1C00, // ***###****** **** 0x38E0, // **###***###* **** 0x3FE0, // **#########* **** 0x00E0, // ********###* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x35 = 5 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3FC0, // **########** **** 0x00E0, // ********###* **** 0x30E0, // **##****###* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x36 = 6 0x0000, // ************ **** 0x0700, // *****###**** **** 0x0E00, // ****###***** **** 0x1C00, // ***###****** **** 0x3FC0, // **########** **** 0x3860, // **###****##* **** 0x3860, // **###****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x37 = 7 0x0000, // ************ **** 0x7FE0, // *##########* **** 0x01C0, // *******###** **** 0x0380, // ******###*** **** 0x0700, // *****###**** **** 0x0E00, // ****###***** **** 0x1C00, // ***###****** **** 0x3800, // **###******* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x38 = 8 0x0000, // ************ **** 0x0F80, // ****#####*** **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x0F80, // ****#####*** **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x0F80, // ****#####*** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x39 = 9 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x30E0, // **##****###* **** 0x30E0, // **##****###* **** 0x1FC0, // ***#######** **** 0x0380, // ******###*** **** 0x0700, // *****###**** **** 0x0E00, // ****###***** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x3A = : 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x0000, // ************ **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x3B = ; 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x1800, // ***##******* **** }, { // 0x3C = < 0x0000, // ************ **** 0x00E0, // ********###* **** 0x0380, // ******###*** **** 0x0E00, // ****###***** **** 0x3800, // **###******* **** 0x0E00, // ****###***** **** 0x0380, // ******###*** **** 0x00E0, // ********###* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x3D = = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x3E = > 0x0000, // ************ **** 0x7000, // *###******** **** 0x1C00, // ***###****** **** 0x0700, // *****###**** **** 0x01C0, // *******###** **** 0x0700, // *****###**** **** 0x1C00, // ***###****** **** 0x7000, // *###******** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x3F = ? 0x0000, // ************ **** 0x1F80, // ***######*** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x0180, // *******##*** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x40 = 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FE0, // ***########* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x41 = A 0x0000, // ************ **** 0x0F00, // ****####**** **** 0x1980, // ***##**##*** **** 0x30C0, // **##****##** **** 0x6060, // *##******##* **** 0x7FE0, // *##########* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x42 = Б 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x43 = Ц 0x0000, // ************ **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x3FE0, // **#########* **** 0x0060, // *********##* **** 0x0000 // ************ **** }, { // 0x44 = Д 0x0000, // ************ **** 0x0F80, // ****#####*** **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x7FE0, // *##########* **** 0x6060, // *##******##* **** 0x0000 // ************ **** }, { // 0x45 = E 0x0000, // ************ **** 0x3FE0, // **#########* **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3F80, // **#######*** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x46 = Ф 0x0000, // ************ **** 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x3FC0, // **########** **** 0x0600, // *****##***** **** 0x0000 // ************ **** }, { // 0x47 = Г 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x48 = Х 0x0000, // ************ **** 0x30C0, // **##****##** **** 0x1980, // ***##**##*** **** 0x0F00, // ****####**** **** 0x0600, // *****##***** **** 0x0F00, // ****####**** **** 0x1980, // ***##**##*** **** 0x30C0, // **##****##** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x49 = И 0x0000, // ************ **** 0x60E0, // *##*****###* **** 0x61E0, // *##****####* **** 0x6360, // *##***##*##* **** 0x6660, // *##**##**##* **** 0x6C60, // *##*##***##* **** 0x7860, // *####****##* **** 0x7060, // *###*****##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4A = J 0x0000, // ************ **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4B = К 0x0000, // ************ **** 0x30E0, // **##****###* **** 0x3180, // **##***##*** **** 0x3700, // **##*###**** **** 0x3C00, // **####****** **** 0x3700, // **##*###**** **** 0x3180, // **##***##*** **** 0x30E0, // **##****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4C = Л 0x0000, // ************ **** 0x0FC0, // ****######** **** 0x18C0, // ***##***##** **** 0x18C0, // ***##***##** **** 0x18C0, // ***##***##** **** 0x18C0, // ***##***##** **** 0x18C0, // ***##***##** **** 0x78C0, // *####***##** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4D = М 0x0000, // ************ **** 0x70E0, // *###****###* **** 0x79E0, // *####**####* **** 0x6F60, // *##*####*##* **** 0x6660, // *##**##**##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4E = Н 0x0000, // ************ **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x7FE0, // *##########* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4F = О 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x50 = П 0x0000, // ************ **** 0x3FC0, // **########** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x51 = 0x0380, // ******###*** **** 0x3600, // **##*##***** **** 0x30E0, // **##****###* **** 0x3180, // **##***##*** **** 0x3700, // **##*###**** **** 0x3C00, // **####****** **** 0x3380, // **##**###*** **** 0x30E0, // **##****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x52 = Р 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x53 = С 0x0000, // ************ **** 0x0FC0, // ****######** **** 0x1860, // ***##****##* **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x1860, // ***##****##* **** 0x0FC0, // ****######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x54 = Т 0x0000, // ************ **** 0x7FE0, // *##########* **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x55 = У 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1fE0, // ***########* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x56 = 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x57 = 0x0180, // *******##*** **** 0x0300, // ******##**** **** 0x33E0, // **##**#####* **** 0x3C00, // **####****** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x58 = 0x0000, // ************ **** 0x1F00, // ***#####**** **** 0x3300, // **##**##**** **** 0x3300, // **##**##**** **** 0x33E0, // **##**#####* **** 0x3330, // **##**##**## **** 0x3330, // **##**##**## **** 0x73E0, // *###**#####* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x59 = 0x0000, // ************ **** 0x6300, // *##***##**** **** 0x6300, // *##***##**** **** 0x6300, // *##***##**** **** 0x7FE0, // *##########* **** 0x6330, // *##***##**## **** 0x6330, // *##***##**## **** 0x63E0, // *##***#####* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5A = З 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x0060, // *********##* **** 0x07C0, // *****#####** **** 0x0060, // *********##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5B = 0x0000, // ************ **** 0xFC00, // ######****** **** 0x3000, // **##******** **** 0x37C0, // **##*#####** **** 0x3860, // **###****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5C = 0x0000, // ************ **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x3FC0, // **########** **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5D = 0x0000, // ************ **** 0xFC00, // ######****** **** 0x3000, // **##******** **** 0x37C0, // **##*#####** **** 0x3860, // **###****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x30C0, // **##****##** **** 0x0180, // *******##*** **** 0x0000 // ************ **** }, { // 0x5E = 0x0000, // ************ **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x7FE0, // *##########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5F = 0x0000, // ************ **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x7FE0, // *##########* **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0000 // ************ **** }, { // 0x60 = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FE0, // ***########* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x61 = а 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x7F80, // *########*** **** 0x00C0, // ********##** **** 0x3FC0, // **########** **** 0x60C0, // *##*****##** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x62 = б 0x0000, // ************ **** 0x1FE0, // ***########* **** 0x0C00, // ****##****** **** 0x0380, // ******###*** **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x63 = ц 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3180, // **##***##*** **** 0x3180, // **##***##*** **** 0x3180, // **##***##*** **** 0x3180, // **##***##*** **** 0x3FE0, // **#########* **** 0x0060, // *********##* **** 0x0000, // ************ **** }, { // 0x64 = д 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0F80, // ****#####*** **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x7FE0, // *##########* **** 0x6060, // *##******##* **** 0x0000, // ************ **** }, { // 0x65 = е 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3000, // **##******** **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x66 = ф 0x0000, // ************ **** 0x0000, // ************ **** 0x0300, // ******##**** **** 0x0FC0, // ****######** **** 0x1B60, // ***##*##*##* **** 0x1B60, // ***##*##*##* **** 0x1B60, // ***##*##*##* **** 0x0FC0, // ****######** **** 0x0300, // ******##**** **** 0x0000 // ************ **** }, { // 0x67 = г 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3F80, // **#######*** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x68 = х 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x70E0, // *###****###* **** 0x1980, // ***##**##*** **** 0x0F00, // ****####**** **** 0x1980, // ***##**##*** **** 0x70E0, // *###****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x69 = и 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x30E0, // **##****###* **** 0x3160, // **##***#*##* **** 0x3260, // **##**#**##* **** 0x3460, // **##*#***##* **** 0x3860, // **###****##* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x6A = j 0x0000, // ************ **** 0x00E0, // ********###* **** 0x0000, // ************ **** 0x01E0, // *******####* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x3060, // **##*****##* **** 0x1FC0 // ***#######** **** }, { // 0x6B = к 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x30E0, // **##****###* **** 0x3180, // **##***##*** **** 0x3E00, // **#####***** **** 0x3180, // **##***##*** **** 0x30E0, // **##****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x6C = л 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x07E0, // *****######* **** 0x1860, // ***##****##* **** 0x1869, // ***##****##* **** 0x1860, // ***##****##* **** 0x7860, // *####****##* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x6D = м 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x70E0, // *###****###* **** 0x79E0, // *####**####* **** 0x6F60, // *##*####*##* **** 0x6660, // *##**##**##* **** 0x6060, // *##******##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x6E = н 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x6F = о 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x70 = п 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3FE0, // **#########* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x71 = 0x0000, // ************ **** 0x3380, // **##**###*** **** 0x3600, // **##*##***** **** 0x30E0, // **##****###* **** 0x3180, // **##***##*** **** 0x3E00, // **#####***** **** 0x3180, // **##***##*** **** 0x30E0, // **##****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x72 = р 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x37C0, // **##*#####** **** 0x3860, // **###****##* **** 0x3060, // **##*****##* **** 0x3860, // **###****##* **** 0x37C0, // **##*#####** **** 0x3000, // **##******** **** 0x3000 // **##******** **** }, { // 0x73 = с 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0FE0, // ****#######* **** 0x1800, // ***##******* **** 0x3000, // **##******** **** 0x1800, // ***##******* **** 0x0FE0, // ****#######* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x74 = т 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x75 = у 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x18C0, // ***##***##** **** 0x0D80, // ****##*##*** **** 0x0700, // *****###**** **** 0x0600, // *****##***** **** 0x0C00, // ****##****** **** 0x3800 // **###******* **** }, { // 0x76 = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x77 = 0x0180, // *******##*** **** 0x0300, // ******##**** **** 0x0000, // ************ **** 0x33E0, // **##**#####* **** 0x3C00, // **####****** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x78 = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1F00, // ***#####**** **** 0x3300, // **##**##**** **** 0x33E0, // **##**#####* **** 0x3330, // **##**##**## **** 0x73E0, // *###**#####* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x79 = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x6300, // *##***##**** **** 0x6300, // *##***##**** **** 0x7FE0, // *##########* **** 0x6330, // *##***##**## **** 0x63E0, // *##***#####* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x7A = з 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x01E0, // ******####** **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x7B = 0x0000, // ************ **** 0x0000, // ************ **** 0xFC00, // ######****** **** 0x3000, // **##******** **** 0x3780, // **##*####*** **** 0x38C0, // **###***##** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x7C = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x1F80, // ***######*** **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x7D = 0x0000, // ************ **** 0x0000, // ************ **** 0xFC00, // ######****** **** 0x3000, // **##******** **** 0x3780, // **##*####*** **** 0x38C0, // **###***##** **** 0x30C0, // **##****##** **** 0x3180, // **##***##*** **** 0x0180, // *******##*** **** 0x0000 // ************ **** }, { // 0x7E = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x7FE0, // *##########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x7F = Block 0x0000, // ************ **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, // Russian/Bulgarian { // 0x20 = Leerzeichen 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x21 = ! 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x22 = " 0x0000, // ************ **** 0x39C0, // **###**###** **** 0x18C0, // ***##***##** **** 0x3180, // **##***##*** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x23 = # = NC 0x0000, // ************ **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x7FE0, // *##########* **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x7FE0, // *##########* **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x0000 // ************ **** }, { // 0x24 = $ = NC 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x6660, // *##**##**##* **** 0x6600, // *##**##***** **** 0x3FC0, // **########** **** 0x0660, // *****##**##* **** 0x6660, // *##**##**##* **** 0x3FC0, // **########** **** 0x0600, // *****##***** **** 0x0000, // ************ **** }, { // 0x25 = % 0x0000, // ************ **** 0x70C0, // *###****##** **** 0xD980, // ##*##**##*** **** 0x7300, // *###**##**** **** 0x0600, // *****##***** **** 0x0CE0, // ****##**###* **** 0x19B0, // ***##**##*## **** 0x30E0, // **##****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x26 = ы 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3E60, // **#####**##* **** 0x3760, // **##*###*##* **** 0x3E60, // **#####**##* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x27 = ' 0x0000, // ************ **** 0x0700, // *****###**** **** 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x28 = ( 0x0000, // ************ **** 0x0700, // *****###**** **** 0x0C00, // ****##****** **** 0x1800, // ***##******* **** 0x1800, // ***##******* **** 0x1800, // ***##******* **** 0x0C00, // ****##****** **** 0x0700, // *****###**** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x29 = ) 0x0000, // ************ **** 0x0E00, // ****###***** **** 0x0300, // ******##**** **** 0x0180, // *******##*** **** 0x0180, // *******##*** **** 0x0180, // *******##*** **** 0x0300, // ******##**** **** 0x0E00, // ****###***** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x2A = * 0x0000, // ************ **** 0x0600, // *****##***** **** 0x6660, // *##**##**##* **** 0x36C0, // **##*##*##** **** 0x0F00, // ****####**** **** 0x36C0, // **##*##*##** **** 0x6660, // *##**##**##* **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x2B = + 0x0000, // ************ **** 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x2C = , 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3800, // **###******* **** 0x1800, // ***##******* **** 0x3000, // **##******** **** }, { // 0x2D = - 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x2E = . 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1800, // ***##******* **** 0x1800, // ***##******* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x2F = / 0x0000, // ************ **** 0x00C0, // ********##** **** 0x0180, // *******##*** **** 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x0C00, // ****##****** **** 0x1800, // ***##******* **** 0x3000, // **##******** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x30 = 0 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x31 = 1 0x0000, // ************ **** 0x0700, // *****###**** **** 0x1F00, // ***#####**** **** 0x0700, // *****###**** **** 0x0700, // *****###**** **** 0x0700, // *****###**** **** 0x0700, // *****###**** **** 0x0700, // *****###**** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x32 = 2 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x30E0, // **##****###* **** 0x00E0, // ********###* **** 0x01C0, // *******###** **** 0x0780, // *****####*** **** 0x1E00, // ***####***** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x33 = 3 0x0000, // ************ **** 0x3FE0, // **#########* **** 0x00C0, // ********##** **** 0x0080, // *******##*** **** 0x07E0, // *****######* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x34 = 4 0x0000, // ************ **** 0x00E0, // ********###* **** 0x03C0, // ******####** **** 0x0700, // *****###**** **** 0x1C00, // ***###****** **** 0x38E0, // **###***###* **** 0x3FE0, // **#########* **** 0x00E0, // ********###* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x35 = 5 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3FC0, // **########** **** 0x00E0, // ********###* **** 0x30E0, // **##****###* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x36 = 6 0x0000, // ************ **** 0x0700, // *****###**** **** 0x0E00, // ****###***** **** 0x1C00, // ***###****** **** 0x3FC0, // **########** **** 0x3860, // **###****##* **** 0x3860, // **###****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x37 = 7 0x0000, // ************ **** 0x7FE0, // *##########* **** 0x01C0, // *******###** **** 0x0380, // ******###*** **** 0x0700, // *****###**** **** 0x0E00, // ****###***** **** 0x1C00, // ***###****** **** 0x3800, // **###******* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x38 = 8 0x0000, // ************ **** 0x0F80, // ****#####*** **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x0F80, // ****#####*** **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x0F80, // ****#####*** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x39 = 9 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x30E0, // **##****###* **** 0x30E0, // **##****###* **** 0x1FC0, // ***#######** **** 0x0380, // ******###*** **** 0x0700, // *****###**** **** 0x0E00, // ****###***** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x3A = : 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x0000, // ************ **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x3B = ; 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x1800, // ***##******* **** }, { // 0x3C = < 0x0000, // ************ **** 0x00E0, // ********###* **** 0x0380, // ******###*** **** 0x0E00, // ****###***** **** 0x3800, // **###******* **** 0x0E00, // ****###***** **** 0x0380, // ******###*** **** 0x00E0, // ********###* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x3D = = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x3E = > 0x0000, // ************ **** 0x7000, // *###******** **** 0x1C00, // ***###****** **** 0x0700, // *****###**** **** 0x01C0, // *******###** **** 0x0700, // *****###**** **** 0x1C00, // ***###****** **** 0x7000, // *###******** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x3F = ? 0x0000, // ************ **** 0x1F80, // ***######*** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x0180, // *******##*** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x40 = Ю 0x0000, // ************ **** 0x33C0, // **##**####** **** 0x3660, // **##*##**##* **** 0x3660, // **##*##**##* **** 0x3E60, // **#####**##* **** 0x3660, // **##*##**##* **** 0x3660, // **##*##**##* **** 0x33C0, // **##**####** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x41 = A 0x0000, // ************ **** 0x0F00, // ****####**** **** 0x1980, // ***##**##*** **** 0x30C0, // **##****##** **** 0x6060, // *##******##* **** 0x7FE0, // *##########* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x42 = Б 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x43 = Ц 0x0000, // ************ **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x3FE0, // **#########* **** 0x0060, // *********##* **** 0x0000 // ************ **** }, { // 0x44 = Д 0x0000, // ************ **** 0x0F80, // ****#####*** **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x7FE0, // *##########* **** 0x6060, // *##******##* **** 0x0000 // ************ **** }, { // 0x45 = E 0x0000, // ************ **** 0x3FE0, // **#########* **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3F80, // **#######*** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x46 = Ф 0x0000, // ************ **** 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x3FC0, // **########** **** 0x0600, // *****##***** **** 0x0000 // ************ **** }, { // 0x47 = Г 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x48 = Х 0x0000, // ************ **** 0x30C0, // **##****##** **** 0x1980, // ***##**##*** **** 0x0F00, // ****####**** **** 0x0600, // *****##***** **** 0x0F00, // ****####**** **** 0x1980, // ***##**##*** **** 0x30C0, // **##****##** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x49 = И 0x0000, // ************ **** 0x60E0, // *##*****###* **** 0x61E0, // *##****####* **** 0x6360, // *##***##*##* **** 0x6660, // *##**##**##* **** 0x6C60, // *##*##***##* **** 0x7860, // *####****##* **** 0x7060, // *###*****##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4A = Й 0x0600, // *****##***** **** 0x60E0, // *##*****###* **** 0x61E0, // *##****####* **** 0x6360, // *##***##*##* **** 0x6660, // *##**##**##* **** 0x6C60, // *##*##***##* **** 0x7860, // *####****##* **** 0x7060, // *###*****##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4B = К 0x0000, // ************ **** 0x30E0, // **##****###* **** 0x3180, // **##***##*** **** 0x3700, // **##*###**** **** 0x3C00, // **####****** **** 0x3700, // **##*###**** **** 0x3180, // **##***##*** **** 0x30E0, // **##****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4C = Л 0x0000, // ************ **** 0x0FC0, // ****######** **** 0x18C0, // ***##***##** **** 0x18C0, // ***##***##** **** 0x18C0, // ***##***##** **** 0x18C0, // ***##***##** **** 0x18C0, // ***##***##** **** 0x78C0, // *####***##** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4D = М 0x0000, // ************ **** 0x70E0, // *###****###* **** 0x79E0, // *####**####* **** 0x6F60, // *##*####*##* **** 0x6660, // *##**##**##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4E = Н 0x0000, // ************ **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x7FE0, // *##########* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4F = О 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x50 = П 0x0000, // ************ **** 0x1F80, // ***######*** **** 0x3060, // **##****##** **** 0x3060, // **##****##** **** 0x3060, // **##****##** **** 0x3060, // **##****##** **** 0x3060, // **##****##** **** 0x3060, // **##****##** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x51 = Я 0x0000, // ************ **** 0x1FE0, // ***########* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FE0, // ***########* **** 0x0360, // ******##*##* **** 0x0660, // *****##**##* **** 0x3C60, // **####***##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x52 = Р 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x53 = С 0x0000, // ************ **** 0x0FC0, // ****######** **** 0x1860, // ***##****##* **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x1860, // ***##****##* **** 0x0FC0, // ****######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x54 = Т 0x0000, // ************ **** 0x7FE0, // *##########* **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x55 = У 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1fE0, // ***########* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x56 = Ж 0x0000, // ************ **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x3FC0, // **########** **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x57 = В 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x58 = Ь 0x0000, // ************ **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x59 = Ъ 0x0000, // ************ **** 0x7000, // *###******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5A = З 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x0060, // *********##* **** 0x07C0, // *****#####** **** 0x0060, // *********##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5B = Ш 0x0000, // ************ **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x7FE0, // *##########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5C = Э 0x0000, // ************ **** 0x1F80, // ***######*** **** 0x30C0, // **##****##** **** 0x0060, // *********##* **** 0x07C0, // *****#####** **** 0x0060, // *********##* **** 0x30C0, // **##****##** **** 0x1F80, // ***######*** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5D = Щ 0x0000, // ************ **** 0x3D80, // *##*##*##*** **** 0x3D80, // *##*##*##*** **** 0x3D80, // *##*##*##*** **** 0x3D80, // *##*##*##*** **** 0x3D80, // *##*##*##*** **** 0x3D80, // *##*##*##*** **** 0x7FE0, // *##########* **** 0x0060, // *********##* **** 0x0000 // ************ **** }, { // 0x5E = Ч 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FE0, // ***########* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5F = Ы 0x0000, // ************ **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x7E60, // *######**##* **** 0x6360, // *##***##*##* **** 0x6360, // *##***##*##* **** 0x7E60, // *######**##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x60 = ю 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x33C0, // **##**####** **** 0x3660, // **##*##**##* **** 0x3E60, // **#####**##* **** 0x3660, // **##*##**##* **** 0x33C0, // **##**####** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x61 = а 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x7F80, // *########*** **** 0x00C0, // ********##** **** 0x3FC0, // **########** **** 0x60C0, // *##*****##** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x62 = б 0x0000, // ************ **** 0x1FE0, // ***########* **** 0x0C00, // ****##****** **** 0x0380, // ******###*** **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x63 = ц 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3180, // **##***##*** **** 0x3180, // **##***##*** **** 0x3180, // **##***##*** **** 0x3180, // **##***##*** **** 0x3FE0, // **#########* **** 0x0060, // *********##* **** 0x0000, // ************ **** }, { // 0x64 = д 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0F80, // ****#####*** **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x7FE0, // *##########* **** 0x6060, // *##******##* **** 0x0000, // ************ **** }, { // 0x65 = е 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3000, // **##******** **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x66 = ф 0x0000, // ************ **** 0x0000, // ************ **** 0x0300, // ******##**** **** 0x0FC0, // ****######** **** 0x1B60, // ***##*##*##* **** 0x1B60, // ***##*##*##* **** 0x1B60, // ***##*##*##* **** 0x0FC0, // ****######** **** 0x0300, // ******##**** **** 0x0000 // ************ **** }, { // 0x67 = г 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3F80, // **#######*** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x68 = х 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x70E0, // *###****###* **** 0x1980, // ***##**##*** **** 0x0F00, // ****####**** **** 0x1980, // ***##**##*** **** 0x70E0, // *###****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x69 = и 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x30E0, // **##****###* **** 0x3160, // **##***#*##* **** 0x3260, // **##**#**##* **** 0x3460, // **##*#***##* **** 0x3860, // **###****##* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x6A = й 0x0000, // ************ **** 0x0000, // ************ **** 0x0200, // ******#***** **** 0x30E0, // **##****###* **** 0x3160, // **##***#*##* **** 0x3260, // **##**#**##* **** 0x3460, // **##*#***##* **** 0x3860, // **###****##* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x6B = к 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x30E0, // **##****###* **** 0x3180, // **##***##*** **** 0x3E00, // **#####***** **** 0x3180, // **##***##*** **** 0x30E0, // **##****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x6C = л 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x07E0, // *****######* **** 0x1860, // ***##****##* **** 0x1869, // ***##****##* **** 0x1860, // ***##****##* **** 0x7860, // *####****##* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x6D = м 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x70E0, // *###****###* **** 0x79E0, // *####**####* **** 0x6F60, // *##*####*##* **** 0x6660, // *##**##**##* **** 0x6060, // *##******##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x6E = н 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x6F = о 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x70 = п 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x37C0, // **##*#####** **** 0x3860, // **###****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x71 = я 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1FE0, // ***########* **** 0x3860, // **###****##* **** 0x1FE0, // ***########* **** 0x0360, // ******##*##* **** 0x1C60, // ***###***##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x72 = р 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x37C0, // **##*#####** **** 0x3860, // **###****##* **** 0x3060, // **##*****##* **** 0x3860, // **###****##* **** 0x37C0, // **##*#####** **** 0x3000, // **##******** **** 0x3000 // **##******** **** }, { // 0x73 = с 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0FE0, // ****#######* **** 0x1800, // ***##******* **** 0x3000, // **##******** **** 0x1800, // ***##******* **** 0x0FE0, // ****#######* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x74 = т 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x75 = у 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x18C0, // ***##***##** **** 0x0D80, // ****##*##*** **** 0x0700, // *****###**** **** 0x0600, // *****##***** **** 0x0C00, // ****##****** **** 0x3800 // **###******* **** }, { // 0x76 = ж 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x1F80, // ***######*** **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x77 = в 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x78 = ь 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x79 = ъ 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x7000, // *###******** **** 0x3000, // **##******** **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x7A = з 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x01E0, // ******####** **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x7B = ш 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x7FE0, // *##########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x7C = э 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x03E0, // ******#####* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x7D = щ 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x6D80, // *##*##*##*** **** 0x6D80, // *##*##*##*** **** 0x6D80, // *##*##*##*** **** 0x6D80, // *##*##*##*** **** 0x7FE0, // *##########* **** 0x0060, // *********##* **** 0x0000 // ************ **** }, { // 0x7E = ч 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FE0, // ***########* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x7F = Block 0x0000, // ************ **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, // Ukrainian { // 0x20 = Leerzeichen 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x21 = ! 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x22 = " 0x0000, // ************ **** 0x39C0, // **###**###** **** 0x18C0, // ***##***##** **** 0x3180, // **##***##*** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x23 = # = NC 0x0000, // ************ **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x7FE0, // *##########* **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x7FE0, // *##########* **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x0000 // ************ **** }, { // 0x24 = $ = NC 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x6660, // *##**##**##* **** 0x6600, // *##**##***** **** 0x3FC0, // **########** **** 0x0660, // *****##**##* **** 0x6660, // *##**##**##* **** 0x3FC0, // **########** **** 0x0600, // *****##***** **** 0x0000, // ************ **** }, { // 0x25 = % 0x0000, // ************ **** 0x70C0, // *###****##** **** 0xD980, // ##*##**##*** **** 0x7300, // *###**##**** **** 0x0600, // *****##***** **** 0x0CE0, // ****##**###* **** 0x19B0, // ***##**##*## **** 0x30E0, // **##****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x26 = 0x0F00, // ************ **** 0x1980, // ***##**##*** **** 0x0000, // ************ **** 0x0E00, // ****###***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x1F80, // ***######*** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x27 = ' 0x0000, // ************ **** 0x0700, // *****###**** **** 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x28 = ( 0x0000, // ************ **** 0x0700, // *****###**** **** 0x0C00, // ****##****** **** 0x1800, // ***##******* **** 0x1800, // ***##******* **** 0x1800, // ***##******* **** 0x0C00, // ****##****** **** 0x0700, // *****###**** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x29 = ) 0x0000, // ************ **** 0x0E00, // ****###***** **** 0x0300, // ******##**** **** 0x0180, // *******##*** **** 0x0180, // *******##*** **** 0x0180, // *******##*** **** 0x0300, // ******##**** **** 0x0E00, // ****###***** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x2A = * 0x0000, // ************ **** 0x0600, // *****##***** **** 0x6660, // *##**##**##* **** 0x36C0, // **##*##*##** **** 0x0F00, // ****####**** **** 0x36C0, // **##*##*##** **** 0x6660, // *##**##**##* **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x2B = + 0x0000, // ************ **** 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x2C = , 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3800, // **###******* **** 0x1800, // ***##******* **** 0x3000, // **##******** **** }, { // 0x2D = - 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x2E = . 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1800, // ***##******* **** 0x1800, // ***##******* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x2F = / 0x0000, // ************ **** 0x00C0, // ********##** **** 0x0180, // *******##*** **** 0x0300, // ******##**** **** 0x0600, // *****##***** **** 0x0C00, // ****##****** **** 0x1800, // ***##******* **** 0x3000, // **##******** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x30 = 0 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x31 = 1 0x0000, // ************ **** 0x0700, // *****###**** **** 0x1F00, // ***#####**** **** 0x0700, // *****###**** **** 0x0700, // *****###**** **** 0x0700, // *****###**** **** 0x0700, // *****###**** **** 0x0700, // *****###**** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x32 = 2 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x30E0, // **##****###* **** 0x00E0, // ********###* **** 0x01C0, // *******###** **** 0x0780, // *****####*** **** 0x1E00, // ***####***** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x33 = 3 0x0000, // ************ **** 0x3FE0, // **#########* **** 0x00C0, // ********##** **** 0x0080, // *******##*** **** 0x07E0, // *****######* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x34 = 4 0x0000, // ************ **** 0x00E0, // ********###* **** 0x03C0, // ******####** **** 0x0700, // *****###**** **** 0x1C00, // ***###****** **** 0x38E0, // **###***###* **** 0x3FE0, // **#########* **** 0x00E0, // ********###* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x35 = 5 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3FC0, // **########** **** 0x00E0, // ********###* **** 0x30E0, // **##****###* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x36 = 6 0x0000, // ************ **** 0x0700, // *****###**** **** 0x0E00, // ****###***** **** 0x1C00, // ***###****** **** 0x3FC0, // **########** **** 0x3860, // **###****##* **** 0x3860, // **###****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x37 = 7 0x0000, // ************ **** 0x7FE0, // *##########* **** 0x01C0, // *******###** **** 0x0380, // ******###*** **** 0x0700, // *****###**** **** 0x0E00, // ****###***** **** 0x1C00, // ***###****** **** 0x3800, // **###******* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x38 = 8 0x0000, // ************ **** 0x0F80, // ****#####*** **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x0F80, // ****#####*** **** 0x38E0, // **###***###* **** 0x38E0, // **###***###* **** 0x0F80, // ****#####*** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x39 = 9 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x30E0, // **##****###* **** 0x30E0, // **##****###* **** 0x1FC0, // ***#######** **** 0x0380, // ******###*** **** 0x0700, // *****###**** **** 0x0E00, // ****###***** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x3A = : 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x0000, // ************ **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x3B = ; 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0C00, // ****##****** **** 0x0C00, // ****##****** **** 0x1800, // ***##******* **** }, { // 0x3C = < 0x0000, // ************ **** 0x00E0, // ********###* **** 0x0380, // ******###*** **** 0x0E00, // ****###***** **** 0x3800, // **###******* **** 0x0E00, // ****###***** **** 0x0380, // ******###*** **** 0x00E0, // ********###* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x3D = = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x3E = > 0x0000, // ************ **** 0x7000, // *###******** **** 0x1C00, // ***###****** **** 0x0700, // *****###**** **** 0x01C0, // *******###** **** 0x0700, // *****###**** **** 0x1C00, // ***###****** **** 0x7000, // *###******** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x3F = ? 0x0000, // ************ **** 0x1F80, // ***######*** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x0180, // *******##*** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x40 = Ю 0x0000, // ************ **** 0x1F80, // **##**####** **** 0x30C0, // **##*##**##* **** 0x3000, // **##*##**##* **** 0x1F80, // **#####**##* **** 0x30C0, // **##*##**##* **** 0x1F80, // **##*##**##* **** 0x00C0, // **##**####** **** 0x30C0, // ************ **** 0x1F80 // ************ **** }, { // 0x41 = A 0x0000, // ************ **** 0x0F00, // ****####**** **** 0x1980, // ***##**##*** **** 0x30C0, // **##****##** **** 0x6060, // *##******##* **** 0x7FE0, // *##########* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x42 = Б 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x43 = Ц 0x0000, // ************ **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x30C0, // **##****##** **** 0x3FE0, // **#########* **** 0x0060, // *********##* **** 0x0000 // ************ **** }, { // 0x44 = Д 0x0000, // ************ **** 0x0F80, // ****#####*** **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x7FE0, // *##########* **** 0x6060, // *##******##* **** 0x0000 // ************ **** }, { // 0x45 = E 0x0000, // ************ **** 0x3FE0, // **#########* **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3F80, // **#######*** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x46 = Ф 0x0000, // ************ **** 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x3FC0, // **########** **** 0x0600, // *****##***** **** 0x0000 // ************ **** }, { // 0x47 = Г 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x48 = Х 0x0000, // ************ **** 0x30C0, // **##****##** **** 0x1980, // ***##**##*** **** 0x0F00, // ****####**** **** 0x0600, // *****##***** **** 0x0F00, // ****####**** **** 0x1980, // ***##**##*** **** 0x30C0, // **##****##** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x49 = И 0x0000, // ************ **** 0x60E0, // *##*****###* **** 0x61E0, // *##****####* **** 0x6360, // *##***##*##* **** 0x6660, // *##**##**##* **** 0x6C60, // *##*##***##* **** 0x7860, // *####****##* **** 0x7060, // *###*****##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4A = Й 0x0600, // *****##***** **** 0x60E0, // *##*****###* **** 0x61E0, // *##****####* **** 0x6360, // *##***##*##* **** 0x6660, // *##**##**##* **** 0x6C60, // *##*##***##* **** 0x7860, // *####****##* **** 0x7060, // *###*****##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4B = К 0x0000, // ************ **** 0x30E0, // **##****###* **** 0x3180, // **##***##*** **** 0x3700, // **##*###**** **** 0x3C00, // **####****** **** 0x3700, // **##*###**** **** 0x3180, // **##***##*** **** 0x30E0, // **##****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4C = Л 0x0000, // ************ **** 0x0FC0, // ****######** **** 0x18C0, // ***##***##** **** 0x18C0, // ***##***##** **** 0x18C0, // ***##***##** **** 0x18C0, // ***##***##** **** 0x18C0, // ***##***##** **** 0x78C0, // *####***##** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4D = М 0x0000, // ************ **** 0x70E0, // *###****###* **** 0x79E0, // *####**####* **** 0x6F60, // *##*####*##* **** 0x6660, // *##**##**##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4E = Н 0x0000, // ************ **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x7FE0, // *##########* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x6060, // *##******##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x4F = О 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x50 = П 0x0000, // ************ **** 0x1F80, // ***######*** **** 0x3060, // **##****##** **** 0x3060, // **##****##** **** 0x3060, // **##****##** **** 0x3060, // **##****##** **** 0x3060, // **##****##** **** 0x3060, // **##****##** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x51 = Я 0x0000, // ************ **** 0x1FE0, // ***########* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FE0, // ***########* **** 0x0360, // ******##*##* **** 0x0660, // *****##**##* **** 0x3C60, // **####***##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x52 = Р 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x53 = С 0x0000, // ************ **** 0x0FC0, // ****######** **** 0x1860, // ***##****##* **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x1860, // ***##****##* **** 0x0FC0, // ****######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x54 = Т 0x0000, // ************ **** 0x7FE0, // *##########* **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x55 = У 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1fE0, // ***########* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x56 = Ж 0x0000, // ************ **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x3FC0, // **########** **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x57 = В 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x58 = Ь 0x0000, // ************ **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x59 = 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5A = З 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x0060, // *********##* **** 0x07C0, // *****#####** **** 0x0060, // *********##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5B = Ш 0x0000, // ************ **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x7FE0, // *##########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5C = 0x0000, // ************ **** 0x1F80, // ***######*** **** 0x30C0, // **##****##** **** 0x6000, // *##********* **** 0x3E00, // **#####***** **** 0x6000, // *##********* **** 0x30C0, // **##****##** **** 0x1F80, // ***######*** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5D = Щ 0x0000, // ************ **** 0x3D80, // *##*##*##*** **** 0x3D80, // *##*##*##*** **** 0x3D80, // *##*##*##*** **** 0x3D80, // *##*##*##*** **** 0x3D80, // *##*##*##*** **** 0x3D80, // *##*##*##*** **** 0x7FE0, // *##########* **** 0x0060, // *********##* **** 0x0000 // ************ **** }, { // 0x5E = Ч 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FE0, // ***########* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x5F = 0x19C0, // ***##**##*** **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x60 = ю 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x33C0, // **##**####** **** 0x3660, // **##*##**##* **** 0x3E60, // **#####**##* **** 0x3660, // **##*##**##* **** 0x33C0, // **##**####** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x61 = а 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x7F80, // *########*** **** 0x00C0, // ********##** **** 0x3FC0, // **########** **** 0x60C0, // *##*****##** **** 0x3FE0, // **#########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x62 = б 0x0000, // ************ **** 0x1FE0, // ***########* **** 0x0C00, // ****##****** **** 0x0380, // ******###*** **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x63 = ц 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3180, // **##***##*** **** 0x3180, // **##***##*** **** 0x3180, // **##***##*** **** 0x3180, // **##***##*** **** 0x3FE0, // **#########* **** 0x0060, // *********##* **** 0x0000, // ************ **** }, { // 0x64 = д 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0F80, // ****#####*** **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x1980, // ***##**##*** **** 0x7FE0, // *##########* **** 0x6060, // *##******##* **** 0x0000, // ************ **** }, { // 0x65 = е 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3000, // **##******** **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x66 = ф 0x0000, // ************ **** 0x0000, // ************ **** 0x0300, // ******##**** **** 0x0FC0, // ****######** **** 0x1B60, // ***##*##*##* **** 0x1B60, // ***##*##*##* **** 0x1B60, // ***##*##*##* **** 0x0FC0, // ****######** **** 0x0300, // ******##**** **** 0x0000 // ************ **** }, { // 0x67 = г 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3F80, // **#######*** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x68 = х 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x70E0, // *###****###* **** 0x1980, // ***##**##*** **** 0x0F00, // ****####**** **** 0x1980, // ***##**##*** **** 0x70E0, // *###****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x69 = и 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x30E0, // **##****###* **** 0x3160, // **##***#*##* **** 0x3260, // **##**#**##* **** 0x3460, // **##*#***##* **** 0x3860, // **###****##* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x6A = й 0x0000, // ************ **** 0x0000, // ************ **** 0x0200, // ******#***** **** 0x30E0, // **##****###* **** 0x3160, // **##***#*##* **** 0x3260, // **##**#**##* **** 0x3460, // **##*#***##* **** 0x3860, // **###****##* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x6B = к 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x30E0, // **##****###* **** 0x3180, // **##***##*** **** 0x3E00, // **#####***** **** 0x3180, // **##***##*** **** 0x30E0, // **##****###* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x6C = л 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x07E0, // *****######* **** 0x1860, // ***##****##* **** 0x1869, // ***##****##* **** 0x1860, // ***##****##* **** 0x7860, // *####****##* **** 0x0000, // ************ **** 0x0000, // ************ **** }, { // 0x6D = м 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x70E0, // *###****###* **** 0x79E0, // *####**####* **** 0x6F60, // *##*####*##* **** 0x6660, // *##**##**##* **** 0x6060, // *##******##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x6E = н 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3FE0, // **#########* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x6F = о 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x70 = п 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x37C0, // **##*#####** **** 0x3860, // **###****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x71 = я 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1FE0, // ***########* **** 0x3860, // **###****##* **** 0x1FE0, // ***########* **** 0x0360, // ******##*##* **** 0x1C60, // ***###***##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x72 = р 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x37C0, // **##*#####** **** 0x3860, // **###****##* **** 0x3060, // **##*****##* **** 0x3860, // **###****##* **** 0x37C0, // **##*#####** **** 0x3000, // **##******** **** 0x3000 // **##******** **** }, { // 0x73 = с 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x0FE0, // ****#######* **** 0x1800, // ***##******* **** 0x3000, // **##******** **** 0x1800, // ***##******* **** 0x0FE0, // ****#######* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x74 = т 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x75 = у 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x18C0, // ***##***##** **** 0x0D80, // ****##*##*** **** 0x0700, // *****###**** **** 0x0600, // *****##***** **** 0x0C00, // ****##****** **** 0x3800 // **###******* **** }, { // 0x76 = ж 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x1F80, // ***######*** **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x77 = в 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x78 = ь 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3000, // **##******** **** 0x3000, // **##******** **** 0x3FC0, // **########** **** 0x3060, // **##*****##* **** 0x3FC0, // **########** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x79 = 0x0000, // ************ **** 0x0E00, // ****###***** **** 0x0000, // ************ **** 0x0E00, // ****###***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x0600, // *****##***** **** 0x1F80, // ***######*** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x7A = з 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x1FC0, // ***#######** **** 0x3060, // **##*****##* **** 0x01E0, // ******####** **** 0x3060, // **##*****##* **** 0x1FC0, // ***#######** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x7B = ш 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x6660, // *##**##**##* **** 0x7FE0, // *##########* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x7C = 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3F80, // **#######*** **** 0x60C0, // *##*****##** **** 0x7C00, // *#####****** **** 0x60C0, // *##*****##** **** 0x3F80, // **#######*** **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x7D = щ 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x6D80, // *##*##*##*** **** 0x6D80, // *##*##*##*** **** 0x6D80, // *##*##*##*** **** 0x6D80, // *##*##*##*** **** 0x7FE0, // *##########* **** 0x0060, // *********##* **** 0x0000 // ************ **** }, { // 0x7E = ч 0x0000, // ************ **** 0x0000, // ************ **** 0x0000, // ************ **** 0x3060, // **##*****##* **** 0x3060, // **##*****##* **** 0x1FE0, // ***########* **** 0x0060, // *********##* **** 0x0060, // *********##* **** 0x0000, // ************ **** 0x0000 // ************ **** }, { // 0x7F = Block 0x0000, // ************ **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x7FE0, // *##########* **** 0x0000, // ************ **** 0x0000 // ************ **** } }; int NationalOptionSubsetG0Default[13]= {0x23,0xa4,0x40,0 ,0 ,0 ,0x5e,0x5f,0 ,0 ,0 ,0 ,0 }; int NationalOptionSubsetCZ_SK[13]= {0x23,0x84,0x85,0x95,0x93,0x92,0xed,0x87,0x91,0xeb,0x8f,0xef,0x86}; int NationalOptionSubsetEN[13]= {0x83,0x24,0x80,0x8b,0x8c,0x8d,0x8e,0x23,0x81,0x82,0x88,0x89,0x8a}; int NationalOptionSubsetEE[13]= {0x23,0xc6,0 ,0x5b,0x5c,0 ,0x5d,0xd6,0 ,0x7b,0x7c,0 ,0x7d}; int NationalOptionSubsetFR[13]= {0xe9,0xef,0xe0,0xeb,0xea,0xf9,0xee,0x23,0xe8,0xe2,0xf4,0xfb,0xe7}; int NationalOptionSubsetDE[13]= {0x23,0x24,0xa7,0xc4,0xd6,0xdc,0x5e,0x5f,0xb0,0xe4,0xf6,0xfc,0xdf}; int NationalOptionSubsetIT[13]= {0xa3,0x24,0xe9,0xb0,0xe7,0x8d,0x8e,0x23,0xf9,0xe0,0xf2,0xe8,0xec}; // no arrows as max char is 0xff int NationalOptionSubsetLV_LT[13]= {0x23,0x24,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 }; int NationalOptionSubsetPL[13]= {0x23,0 ,0 ,0 ,0 ,0 ,0 ,0xee,0 ,0 ,0 ,0 ,0 }; int NationalOptionSubsetPT_ES[13]= {0x23,0x24,0xa1,0xe1,0xe9,0xed,0xf3,0xfa,0xbf,0xfc,0xf1,0xe8,0xe0}; int NationalOptionSubsetRO[13]= {0x23,0x94,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0xd2,0 ,0 ,0xde}; int NationalOptionSubsetSR_HR_SL[13]= {0x23,0 ,0 ,0 ,0 ,0xfb,0 ,0xdb,0 ,0 ,0 ,0 ,0 }; int NationalOptionSubsetSV_FI[13]= {0x23,0xa4,0xc9,0xc4,0xd6,0xc5,0xdc,0x5f,0xe9,0xe4,0xf6,0xe5,0xfc}; int NationalOptionSubsetTR[13]= {0 ,0 ,0 ,0 ,0x5c,0xd7,0x5d,0 ,0 ,0 ,0x7c,0xcc,0x7d}; int CyrillicOptionRU_BG[96] = {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x44b,0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x42e,0x410,0x411,0x426,0x414,0x415,0x424,0x413,0x425,0x418,0x419,0x41a,0x41b,0x41c,0x41d,0x41e, 0x41f,0x42f,0x420,0x421,0x422,0x423,0x416,0x412,0x42c,0x42a,0x417,0x428,0x42d,0x429,0x427,0x42b, 0x44e,0x430,0x431,0x446,0x434,0x435,0x444,0x433,0x445,0x438,0x439,0x43a,0x43b,0x43c,0x43d,0x43e, 0x43f,0x44f,0x440,0x441,0x442,0x443,0x436,0x432,0x44c,0x44a,0x437,0x448,0x437,0x449,0x447,0x7f}; inline int NationalOptionSubset(int chr) { switch (chr) { case 0x23: return 0; case 0x24: return 1; case 0x40: return 2; case 0x5b: return 3; case 0x5c: return 4; case 0x5d: return 5; case 0x5e: return 6; case 0x5f: return 7; case 0x60: return 8; case 0x7b: return 9; case 0x7c: return 10; case 0x7d: return 11; case 0x7e: return 12; } return -1; } inline unsigned int LeftBits(unsigned int bits) { // Scale bit positions 0xfc00 to 0xfff0 positions unsigned int res=0; if (bits&0x8000) res|=0xC000; if (bits&0x4000) res|=0x3000; if (bits&0x2000) res|=0x0C00; if (bits&0x1000) res|=0x0300; if (bits&0x0800) res|=0x00C0; if (bits&0x0400) res|=0x0030; return res; } inline unsigned int RightBits(unsigned int bits) { // Scale bit positions 0x03f0 to 0xfff0 positions unsigned int res=0; if (bits&0x0200) res|=0xC000; if (bits&0x0100) res|=0x3000; if (bits&0x0080) res|=0x0C00; if (bits&0x0040) res|=0x0300; if (bits&0x0020) res|=0x00C0; if (bits&0x0010) res|=0x0030; return res; } unsigned int* GetFontChar(cTeletextChar c, unsigned int *buffer) { // Get character bitmap for character/charset enumCharsets font=c.GetCharset(); int chr=c.GetChar(); unsigned int *bitmap=NULL; int i; int NationalOption=NationalOptionSubset(chr); switch (font) { case CHARSET_LATIN_G0: if (NationalOption>=0) { if (NationalOptionSubsetG0Default[NationalOption]>0) bitmap=TXT_Font[NationalOptionSubsetG0Default[NationalOption]-0x20]; } else { if (chr>=0x20 && chr<0x80) { bitmap=TXT_Font[chr-0x20]; } } break; case CHARSET_LATIN_G0_EN: if (NationalOption>=0) { if (NationalOptionSubsetEN[NationalOption]>0) bitmap=TXT_Font[NationalOptionSubsetEN[NationalOption]-0x20]; } else { if (chr>=0x20 && chr<0x80) { bitmap=TXT_Font[chr-0x20]; } } break; case CHARSET_LATIN_G0_FR: if (NationalOption>=0) { if (NationalOptionSubsetFR[NationalOption]>0) bitmap=TXT_Font[NationalOptionSubsetFR[NationalOption]-0x20]; } else { if (chr>=0x20 && chr<0x80) { bitmap=TXT_Font[chr-0x20]; } } break; case CHARSET_LATIN_G0_IT: if (NationalOption>=0) { if (NationalOptionSubsetIT[NationalOption]>0) bitmap=TXT_Font[NationalOptionSubsetIT[NationalOption]-0x20]; } else { if (chr>=0x20 && chr<0x80) { bitmap=TXT_Font[chr-0x20]; } } break; case CHARSET_LATIN_G0_PT_ES: if (NationalOption>=0) { if (NationalOptionSubsetPT_ES[NationalOption]>0) bitmap=TXT_Font[NationalOptionSubsetPT_ES[NationalOption]-0x20]; } else { if (chr>=0x20 && chr<0x80) { bitmap=TXT_Font[chr-0x20]; } } break; case CHARSET_LATIN_G0_SV_FI: if (NationalOption>=0) { if (NationalOptionSubsetSV_FI[NationalOption]>0) bitmap=TXT_Font[NationalOptionSubsetSV_FI[NationalOption]-0x20]; } else { if (chr>=0x20 && chr<0x80) { bitmap=TXT_Font[chr-0x20]; } } break; case CHARSET_LATIN_G0_DE: if (chr>=0x20 && chr<0x80) { bitmap=TXT_Font[chr-0x20]; } break; case CHARSET_LATIN_G0_CZ_SK: if (NationalOption>=0) { if (NationalOptionSubsetCZ_SK[NationalOption]>0) bitmap=TXT_Font[NationalOptionSubsetCZ_SK[NationalOption]-0x20]; } else { if (chr>=0x20 && chr<0x80) { bitmap=TXT_Font[chr-0x20]; } } break; case CHARSET_LATIN_G0_EE: case CHARSET_LATIN_G0_LV_LT: case CHARSET_LATIN_G0_PL: case CHARSET_LATIN_G0_RO: case CHARSET_LATIN_G0_SR_HR_SL: case CHARSET_LATIN_G0_TR: // Partially supported latin charsets if (chr>=0x20 && chr<0x80 && NationalOption<0) { bitmap=TXT_Font[chr-0x20]; } break; case CHARSET_LATIN_G2: break; case CHARSET_CYRILLIC_G0_SR_HR: if (chr>=0x20 && chr<0x80) { bitmap=TXT_Font_Cyrillic[chr-0x20]; } break; case CHARSET_CYRILLIC_G0_RU_BG: if (chr>=0x20 && chr<0x80) { bitmap=TXT_Font_Cyrillic[chr-0x20+0x80]; } break; case CHARSET_CYRILLIC_G0_UK: if (chr>=0x20 && chr<0x80) { bitmap=TXT_Font_Cyrillic[chr-0x20+0x80+0x80]; } break; case CHARSET_CYRILLIC_G2: case CHARSET_GREEK_G0: case CHARSET_GREEK_G2: case CHARSET_ARABIC_G0: case CHARSET_ARABIC_G2: case CHARSET_HEBREW_G0: // totally unsupported break; case CHARSET_GRAPHICS_G1: if (chr>=0x20 && chr<0x40) { bitmap=TXT_Font[chr-0x20+0x80]; } else if (chr>=0x60 && chr<0x80) { bitmap=TXT_Font[chr-0x60+0xE0]; } break; case CHARSET_GRAPHICS_G1_SEP: if (chr>=0x20 && chr<0x40) { bitmap=TXT_Font[chr-0x20+0x80]; } else if (chr>=0x60 && chr<0x80) { bitmap=TXT_Font[chr-0x60+0xE0]; } if (bitmap) { for (i=0;i<10;i++) buffer[i]=bitmap[i]&TXT_Mask[i]; bitmap=buffer; } break; case CHARSET_GRAPHICS_G3: case CHARSET_INVALID: // Totally unsupported break; } if (!buffer) { printf("Warning: Undefined char: %x %x\n",font,chr); return NULL; } switch (c.GetDblHeight()) { case dblh_Top: // Scale top 5 lines to full height buffer[8]=buffer[9]=bitmap[4]; buffer[6]=buffer[7]=bitmap[3]; buffer[4]=buffer[5]=bitmap[2]; buffer[2]=buffer[3]=bitmap[1]; buffer[1]=buffer[0]=bitmap[0]; bitmap=buffer; break; case dblh_Bottom: // Scale bottom 5 lines to full height buffer[0]=buffer[1]=bitmap[5]; buffer[2]=buffer[3]=bitmap[6]; buffer[4]=buffer[5]=bitmap[7]; buffer[6]=buffer[7]=bitmap[8]; buffer[8]=buffer[9]=bitmap[9]; bitmap=buffer; default:; } switch (c.GetDblWidth()) { case dblw_Left: // Scale 6 left columns to full width buffer[0]=LeftBits(bitmap[0]); buffer[1]=LeftBits(bitmap[1]); buffer[2]=LeftBits(bitmap[2]); buffer[3]=LeftBits(bitmap[3]); buffer[4]=LeftBits(bitmap[4]); buffer[5]=LeftBits(bitmap[5]); buffer[6]=LeftBits(bitmap[6]); buffer[7]=LeftBits(bitmap[7]); buffer[8]=LeftBits(bitmap[8]); buffer[9]=LeftBits(bitmap[9]); bitmap=buffer; break; case dblw_Right: // Scale 6 right columns to full width buffer[0]=RightBits(bitmap[0]); buffer[1]=RightBits(bitmap[1]); buffer[2]=RightBits(bitmap[2]); buffer[3]=RightBits(bitmap[3]); buffer[4]=RightBits(bitmap[4]); buffer[5]=RightBits(bitmap[5]); buffer[6]=RightBits(bitmap[6]); buffer[7]=RightBits(bitmap[7]); buffer[8]=RightBits(bitmap[8]); buffer[9]=RightBits(bitmap[9]); bitmap=buffer; default:; } return bitmap; } unsigned int GetVTXChar(cTeletextChar c) { // convert character for character/charset to utf8 int convertedChar = 0; enumCharsets font = c.GetCharset(); int chr = c.GetChar(); int NationalOption = NationalOptionSubset(chr); switch (font) { case CHARSET_LATIN_G0: if (NationalOption>=0) { if (NationalOptionSubsetG0Default[NationalOption]>0) convertedChar = NationalOptionSubsetG0Default[NationalOption]; } else { if (chr>=0x20 && chr<0x80) { convertedChar = chr; } if (chr>=0xa0 && chr<0xff) { // pass ISO-8859-1 converted from "X/26 G0 character with diacritical mark" convertedChar = chr; } } break; case CHARSET_LATIN_G0_EN: if (NationalOption>=0) { if (NationalOptionSubsetEN[NationalOption]>0) convertedChar = NationalOptionSubsetEN[NationalOption]; } else { if (chr>=0x20 && chr<0x80) { convertedChar = chr; } } break; case CHARSET_LATIN_G0_FR: if (NationalOption>=0) { if (NationalOptionSubsetFR[NationalOption]>0) convertedChar = NationalOptionSubsetFR[NationalOption]; } else { if (chr>=0x20 && chr<0x80) { convertedChar = chr; } } break; case CHARSET_LATIN_G0_IT: if (NationalOption>=0) { if (NationalOptionSubsetIT[NationalOption]>0) convertedChar = NationalOptionSubsetIT[NationalOption]; } else { if (chr>=0x20 && chr<0x80) { convertedChar = chr; } } break; case CHARSET_LATIN_G0_PT_ES: if (NationalOption>=0) { if (NationalOptionSubsetPT_ES[NationalOption]>0) convertedChar = NationalOptionSubsetPT_ES[NationalOption]; } else { if (chr>=0x20 && chr<0x80) { convertedChar = chr; } } break; case CHARSET_LATIN_G0_SV_FI: if (NationalOption>=0) { if (NationalOptionSubsetSV_FI[NationalOption]>0) convertedChar = NationalOptionSubsetSV_FI[NationalOption]; } else { if (chr>=0x20 && chr<0x80) { convertedChar = chr; } } break; case CHARSET_LATIN_G0_DE: if (NationalOption>=0) { if (NationalOptionSubsetDE[NationalOption]>0) convertedChar = NationalOptionSubsetDE[NationalOption]; } else { if (chr>=0x20 && chr<0x80) { convertedChar = chr; } } break; case CHARSET_LATIN_G0_CZ_SK: if (NationalOption>=0) { if (NationalOptionSubsetCZ_SK[NationalOption]>0) convertedChar = NationalOptionSubsetCZ_SK[NationalOption]; } else { if (chr>=0x20 && chr<0x80) { convertedChar = chr; } } break; case CHARSET_LATIN_G0_EE: case CHARSET_LATIN_G0_LV_LT: case CHARSET_LATIN_G0_PL: case CHARSET_LATIN_G0_RO: case CHARSET_LATIN_G0_SR_HR_SL: case CHARSET_LATIN_G0_TR: // Partially supported latin charsets if (chr>=0x20 && chr<0x80 && NationalOption<0) { convertedChar = chr; } break; case CHARSET_LATIN_G2: case CHARSET_CYRILLIC_G0_SR_HR: break; case CHARSET_CYRILLIC_G0_RU_BG: if(chr >=20 && chr < 0x80){ convertedChar = CyrillicOptionRU_BG[chr-0x20]; } break; case CHARSET_CYRILLIC_G0_UK: case CHARSET_CYRILLIC_G2: case CHARSET_GREEK_G0: case CHARSET_GREEK_G2: case CHARSET_ARABIC_G0: case CHARSET_ARABIC_G2: case CHARSET_HEBREW_G0: // totally unsupported break; case CHARSET_GRAPHICS_G1: convertedChar = chr + 0xee00; break; case CHARSET_GRAPHICS_G1_SEP: convertedChar = chr + 0xee00 - 0x20; break; case CHARSET_GRAPHICS_G3: case CHARSET_INVALID: // Totally unsupported break; } return convertedChar; } /* X/26 "G0 character with diacritical mark" mapping */ // extract from G2 column 4: // 0: no modification // 1: GRAVE (GRAVIS) // 2: ACUTE (AKUT) // 3: CIRCUMFLEX (ZIRKUMFLEX) // 4: TILDE (TILDE) // 8: DIAERESIS (TREMA) // A: RING ABOVE (RING DARÜBER) // B: CEDILLA (CEDILLE) uint8_t X26_G0_CharWithDiacritcalMarkMapping(uint8_t c, uint8_t mark) { uint8_t m = c; // default unmodified char switch(c) { case 0x41: // A 0xc0...0xc5 case 0x61: // a 0xe0...0xe5 switch(mark) { case 0x1: m = 0xc0 + c - 0x41; break; // GRAVE case 0x2: m = 0xc1 + c - 0x41; break; // ACUTE case 0x3: m = 0xc2 + c - 0x41; break; // CIRCUMFLEX case 0x4: m = 0xc3 + c - 0x41; break; // TILDE case 0x8: m = 0xc4 + c - 0x41; break; // DIAERESIS case 0xa: m = 0xc5 + c - 0x41; break; // RING ABOVE }; break; // UNSUPPORTED "AE" 0xc6 0xe6 case 0x43: // C 0xc7 case 0x63: // c 0xe7 switch(mark) { case 0xb: m = 0xc7 + c - 0x43; break; // CEDILLA }; break; case 0x45: // E 0xc8...0xcb case 0x65: // e 0xe8...0xeb switch(mark) { case 0x1: m = 0xc8 + c - 0x45; break; // GRAVE case 0x2: m = 0xc9 + c - 0x45; break; // ACUTE case 0x3: m = 0xca + c - 0x45; break; // CIRCUMFLEX case 0x8: m = 0xcb + c - 0x45; break; // DIAERESIS }; break; case 0x49: // I 0xcc...0xcf case 0x69: // i 0xec...0xef switch(mark) { case 0x1: m = 0xcc + c - 0x49; break; // GRAVE case 0x2: m = 0xcd + c - 0x49; break; // ACUTE case 0x3: m = 0xce + c - 0x49; break; // CIRCUMFLEX case 0x8: m = 0xcf + c - 0x49; break; // DIAERESIS }; break; // UNSUPPORTED "ETH" 0xd0 0xf0 case 0x4e: // N 0xd1 case 0x6e: // n 0xf1 switch(mark) { case 0x4: m = 0xd1 + c - 0x4e; break; // TILDE }; break; case 0x4f: // O 0xd2...0xd6 case 0x6f: // o 0xf2...0xf6 switch(mark) { case 0x1: m = 0xd2 + c - 0x4f; break; // GRAVE case 0x2: m = 0xd3 + c - 0x4f; break; // ACUTE case 0x3: m = 0xd4 + c - 0x4f; break; // CIRCUMFLEX case 0x4: m = 0xd5 + c - 0x4f; break; // TILDE case 0x8: m = 0xd6 + c - 0x4f; break; // DIAERESIS }; break; // UNSUPPORTED "MULTIPLICATION SIGN" 0xd7 // UNSUPPORTED "DIVISION SIGN" 0xf7 // UNSUPPORTED "O WITH STROKE" 0xd8 0xf8 case 0x55: // U 0xd9...0xdc case 0x75: // u 0xf9...0xfc switch(mark) { case 0x1: m = 0xd9 + c - 0x55; break; // GRAVE case 0x2: m = 0xda + c - 0x55; break; // ACUTE case 0x3: m = 0xdb + c - 0x55; break; // CIRCUMFLEX case 0x8: m = 0xdc + c - 0x55; break; // DIAERESIS }; break; case 0x59: // Y 0xdd case 0x79: // y 0xfd switch(mark) { case 0x2: m = 0xdd + c - 0x59; break; // ACUTE }; break; // UNSUPPORTED "SHARP S" 0xdf // UNSUPPORTED "THRON" 0xff default: break; }; return m; }; // vim: ts=4 sw=4 et vdr-plugin-osdteletext-2.3.1/txtfont.h000066400000000000000000000020021415701714300200220ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) < 2021 by TODO * * Copyright (c) 2021 by Peter Bieringer (extenions) * * * * 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 __TXTFONT_H #define __TXTFONT_H #include "txtrender.h" unsigned int* GetFontChar(cTeletextChar c, unsigned int *buffer); unsigned int GetVTXChar(cTeletextChar c); uint8_t X26_G0_CharWithDiacritcalMarkMapping(uint8_t c, uint8_t mark); #endif vdr-plugin-osdteletext-2.3.1/txtrecv.c000066400000000000000000000512041415701714300200160ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) 2003,2004 by Marcel Wiesweg * * Copyright (c) 2021 by Peter Bieringer (extenions) * * * * 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 #include "txtrecv.h" #include "tables.h" #include "setup.h" #include "menu.h" #include "logging.h" #include #include #include #include #include #include #include #include #include #include cTelePage::cTelePage(PageID t_page, uchar t_flags, uchar t_lang,int t_mag, Storage *s) : mag(t_mag), flags(t_flags), lang(t_lang), page(t_page), storage(s) { memset(pagedata.pagebuf ,' ',25 * 40); // clear X/0-24 buffer with spaces memset(pagedata.pagebuf_X25, 0, 1 * 40); // clear X25 buffer memset(pagedata.pagebuf_X26, 0, 16 * 40); // clear X26 buffer memset(pagedata.pagebuf_X27, 0, 16 * 40); // clear X27 buffer memset(pagedata.pagebuf_X28, 0, 16 * 40); // clear X28 buffer memset(pagedata.pagebuf_M29, 0, 16 * 40); // clear M29 buffer } cTelePage::~cTelePage() { } void cTelePage::SetLine(const int line, uchar *myptr, const char *debugPrefix) { unsigned char *buf = NULL; int dc = 0; if (strlen(debugPrefix) > 0) { printf("DEBUG: %s#%02d <:", debugPrefix, line); for (int i = 0; i < 40; i++) { printf(" %02x", myptr[i]); }; printf("\n"); }; switch(line) { case 0: // VTX header buf = pagedata.pagebuf; memcpy(buf, myptr, 8); // copy first 8 bytes raw // copy 32 VTX for (int i = 8; i < 40; i++) { buf[i] = myptr[i] & 0x7f; // clear of parity bit }; break; case 1 ... 24: // standard VTX, clear parity bit buf = pagedata.pagebuf + 40 * line; for (int i = 0; i < 40; i++) { buf[i] = myptr[i] & 0x7f; // clear of parity bit }; break; case 25: buf = pagedata.pagebuf_X25; for (int i = 0; i < 40; i++) { buf[i] = myptr[i] & 0x7f; // clear of parity bit }; break; case 26: buf = pagedata.pagebuf_X26; // further handling below break; case 27: buf = pagedata.pagebuf_X27; // further handling below break; case 28: buf = pagedata.pagebuf_X28; // further handling below break; case 29: buf = pagedata.pagebuf_M29; // further handling below break; default: // esyslog("osdteletext: cTelePage::SetLine called with unsupported line=%d (code issue)\n", line); break; }; switch(line) { case 26 ... 29: // line 26-29 contain DesignationCode dc = unhamtab[myptr[0]] & 0x0f; buf += dc * 40; // shift buffer start to DesignationCode row buf[0] = dc | 0x80; // store unhammed DesignationCode | 0x80 (shows "used") break; }; switch(line) { case 26: case 28: case 29: // unhamming 24/18 triplet for (int triplet = 0; triplet < 13; triplet++) { switch(line) { case 26: // ETSI 8.3 unhamming 24/18 // 1 2 3 4 5 6 7 8 | 9 10 11 12 13 14 15 16 | 17 18 19 20 21 22 23 24 // P1 P2 D1 P3 D2 D3 D4 P4 | D5 D6 D7 D8 D9 D10 D11 P5 | D12 D13 D14 D15 D16 D17 D18 P6 // ETSI 12.3.1 X/26 address / mode / data // A0 A1 A2 A3 | A4 A5 M0 M1 M2 M3 M4 | D0 D1 D2 D3 D4 D5 D6 buf[triplet*3 + 1] = ((myptr[triplet*3 + 1] & 0x04) >> 2) // A0 mask 3 and shift to 1 | ((myptr[triplet*3 + 1] & 0x70) >> 3) // A1-3 mask 5-7 and shift to 2-4 | ((myptr[triplet*3 + 2] & 0x03) << 4); // A4-5 mask 1-2 (9-10) and shift to 5-6 buf[triplet*3 + 2] = ((myptr[triplet*3 + 2] & 0x7c) >> 2); // M0-4 mask 3-7 (11-15) and shift to 1-5 buf[triplet*3 + 3] = ((myptr[triplet*3 + 3] & 0x7f) ); // D0-6 mask 1-7 and nothing to shift #if 0 if (strlen(debugPrefix) > 0) printf("DEBUG: %s#%02d T: t=%d i1=%02x i2=%02x i3=%02x -> o1=%02x o2=%02x o3=%02x\n", debugPrefix, line, triplet , myptr[1 + triplet*3], myptr[2 + triplet*3], myptr[3 + triplet*3] , buf[triplet*3 + 1], buf[triplet*3 + 2], buf[triplet*3 + 3] ); #endif break; case 28: // TODO implement break; case 29: // TODO implement break; }; }; break; case 27: // line 27 contain only a 16-bit CRC at the end memcpy(buf + 40 * dc + 1, myptr + 1, 39); // store byte 2-40 break; default: // no storage break; }; if (strlen(debugPrefix) > 0) { if (buf != NULL) { printf("DEBUG: %s#%02d >:", debugPrefix, line); for (int i = 0; i < 40; i++) { printf(" %02x", buf[i]); }; printf("\n"); } else { printf("DEBUG: %s#%02d >: NOT-SELECTED-TO-STORE\n", debugPrefix, line); }; }; } void cTelePage::save() { unsigned char buf; StorageHandle fd; if ( (fd=storage->openForWriting(page)) ) { // page header (12) memcpy(pagedata.pageheader, "VTXV5", 5); // prefix (5) "VTXV4" < 2.0.0 buf=0x01; pagedata.pageheader[5] = buf; // fixed 0x01 (1) buf=mag; pagedata.pageheader[6] = buf; // mag (1) buf=page.page; pagedata.pageheader[7] = buf; // page (1) buf=flags; pagedata.pageheader[8] = buf; // flags (1) buf=lang; pagedata.pageheader[9] = buf; // lang (1) buf=0x00; pagedata.pageheader[10] = buf; // fixed 0x00 (1) buf=0x00; pagedata.pageheader[11] = buf; // fixed 0x00 (1) storage->write(&pagedata, sizeof(TelePageData), fd); storage->close(fd); } } bool cTelePage::IsTopTextPage() { return (page.page & 0xFF) > 0x99 || (page.page & 0x0F) > 0x9; } cTxtStatus::cTxtStatus(bool storeTopText, Storage* storage) : receiver(NULL), storeTopText(storeTopText), storage(storage) , NonLiveChannelNumber(0) { } cTxtStatus::~cTxtStatus() { delete receiver; } void cTxtStatus::ChannelSwitch(const cDevice *Device, int ChannelNumber, bool LiveView) { // ignore if channel is 0 if (ChannelNumber == 0) { if (LiveView && receiver) { if (receiver->Live()) { DEBUG_OT_TXTRCVC("STOPRC channel=0 switch on DVB %d for channel %d LiveView=%s (receiver is attached to LIVE channel)\n", Device->DeviceNumber(), ChannelNumber, BOOLTOTEXT(LiveView)); DELETENULL(receiver); return; } else { DEBUG_OT_TXTRCVC("IGNORE channel=0 switch on DVB %d for channel %d LiveView=%s (receiver is attached to NON-LIVE channel)\n", Device->DeviceNumber(), ChannelNumber, BOOLTOTEXT(LiveView)); return; }; } else { DEBUG_OT_TXTRCVC("IGNORE channel=0 switch on DVB %d for channel %d LiveView=%s\n", Device->DeviceNumber(), ChannelNumber, BOOLTOTEXT(LiveView)); }; return; }; // ignore if channel is invalid (highly unlikely, this will ever // be the case, but defensive coding rules!) #if defined(APIVERSNUM) && APIVERSNUM >= 20301 LOCK_CHANNELS_READ; const cChannel* newChannel = Channels->GetByNumber(ChannelNumber); #else const cChannel* newChannel = Channels.GetByNumber(ChannelNumber); #endif if (newChannel == NULL) { DEBUG_OT_TXTRCVC("IGNORE invalid channel on DVB %d for channel %d LiveView=%s\n", Device->DeviceNumber(), ChannelNumber, BOOLTOTEXT(LiveView)); return; }; if (!LiveView) { if ((NonLiveChannelNumber > 0) && (NonLiveChannelNumber == ChannelNumber)) { // don't ignore non-live-channel-switching in case of NonLiveChannelNumber was hit DEBUG_OT_TXTRCVC("PASSED selected NON-LIVE channel switch detected on DVB %d for channel %d '%s'\n", Device->DeviceNumber(), newChannel->Number(), newChannel->Name()); } else if ( (NonLiveChannelNumber > 0) // currently on tuned channel && (NonLiveChannelNumber != ChannelNumber) // channel is not matching && (receiver) // receiver is active ) { if (receiver->device->DeviceNumber() == Device->DeviceNumber()) { // device matching // don't ignore non-live-channel-switching in case of Device was hit DEBUG_OT_TXTRCVC("STOPRC not matching NON-LIVE channel switch detected on DVB %d (currently used by receiver) for channel %d '%s'\n", Device->DeviceNumber(), newChannel->Number(), newChannel->Name()); DELETENULL(receiver); return; } else { DEBUG_OT_TXTRCVC("IGNORE not matching NON-LIVE channel switch on DVB %d (not used by receiver) for channel %d '%s'\n", Device->DeviceNumber(), newChannel->Number(), newChannel->Name()); return; }; } else { // ignore other non-live-channel-switching DEBUG_OT_TXTRCVC("IGNORE not matching NON-LIVE channel switch on DVB %d for channel %d '%s'\n", Device->DeviceNumber(), newChannel->Number(), newChannel->Name()); return; }; } else { // ignore non-live-channel-switching if (ChannelNumber != cDevice::CurrentChannel()) { DEBUG_OT_TXTRCVC("IGNORE not current device LIVE channel switch on DVB %d for channel %d '%s'\n", Device->DeviceNumber(), newChannel->Number(), newChannel->Name()); return; }; // process live channel switch DEBUG_OT_TXTRCVC("PASSED LIVE channel switch detected on DVB %d for channel %d '%s'\n", Device->DeviceNumber(), newChannel->Number(), newChannel->Name()); }; // now re-attach the receiver to the new channel int TPid = newChannel->Tpid(); if (LiveView && TPid && receiver) { // tell still running receiver thread that it will be deleted and new channel is live // will be used during deleting the receiver to signal that status via TeletextBrowser::ChannelSwitched receiver->SetFlagStopByLiveChannelSwitch(true); }; // channel was changed, delete the running receiver if still running DELETENULL(receiver); if (TPid) { if (LiveView) { // attach to actual device receiver = new cTxtReceiver(cDevice::ActualDevice(), LiveView, newChannel, storeTopText, storage); cDevice::ActualDevice()->AttachReceiver(receiver); DEBUG_OT_TXTRCVC("ATTACH receiver to DVB %d for LIVE channel %d '%s'\n", cDevice::ActualDevice()->DeviceNumber(), newChannel->Number(), newChannel->Name()); TeletextBrowser::ChannelSwitched(ChannelNumber, ChannelIsLive); NonLiveChannelNumber = 0; // clear non-live channel number } else { cDevice *device = cDevice::GetDevice(Device->DeviceNumber()); receiver = new cTxtReceiver(device, LiveView, newChannel, storeTopText, storage); device->AttachReceiver(receiver); DEBUG_OT_TXTRCVC("ATTACH receiver to DVB %d for TUNED channel %d '%s'\n", Device->DeviceNumber(), newChannel->Number(), newChannel->Name()); TeletextBrowser::ChannelSwitched(ChannelNumber, ChannelIsTuned); }; } else { if (LiveView) { DEBUG_OT_TXTRCVC("NOOP do not attach receiver (MISSING teletext) on DVB %d for LIVE channel %d '%s'\n", Device->DeviceNumber(), newChannel->Number(), newChannel->Name()); TeletextBrowser::ChannelSwitched(ChannelNumber, ChannelIsLiveButHasNoTeletext); } else { DEBUG_OT_TXTRCVC("NOOP do not attach receiver (MISSING teletext) on DVB %d for TUNED channel %d '%s'\n", Device->DeviceNumber(), newChannel->Number(), newChannel->Name()); TeletextBrowser::ChannelSwitched(ChannelNumber, ChannelIsTunedButHasNoTeletext); }; } } cTxtReceiver::cTxtReceiver(const cDevice *dev, const bool live, const cChannel* chan, bool storeTopText, Storage* storage) : cReceiver(chan, -1), cThread("osdteletext-receiver", true), TxtPage(0), storeTopText(storeTopText), buffer((188+60)*75), storage(storage) , device(dev) , live(live) , flagStopByLiveChannelSwitch(false) , channel(chan), statTxtReceiverPageCount(0) { isyslog("osdteletext: cTxtReceiver started on DVB %d for channel %d '%s' ID=%s storeTopText=%s LiveView=%s\n", device->DeviceNumber(), channel->Number(), channel->Name(), *ChannelID().ToString(), BOOLTOTEXT(storeTopText), BOOLTOTEXT(live)); SetPids(NULL); AddPid(chan->Tpid()); storage->prepareDirectory(ChannelID()); time(&statTxtReceiverTimeStart); // record start time // 10 ms timeout on getting TS frames buffer.SetTimeouts(0, 10); } cTxtReceiver::~cTxtReceiver() { Detach(); Activate(false); buffer.Clear(); delete TxtPage; // calculate and log statistics time_t statTxtReceiverTimeStop; time(&statTxtReceiverTimeStop); double time_diff = difftime(statTxtReceiverTimeStop, statTxtReceiverTimeStart); isyslog("osdteletext: cTxtReceiver stopped after %.0lf sec: cTelePage received on DVB %d for channel %d '%s' ID=%s: %ld (%.3lf/sec)\n", time_diff, device->DeviceNumber(), channel->Number(), channel->Name(), *ChannelID().ToString(), statTxtReceiverPageCount, statTxtReceiverPageCount / time_diff); if (!live) { // tuned channel if (flagStopByLiveChannelSwitch == false) { TeletextBrowser::ChannelSwitched(channel->Number(), ChannelWasTuned); // trigger TeletextBrowser that channel is no longer tuned } else { TeletextBrowser::ChannelSwitched(channel->Number(), ChannelWasTunedNewChannelIsLive); // trigger TeletextBrowser that channel is no longer tuned but new channel is live }; }; } void cTxtReceiver::Stop() { Activate(false); } void cTxtReceiver::Activate(bool On) { if (On) { if (!Running()) { Start(); } } else if (Running()) { buffer.Signal(); Cancel(2); } } #if defined(APIVERSNUM) && APIVERSNUM >= 20301 void cTxtReceiver::Receive(const uchar *Data, int Length) #else void cTxtReceiver::Receive(uchar *Data, int Length) #endif { cFrame *frame=new cFrame(Data, Length); if (!buffer.Put(frame)) { // Buffer overrun delete frame; buffer.Signal(); } } void cTxtReceiver::Action() { while (Running()) { cFrame *frame=buffer.Get(); if (frame) { uchar *Datai=frame->Data(); for (int i=0; i < 4; i++) { if (Datai[4+i*46]==2 || Datai[4+i*46]==3) { for (int j=(8+i*46);j<(50+i*46);j++) Datai[j]=invtab[Datai[j]]; DecodeTXT(&Datai[i*46]); } } buffer.Drop(frame); } else buffer.Wait(); } buffer.Clear(); } uchar cTxtReceiver::unham16 (uchar *p) { unsigned short c1,c2; c1=unhamtab[p[0]]; c2=unhamtab[p[1]]; return (c1 & 0x0F) | (c2 & 0x0F) *16; } void cTxtReceiver::SaveAndDeleteTxtPage() { if (TxtPage) { if (storeTopText || !TxtPage->IsTopTextPage()) { TxtPage->save(); if (TxtPage->page.page == 0x100) { // call browser to place mark in map TeletextBrowser::ChannelPage100Stored(channel->Number()); }; DELETENULL(TxtPage); } } } void cTxtReceiver::DecodeTXT(uchar* TXT_buf) { // Format of buffer: // 0x00-0x04 ? // 0x05-0x06 Clock Run-In? // 0x07 Framing Code? // 0x08 Magazine number (100-digit of page number) // 0x09 Line number // 0x0A..0x31 Line data // Line 0 only: // 0x0A 10-digit of page number // 0x0B 1-digit of page number // 0x0C Sub-Code bits 0..3 // 0x0D Sub-Code bits 4..6 + C4 flag // 0x0E Sub-Code bits 8..11 // 0x0F Sub-Code bits 12..13 + C5,C6 flag // 0x10 C7-C10 flags // 0x11 C11-C14 flags // // Flags: // C4 - Erase last page, new page transmitted // C5 - News flash, boxed display // C6 - Subtitle, boxed display // C7 - Suppress Header, dont show line 0 // C8 - Update, page has changed // C9 - Interrupt Sequence, page number is out of order // C10 - Inhibit Display // C11 - Magazine Serial mode // C12-C14 - Language selection, lower 3 bits int hdr,mag,mag8,line; uchar *ptr; uchar flags,lang; hdr = unham16 (&TXT_buf[0x8]); mag = hdr & 0x07; mag8 = mag ?: 8; line = (hdr>>3) & 0x1f; ptr = &TXT_buf[10]; static int stat_pagecount = 0; static long int stat_pagecount_total = 0; static time_t stat_time_last; static time_t stat_time_start; static int init = 0; if (init == 0) { time(&stat_time_last); time(&stat_time_start); init = 1; } time_t stat_time_now; double stat_time_diff_last; double stat_time_diff_start; static char debugPrefix[16]; if (line == 0) { unsigned char b1, b2, b3, b4; int pgno, subno; b1 = unham16 (ptr); // Page no, 10- and 1-digit if (b1 == 0xff) return; SaveAndDeleteTxtPage(); snprintf(debugPrefix, sizeof(debugPrefix), "%s", ""); // clear debug status b2 = unham16 (ptr+2); // Sub-code 0..6 + C4 b3 = unham16 (ptr+4); // Sub-code 8..13 + C5,C6 b4 = unham16 (ptr+6); // C7..C14 // flags: // 0x80 C4 - Erase page // 0x40 C5 - News flash // 0x20 C6 - Subtitle // 0x10 C7 - Suppress Header // 0x08 C8 - Update // 0x04 C9 - Interrupt Sequence // 0x02 C9 (Bug?) // 0x01 C11 - Magazine Serial mode flags=b2 & 0x80; flags|=(b3&0x40)|((b3>>2)&0x20); //?????? flags|=((b4<<4)&0x10)|((b4<<2)&0x08)|(b4&0x04)|((b4>>1)&0x02)|((b4>>4)&0x01); lang=((b4>>5) & 0x07); pgno = mag8 * 256 + b1; subno = (b2 + b3 * 256) & 0x3f7f; // Sub Page Number TxtPage = new cTelePage(PageID(ChannelID(), pgno, subno), flags, lang, mag, storage); DEBUG_OT_NEPG("new cTelePage pgno=%03x subno=%02x flags=0x%02x lang=0x%02x\n", pgno, subno, flags, lang); stat_pagecount++; stat_pagecount_total++; statTxtReceiverPageCount++; time(&stat_time_now); stat_time_diff_last = difftime(stat_time_now, stat_time_last); if (stat_time_diff_last >= 10) { // every 10 seconds stat_time_diff_start = difftime(stat_time_now, stat_time_start); DEBUG_OT_COPG("received on DVB %d channel %d '%s' cTelePages: %d in %.0lf sec (total: %ld in %.0lf sec -> %.3lf/sec)\n" , device->DeviceNumber() , channel->Number() , channel->Name() , stat_pagecount , stat_time_diff_last , stat_pagecount_total , stat_time_diff_start , stat_pagecount_total / stat_time_diff_start ); stat_pagecount = 0; stat_time_last = stat_time_now; }; if (m_debugmask & DEBUG_MASK_OT_TXTRCVD) { if (m_debugpsub == 0) { if (m_debugpage == TxtPage->page.page) { // select debug for all sub-pages snprintf(debugPrefix, sizeof(debugPrefix), "p=%03x*%02x", TxtPage->page.page, TxtPage->page.subPage); } else if (m_debugline >= 0) { // all pages, but specific line only snprintf(debugPrefix, sizeof(debugPrefix), "p=%03x!%02x", TxtPage->page.page, TxtPage->page.subPage); }; } else { if ((m_debugpage == TxtPage->page.page) && (m_debugpsub == TxtPage->page.subPage)) { if ((m_debugline < 0) || (m_debugline == line)) { // select debug only for matching sub-page snprintf(debugPrefix, sizeof(debugPrefix), "p=%03x-%02x", TxtPage->page.page, TxtPage->page.subPage); }; }; }; }; }; if (TxtPage) { if ((strlen(debugPrefix) > 0) && ((m_debugline < 0) || (m_debugline == line))) { TxtPage->SetLine(line,(uchar *)ptr, debugPrefix); } else { TxtPage->SetLine(line,(uchar *)ptr, ""); }; }; } // vim: ts=3 sw=3 et vdr-plugin-osdteletext-2.3.1/txtrecv.h000066400000000000000000000057451415701714300200340ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) 2003,2004 by Marcel Wiesweg * * Copyright (c) 2021 by Peter Bieringer (extenions) * * * * 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 __TXTRECV_H #define __TXTRECV_H #include #include #include #include #include #include #include "storage.h" class cTelePage { private: int mag; unsigned char flags; unsigned char lang; public: PageID page; private: TelePageData pagedata; Storage* storage; public: cTelePage(PageID page, uchar flags, uchar lang, int mag, Storage *s); ~cTelePage(); void SetLine(int, uchar*, const char*); void save(); bool IsTopTextPage(); }; class cRingTxtFrames : public cRingBufferFrame { public: cRingTxtFrames(int Size) : cRingBufferFrame(Size, true) {}; ~cRingTxtFrames() { Clear(); }; void Wait(void) { WaitForGet(); }; void Signal(void) { EnableGet(); }; }; class cTxtReceiver : public cReceiver, public cThread { private: void DecodeTXT(uchar*); uchar unham16 (uchar*); cTelePage *TxtPage; void SaveAndDeleteTxtPage(); bool storeTopText; cRingTxtFrames buffer; Storage *storage; public: const cDevice *device; private: const bool live; bool flagStopByLiveChannelSwitch; const cChannel* channel; long int statTxtReceiverPageCount; time_t statTxtReceiverTimeStart; protected: virtual void Activate(bool On); #if defined(APIVERSNUM) && APIVERSNUM >= 20301 virtual void Receive(const uchar *Data, int Length); #else virtual void Receive(uchar *Data, int Length); #endif virtual void Action(); public: cTxtReceiver(const cDevice *dev, const bool live, const cChannel* chan, bool storeTopText, Storage* storage); virtual ~cTxtReceiver(); virtual void Stop(); void SetFlagStopByLiveChannelSwitch(bool flag) { flagStopByLiveChannelSwitch = flag; }; bool Live() { return live; }; bool ChannelNumber() { return channel->Number(); }; }; class cTxtStatus : public cStatus { public: cTxtReceiver *receiver; private: bool storeTopText; Storage* storage; int NonLiveChannelNumber; protected: virtual void ChannelSwitch(const cDevice *Device, int ChannelNumber, bool LiveView); public: cTxtStatus(bool storeTopText, Storage* storage); void SetNonLiveChannelNumber(const int ChannelNumber) { NonLiveChannelNumber = ChannelNumber; return; }; ~cTxtStatus(); }; #endif vdr-plugin-osdteletext-2.3.1/txtrender.c000066400000000000000000000573641415701714300203530ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) 2005 by Udo Richter * * Copyright (c) 2021 by Peter Bieringer (extenions) * * * * txtrender.c - Teletext display abstraction and teletext code * * renderer * * * * 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 #include "txtrender.h" #include "menu.h" #include "logging.h" #include "txtfont.h" // Font tables // teletext uses 7-bit numbers to identify a font set. // There are three font sets involved: // Primary G0, Secondary G0, and G2 font set. // Font tables are organized in blocks of 8 fonts: enumCharsets FontBlockG0_0000[8] = { CHARSET_LATIN_G0_EN, CHARSET_LATIN_G0_DE, CHARSET_LATIN_G0_SV_FI, CHARSET_LATIN_G0_IT, CHARSET_LATIN_G0_FR, CHARSET_LATIN_G0_PT_ES, CHARSET_LATIN_G0_CZ_SK, CHARSET_LATIN_G0 }; enumCharsets FontBlockG2Latin[8]={ CHARSET_LATIN_G2, CHARSET_LATIN_G2, CHARSET_LATIN_G2, CHARSET_LATIN_G2, CHARSET_LATIN_G2, CHARSET_LATIN_G2, CHARSET_LATIN_G2, CHARSET_LATIN_G2 }; enumCharsets FontBlockG0_0001[8] = { CHARSET_LATIN_G0_PL, CHARSET_LATIN_G0_DE, CHARSET_LATIN_G0_SV_FI, CHARSET_LATIN_G0_IT, CHARSET_LATIN_G0_FR, CHARSET_LATIN_G0, CHARSET_LATIN_G0_CZ_SK, CHARSET_LATIN_G0 }; enumCharsets FontBlockG0_0010[8] = { CHARSET_LATIN_G0_EN, CHARSET_LATIN_G0_DE, CHARSET_LATIN_G0_SV_FI, CHARSET_LATIN_G0_IT, CHARSET_LATIN_G0_FR, CHARSET_LATIN_G0_PT_ES, CHARSET_LATIN_G0_TR, CHARSET_LATIN_G0 }; enumCharsets FontBlockG0_0011[8] = { CHARSET_LATIN_G0, CHARSET_LATIN_G0, CHARSET_LATIN_G0, CHARSET_LATIN_G0, CHARSET_LATIN_G0, CHARSET_LATIN_G0_SR_HR_SL, CHARSET_LATIN_G0, CHARSET_LATIN_G0_RO }; enumCharsets FontBlockG0_0100[8] = { CHARSET_CYRILLIC_G0_SR_HR, CHARSET_LATIN_G0_DE, CHARSET_LATIN_G0_EE, CHARSET_LATIN_G0_LV_LT, CHARSET_CYRILLIC_G0_RU_BG, CHARSET_CYRILLIC_G0_UK, CHARSET_LATIN_G0_CZ_SK, CHARSET_INVALID }; enumCharsets FontBlockG2_0100[8] = { CHARSET_CYRILLIC_G2, CHARSET_LATIN_G2, CHARSET_LATIN_G2, CHARSET_LATIN_G2, CHARSET_CYRILLIC_G2, CHARSET_CYRILLIC_G2, CHARSET_LATIN_G2, CHARSET_INVALID }; enumCharsets FontBlockG0_0110[8] = { CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_LATIN_G0_TR, CHARSET_GREEK_G0 }; enumCharsets FontBlockG2_0110[8] = { CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_LATIN_G2, CHARSET_GREEK_G2 }; enumCharsets FontBlockG0_1000[8] = { CHARSET_LATIN_G0_EN, CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_LATIN_G0_FR, CHARSET_INVALID, CHARSET_INVALID, CHARSET_ARABIC_G0 }; enumCharsets FontBlockG2_1000[8] = { CHARSET_ARABIC_G2, CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_ARABIC_G2, CHARSET_INVALID, CHARSET_INVALID, CHARSET_ARABIC_G2 }; enumCharsets FontBlockG0_1010[8] = { CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_HEBREW_G0, CHARSET_INVALID, CHARSET_ARABIC_G0, }; enumCharsets FontBlockG2_1010[8] = { CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_ARABIC_G2, CHARSET_INVALID, CHARSET_ARABIC_G2, }; enumCharsets FontBlockInvalid[8] = { CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID, CHARSET_INVALID }; // The actual font table definition: // Split the 7-bit number into upper 4 and lower 3 bits, // use upper 4 bits for outer array, // use lower 3 bits for inner array struct structFontBlock { enumCharsets *G0Block; enumCharsets *G2Block; }; structFontBlock FontTable[16] = { { FontBlockG0_0000, FontBlockG2Latin }, // 0000 block { FontBlockG0_0001, FontBlockG2Latin }, // 0001 block { FontBlockG0_0010, FontBlockG2Latin }, // 0010 block { FontBlockG0_0011, FontBlockG2Latin }, // 0011 block { FontBlockG0_0100, FontBlockG2_0100 }, // 0100 block { FontBlockInvalid, FontBlockInvalid }, // 0101 block { FontBlockG0_0110, FontBlockG2_0110 }, // 0110 block { FontBlockInvalid, FontBlockInvalid }, // 0111 block { FontBlockG0_1000, FontBlockG2_1000 }, // 1000 block { FontBlockInvalid, FontBlockInvalid }, // 1001 block { FontBlockG0_1010, FontBlockG2_1010 }, // 1010 block { FontBlockInvalid, FontBlockInvalid }, // 1011 block { FontBlockInvalid, FontBlockInvalid }, // 1100 block { FontBlockInvalid, FontBlockInvalid }, // 1101 block { FontBlockInvalid, FontBlockInvalid }, // 1110 block { FontBlockInvalid, FontBlockInvalid } // 1111 block }; inline enumCharsets GetG0Charset(int codepage) { return FontTable[codepage>>3].G0Block[codepage&7]; } inline enumCharsets GetG2Charset(int codepage) { return FontTable[codepage>>3].G2Block[codepage&7]; } cRenderPage::cRenderPage() : Dirty(false), DirtyAll(false), // Todo: make this configurable FirstG0CodePage(ttSetup.txtG0Block<<3), SecondG0CodePage(ttSetup.txtG2Block<<3) { } enum enumSizeMode { // Possible size modifications of characters sizeNormal, sizeDoubleWidth, sizeDoubleHeight, sizeDoubleSize }; // Debug only: List of teletext spacing code short names const char *(names[0x20])={ "AlBk","AlRd","AlGr","AlYl","AlBl","AlMg","AlCy","AlWh", "Flsh","Stdy","EnBx","StBx","SzNo","SzDh","SzDw","SzDs", "MoBk","MoRd","MoGr","MoYl","MoBl","MoMg","MoCy","MoWh", "Conc","GrCn","GrSp","ESC", "BkBl","StBk","HoMo","ReMo"}; void cRenderPage::ReadTeletextHeader(unsigned char *Header) { // Format of buffer, see also structure TelePageData in storage.h // Header: 12 bytes (0-11) // 0 String "VTXV5" // 5 always 0x01 // 6 magazine number // 7 page number // 8 flags // 9 lang // 10 always 0x00 // 11 always 0x00 // Teletext base data starting from byte 12 // 12 teletext data, 25x40 bytes // VTXV5 extension // X25 ( 1x40) // X26 (16x40) // X27 (16x40) // X28 (16x40) // M29 (16x40) // Format of flags: // 0x80 C4 - Erase page // 0x40 C5 - News flash // 0x20 C6 - Subtitle // 0x10 C7 - Suppress Header // 0x08 C8 - Update // 0x04 C9 - Interrupt Sequence // 0x02 C9 (Bug?) // 0x01 C11 - Magazine Serial mode Flags=Header[8]; Lang=Header[9]; } void cRenderPage::RenderTeletextCode(unsigned char *PageCode) { int x,y; bool EmptyNextLine=false; // Skip one line, in case double height chars were/will be used // Get code pages: int LocalG0CodePage=(FirstG0CodePage & 0x78) | ((Lang & 0x04)>>2) | (Lang & 0x02) | ((Lang & 0x01)<<2); enumCharsets FirstG0=GetG0Charset(LocalG0CodePage); enumCharsets SecondG0=GetG0Charset(SecondG0CodePage); // Reserved for later use: // enumCharsets FirstG2=GetG2Charset(LocalG0CodePage); for (y=0;y<24;(EmptyNextLine?y+=2:y++)) { // Start of line: Set start of line defaults if (m_debugmask & DEBUG_MASK_OT_TXTRD) { printf("y=%02d ", y); }; // Hold Mosaics mode: Remember last mosaic char/charset // for next spacing code bool HoldMosaics=false; unsigned char HoldMosaicChar=' '; enumCharsets HoldMosaicCharset=FirstG0; enumSizeMode Size=sizeNormal; // Font size modification bool SecondCharset=false; // Use primary or secondary G0 charset bool GraphicCharset=false; // Graphics charset used? bool SeparateGraphics=false; // Use separated vs. contiguous graphics charset bool NoNextChar=false; // Skip display of next char, for double-width EmptyNextLine=false; // Skip next line, for double-height cTeletextChar c; // auto.initialized to everything off c.SetFGColor(ttcWhite); c.SetBGColor(ttcBlack); c.SetCharset(FirstG0); if (y==0 && (Flags&0x10)) { DEBUG_OT_BOXED("set c.SetBoxed(true) Flags=%02x x=%d y=%d", Flags, x, y); c.SetBoxedOut(true); } if (Flags&0x60) { DEBUG_OT_BOXED("set c.SetBoxed(true) Flags=%02x x=%d y=%d", Flags, x, y); c.SetBoxedOut(true); } // Pre-scan for double-height and double-size codes for (x=0;x<40;x++) { if (y==0 && x<8) x=8; if ((PageCode[x+40*y] & 0x7f)==0x0D || (PageCode[x+40*y] & 0x7f)==0x0F) EmptyNextLine=true; } // Move through line for (x=0;x<40;x++) { unsigned char ttc=PageCode[x+40*y]; if (y==0 && x<8) continue; // no displayable data here... if (m_debugmask & DEBUG_MASK_OT_TXTRD) { // Debug only: Output line data and spacing codes if (ttc<0x20) printf("%s(%02x) ",names[ttc], ttc); else printf("%02x ",ttc); if (x==39) printf("\n"); }; // Handle all 'Set-At' spacing codes switch (ttc) { case 0x09: // Steady DEBUG_OT_BLINK("set bc.SetBlink(false) ttc=%d x=%d y=%d", ttc, x, y); c.SetBlink(false); break; case 0x0C: // Normal Size if (Size!=sizeNormal) { Size=sizeNormal; HoldMosaicChar=' '; HoldMosaicCharset=FirstG0; } break; case 0x18: // Conceal c.SetConceal(true); break; case 0x19: // Contiguous Mosaic Graphics SeparateGraphics=false; if (GraphicCharset) c.SetCharset(CHARSET_GRAPHICS_G1); break; case 0x1A: // Separated Mosaic Graphics SeparateGraphics=true; if (GraphicCharset) c.SetCharset(CHARSET_GRAPHICS_G1_SEP); break; case 0x1C: // Black Background c.SetBGColor(ttcBlack); break; case 0x1D: // New Background c.SetBGColor(c.GetFGColor()); break; case 0x1E: // Hold Mosaic HoldMosaics=true; break; } // temporary copy of character data: cTeletextChar c2=c; // c2 will be text character or space character or hold mosaic // c2 may also have temporary flags or charsets if (ttc<0x20) { // Spacing code, display space or hold mosaic if (HoldMosaics) { c2.SetChar(HoldMosaicChar); c2.SetCharset(HoldMosaicCharset); } else { c2.SetChar(' '); } } else { // Character code c2.SetChar(ttc); if (GraphicCharset) { if (ttc&0x20) { // real graphics code, remember for HoldMosaics HoldMosaicChar=ttc; HoldMosaicCharset=c.GetCharset(); } else { // invalid code, pass-through to G0 c2.SetCharset(SecondCharset?SecondG0:FirstG0); } } } // Handle double-height and double-width extremes if (y>=23) { if (Size==sizeDoubleHeight) Size=sizeNormal; if (Size==sizeDoubleSize) Size=sizeDoubleWidth; } if (x>=38) { if (Size==sizeDoubleWidth) Size=sizeNormal; if (Size==sizeDoubleSize) Size=sizeDoubleHeight; } // Now set character code if (NoNextChar) { // Suppress this char due to double width last char NoNextChar=false; } else { switch (Size) { case sizeNormal: // Normal sized SetChar(x,y,c2); if (EmptyNextLine && y<23) { // Clean up next line SetChar(x,y+1,c2.ToChar(' ').ToCharset(FirstG0)); } break; case sizeDoubleWidth: // Double width SetChar(x,y,c2.ToDblWidth(dblw_Left)); SetChar(x+1,y,c2.ToDblWidth(dblw_Right)); if (EmptyNextLine && y<23) { // Clean up next line SetChar(x ,y+1,c2.ToChar(' ').ToCharset(FirstG0)); SetChar(x+1,y+1,c2.ToChar(' ').ToCharset(FirstG0)); } NoNextChar=true; break; case sizeDoubleHeight: // Double height SetChar(x,y,c2.ToDblHeight(dblh_Top)); SetChar(x,y+1,c2.ToDblHeight(dblh_Bottom)); break; case sizeDoubleSize: // Double Size SetChar(x , y,c2.ToDblHeight(dblh_Top ).ToDblWidth(dblw_Left )); SetChar(x+1, y,c2.ToDblHeight(dblh_Top ).ToDblWidth(dblw_Right)); SetChar(x ,y+1,c2.ToDblHeight(dblh_Bottom).ToDblWidth(dblw_Left )); SetChar(x+1,y+1,c2.ToDblHeight(dblh_Bottom).ToDblWidth(dblw_Right)); NoNextChar=true; break; } } // Handle all 'Set-After' spacing codes switch (ttc) { case 0x00 ... 0x07: // Set FG color if (GraphicCharset) { // Actual switch from graphics charset HoldMosaicChar=' '; HoldMosaicCharset=FirstG0; } c.SetFGColor((enumTeletextColor)ttc); c.SetCharset(SecondCharset?SecondG0:FirstG0); GraphicCharset=false; c.SetConceal(false); break; case 0x08: // Flash DEBUG_OT_BLINK("set c.SetBlink(true) ttc=%02x x=%d y=%d", ttc, x, y); c.SetBlink(true); break; case 0x0A: // End Box DEBUG_OT_BOXED("set c.SetBoxed(true) End Box ttc=%02x x=%d y=%d", ttc, x, y); c.SetBoxedOut(true); break; case 0x0B: // Start Box DEBUG_OT_BOXED("set c.SetBoxed(false) StartBox ttc=%02x x=%d y=%d", ttc, x, y); c.SetBoxedOut(false); break; case 0x0D: // Double Height if (Size!=sizeDoubleHeight) { Size=sizeDoubleHeight; HoldMosaicChar=' '; HoldMosaicCharset=FirstG0; } break; case 0x0E: // Double Width if (Size!=sizeDoubleWidth) { Size=sizeDoubleWidth; HoldMosaicChar=' '; HoldMosaicCharset=FirstG0; } break; case 0x0F: // Double Size if (Size!=sizeDoubleSize) { Size=sizeDoubleSize; HoldMosaicChar=' '; HoldMosaicCharset=FirstG0; } break; case 0x10 ... 0x17: // Mosaic FG Color if (!GraphicCharset) { // Actual switch to graphics charset HoldMosaicChar=' '; HoldMosaicCharset=FirstG0; } c.SetFGColor((enumTeletextColor)(ttc-0x10)); c.SetCharset(SeparateGraphics?CHARSET_GRAPHICS_G1_SEP:CHARSET_GRAPHICS_G1); GraphicCharset=true; c.SetConceal(false); break; case 0x1B: // ESC Switch SecondCharset=!SecondCharset; if (!GraphicCharset) c.SetCharset(SecondCharset?SecondG0:FirstG0); break; case 0x1F: // Release Mosaic HoldMosaics=false; break; } } // end for x } // end for y for (x=0;x<40;x++) { // Clean out last lines cTeletextChar c; c.SetFGColor(ttcWhite); c.SetBGColor(ttcBlack); c.SetCharset(FirstG0); c.SetChar(' '); if (Flags&0x60) { DEBUG_OT_BOXED("set c.SetBoxed(true) Flags=%02x ttc=(space) x=%d y=%d", Flags, x, y); c.SetBoxedOut(true); } SetChar(x,24,c); SetChar(x,25,c); SetChar(x,26,c); } /* VTXV5 handling starts here */ DEBUG_OT_TXTRDT("start X/26 handling"); /* X/26 */ x = -1; y = -1; // reset x/y unsigned char* PageCode_X26 = PageCode + 25*40 + 40; // X/1-24 + X/25 for (int row = 0; row <= 15; row++) { // convert X/26/0-15 into triplets if (PageCode_X26[row*40] == 0) { // row empty continue; } else if ((PageCode_X26[row*40] & 0x80) != 0x80) { DEBUG_OT_TXTRDT("invalid X/26 row (DesignationCode flag not valid)"); continue; }; for (int triplet = 0; triplet < 13; triplet++) { uint8_t addr = PageCode_X26[row*40 + 1 + triplet*3]; uint8_t mode = PageCode_X26[row*40 + 2 + triplet*3]; uint8_t data = PageCode_X26[row*40 + 3 + triplet*3]; int found = 0; const char* info; if ((mode == 0x04) && (addr >= 40) && (addr <= 63)) { // 0x04 = 0b00100 // "Set Active Position" found = 1; if (addr == 40) { y = 24; } else { y = addr - 40; }; x = data; DEBUG_OT_TXTRDT("X/26 triplet found: row=%d triplet=%d SetActivePosition y=%d x=%d\n", row, triplet, y, x); } else if ((mode == 0x04) && (addr >= 0) && (addr <= 39)) { // 0x04 = 0b00100 // RESERVED found = 1; } else if ((mode == 0x1f) && (addr == 0x3f)) { // 0x1f = 0b11111 // "Termination Marker" found = 1; if (m_debugmask & DEBUG_MASK_OT_TXTRDT) { switch(data & 0x07) { case 0x00: // 0b000 info = "Intermediate (G)POP sub-page. End of object, more objects follow on this page."; break; case 0x01: // 0b001 info = "Intermediate (G)POP sub-page. End of last object on this page."; break; case 0x02: // 0b010 info = "Last (G)POP sub-page. End of object, more objects follow on this page."; break; case 0x03: // 0b011 info = "Last (G)POP sub-page. End of last object on this page."; break; case 0x04: // 0b100 info = "Local Object definitions. End of object, more objects follow on this page."; break; case 0x05: // 0b101 info = "Local Object definitions. End of last object on this page."; break; case 0x06: // 0b110 info = "Local enhancement data. End of enhancement data, Local Object definitions follow."; break; case 0x07: // 0b111 info = "Local enhancement data. End of enhancement data, no Local Object definitions follow."; break; }; DEBUG_OT_TXTRDT("X/26 triplet found: row=%d triplet=%d TerminationMarker: %s\n", row, triplet, info); }; } else if (((mode & 0x10) == 0x10) && (addr >= 0) && (addr <= 39)) { // 0x1x = 0b1xxxx // G0 Characters Including Diacritical Marks if (y == -1) { // "Set Active Position" not seen so far -> no y known so far -> SKIP DEBUG_OT_TXTRDT("misplaced X/26 triplet 'G0 Characters Including Diacritical Marks' misses 'Set Active Position' in advance"); continue; }; x = addr; cTeletextChar c = GetChar(x, y); if (mode == 0x10) { // 0x10 = 0b10000 info = "G0 character without diacritical mark"; // No diacritical mark exists for mode description value 0b10000. An unmodified G0 character is then displayed unless the 7 bits of the data field have the value 0b0101010 (2/A) when the symbol "@" shall be displayed. if (data == 0x2a) { // set char to '@' c.SetCharset(CHARSET_LATIN_G0); c.SetChar(0x80); } else { c.SetCharset(CHARSET_LATIN_G0); c.SetChar(data); }; DEBUG_OT_TXTRDT("X/26 triplet found: row=%d triplet=%d: %s (data=0x%02x)\n", row, triplet, info, data); found = 1; } else { info = "G0 character with diacritical mark"; found = 1; uint8_t mark = mode & 0x0f; DEBUG_OT_TXTRDT("X/26 triplet found: row=%d triplet=%d: %s x=%d mark=%d data=0x%02x\n", row, triplet, info, x, mark, data); if (data >= 0x20) { DEBUG_OT_TXTRDT("X/26 triplet exec : y=%02d x=%02d change Char=0x%02x Charset=0x%04x mark=%x => Char=0x%02x Charset=0x%04x\n", y, x, c.GetChar(), c.GetCharset(), mark, X26_G0_CharWithDiacritcalMarkMapping(data, mark), CHARSET_LATIN_G0); c.SetCharset(CHARSET_LATIN_G0); c.SetChar(X26_G0_CharWithDiacritcalMarkMapping(data, mark)); } else { // ignore: Data field values < 20 hex are reserved but decoders should still set the column co-ordinate of the Active Position to the value of the address field. }; }; SetChar(x, y, c); }; if (found == 0) DEBUG_OT_TXTRDT("X/26 triplet found: row=%d triplet=%d UNSUPPORTED addr=0x%02x mode=0x%02x data=0x%02x\n", row, triplet, addr, mode, data); }; }; } // vim: ts=4 sw=4 et vdr-plugin-osdteletext-2.3.1/txtrender.h000066400000000000000000000275531415701714300203550ustar00rootroot00000000000000/*************************************************************** -*- c++ -*- * Copyright (c) 2005 by Udo Richter * * Copyright (c) 2021 by Peter Bieringer (extenions) * * * * txtrender.h - Teletext display abstraction and teletext code * * renderer * * * * 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 OSDTELETEXT_TXTRENDER_H_ #define OSDTELETEXT_TXTRENDER_H_ #include #include // Teletext character sets enum enumCharsets { CHARSET_LATIN_G0 = 0x0000, // native latin (partially todo) CHARSET_LATIN_G0_CZ_SK = 0x0100, // Czech/Slovak (todo) CHARSET_LATIN_G0_EN = 0x0200, // English CHARSET_LATIN_G0_EE = 0x0300, // Estonian (todo) CHARSET_LATIN_G0_FR = 0x0400, // French CHARSET_LATIN_G0_DE = 0x0500, // German CHARSET_LATIN_G0_IT = 0x0600, // Italian CHARSET_LATIN_G0_LV_LT = 0x0700, // Lettish/Lithuanian (todo) CHARSET_LATIN_G0_PL = 0x0800, // Polish (todo) CHARSET_LATIN_G0_PT_ES = 0x0900, // Portuguese/Spanish CHARSET_LATIN_G0_RO = 0x0A00, // Romanian (todo) CHARSET_LATIN_G0_SR_HR_SL = 0x0B00, // Serbian/Croatian/Slovenian (todo) CHARSET_LATIN_G0_SV_FI = 0x0C00, // Swedish/Finnish CHARSET_LATIN_G0_TR = 0x0D00, // Turkish (todo) CHARSET_LATIN_G2 = 0x0E00, // Latin G2 supplementary set (todo) CHARSET_CYRILLIC_G0_SR_HR = 0x0F00, // Serbian/Croatian (todo) CHARSET_CYRILLIC_G0_RU_BG = 0x1000, // Russian/Bulgarian (todo) CHARSET_CYRILLIC_G0_UK = 0x1100, // Ukrainian (todo) CHARSET_CYRILLIC_G2 = 0x1200, // Cyrillic G2 Supplementary (todo) CHARSET_GREEK_G0 = 0x1300, // Greek G0 (todo) CHARSET_GREEK_G2 = 0x1400, // Greeek G2 (todo) CHARSET_ARABIC_G0 = 0x1500, // Arabic G0 (todo) CHARSET_ARABIC_G2 = 0x1600, // Arabic G2 (todo) CHARSET_HEBREW_G0 = 0x1700, // Hebrew G0 (todo) CHARSET_GRAPHICS_G1 = 0x1800, // G1 graphics set CHARSET_GRAPHICS_G1_SEP = 0x1900, // G1 graphics set, separated CHARSET_GRAPHICS_G3 = 0x1A00, // G3 graphics set (todo) CHARSET_INVALID = 0x1F00 // no charset defined }; // Macro to get the lowest non-0 bit position from a bit mask // Should evaluate to const on a const mask #define LowestSet2Bit(mask) ((mask)&0x0001?0:1) #define LowestSet4Bit(mask) ((mask)&0x0003?LowestSet2Bit(mask):LowestSet2Bit((mask)>>2)+2) #define LowestSet8Bit(mask) ((mask)&0x000f?LowestSet4Bit(mask):LowestSet4Bit((mask)>>4)+4) #define LowestSet16Bit(mask) ((mask)&0x00ff?LowestSet8Bit(mask):LowestSet8Bit((mask)>>8)+8) #define LowestSet32Bit(mask) ((mask)&0xffff?LowestSet16Bit(mask):LowestSet16Bit((mask)>>16)+16) // Character modifcation double height: enum enumDblHeight { dblh_Normal=0x00000000, // normal height dblh_Top =0x04000000, // upper half character dblh_Bottom=0x08000000 // lower half character }; // Character modifcation double width: enum enumDblWidth { dblw_Normal=0x00000000, // normal width dblw_Left =0x10000000, // left half character dblw_Right =0x20000000 // right half character }; // Teletext colors enum enumTeletextColor { // level 1: ttcBlack=0, ttcRed=1, ttcGreen=2, ttcYellow=3, ttcBlue=4, ttcMagenta=5, ttcCyan=6, ttcWhite=7, // level 2.5: ttcTransparent=8, ttcHalfRed=9, ttcHalfGreen=10, ttcHalfYellow=11, ttcHalfBlue=12, ttcHalfMagenta=13, ttcHalfCyan=14, ttcGrey=15, // unnamed, level 2.5: ttcColor16=16, ttcColor17=17, ttcColor18=18, ttcColor19=19, ttcColor20=20, ttcColor21=21, ttcColor22=22, ttcColor23=23, ttcColor24=24, ttcColor25=25, ttcColor26=26, ttcColor27=27, ttcColor28=28, ttcColor29=29, ttcColor30=30, ttcColor31=31, ttcFirst=0, ttcLast=31 }; inline enumTeletextColor& operator++(enumTeletextColor& c) { return c=enumTeletextColor(int(c)+1); } inline enumTeletextColor operator++(enumTeletextColor& c, int) { enumTeletextColor tmp(c); ++c; return tmp; } class cTeletextChar { // Wrapper class that represents a teletext character, // including colors and effects. Should optimize back // to 4 byte unsigned int on compile. protected: unsigned int c; static const unsigned int CHAR = 0x000000FF; // character code static const unsigned int CHARSET = 0x00001F00; // character set code, see below static const unsigned int BOXOUT = 0x00004000; // 'boxed' mode hidden area static const unsigned int DIRTY = 0x00008000; // 'dirty' bit - internal marker only static const unsigned int FGCOLOR = 0x001F0000; // 5-bit foreground color code, 3 bit used for now static const unsigned int BGCOLOR = 0x03E00000; // 5-bit background color code, 3 bit used for now static const unsigned int DBLHEIGHT = 0x0C000000; // show double height static const unsigned int DBLWIDTH = 0x30000000; // show double width (todo) static const unsigned int CONCEAL = 0x40000000; // character concealed static const unsigned int BLINK = 0x80000000; // blinking character cTeletextChar(unsigned int cc) { c=cc; } public: cTeletextChar() { c=0; } // inline helper functions: // For each parameter encoded into the 32-bit int, there is // a Get...() to read, a Set...() to write, and a To...() to // return a modified copy inline unsigned int GetC() { return c;}; inline unsigned char GetChar() { return c&CHAR; } inline void SetChar(unsigned char chr) { c=(c&~CHAR)|chr; } inline cTeletextChar ToChar(unsigned char chr) { return cTeletextChar((c&~CHAR)|chr); } inline enumCharsets GetCharset() { return (enumCharsets)(c&CHARSET); } inline void SetCharset(enumCharsets charset) { c=(c&~CHARSET)|charset; } inline cTeletextChar ToCharset(enumCharsets charset) { return cTeletextChar((c&~CHARSET)|charset); } inline enumTeletextColor GetFGColor() { return (enumTeletextColor)((c&FGCOLOR) >> LowestSet32Bit(FGCOLOR)); } inline void SetFGColor(enumTeletextColor fgc) { c=(c&~FGCOLOR) | (fgc << LowestSet32Bit(FGCOLOR)); } inline cTeletextChar ToFGColor(enumTeletextColor fgc) { return cTeletextChar((c&~FGCOLOR) | (fgc << LowestSet32Bit(FGCOLOR))); } inline enumTeletextColor GetBGColor() { return (enumTeletextColor)((c&BGCOLOR) >> LowestSet32Bit(BGCOLOR)); } inline void SetBGColor(enumTeletextColor bgc) { c=(c&~BGCOLOR) | (bgc << LowestSet32Bit(BGCOLOR)); } inline cTeletextChar ToBGColor(enumTeletextColor bgc) { return cTeletextChar((c&~BGCOLOR) | (bgc << LowestSet32Bit(BGCOLOR))); } inline bool GetBoxedOut() { return c&BOXOUT; } inline void SetBoxedOut(bool BoxedOut) { c=(BoxedOut)?(c|BOXOUT):(c&~BOXOUT); } inline cTeletextChar ToBoxedOut(bool BoxedOut) { return cTeletextChar((BoxedOut)?(c|BOXOUT):(c&~BOXOUT)); } inline bool GetDirty() { return c&DIRTY; } inline void SetDirty(bool Dirty) { c=(Dirty)?(c|DIRTY):(c&~DIRTY); } inline cTeletextChar ToDirty(bool Dirty) { return cTeletextChar((Dirty)?(c|DIRTY):(c&~DIRTY)); } inline enumDblHeight GetDblHeight() { return (enumDblHeight)(c&DBLHEIGHT); } inline void SetDblHeight(enumDblHeight dh) { c=(c&~(DBLHEIGHT)) | dh; } inline cTeletextChar ToDblHeight(enumDblHeight dh) { return cTeletextChar((c&~(DBLHEIGHT)) | dh); } inline enumDblWidth GetDblWidth() { return (enumDblWidth)(c&DBLWIDTH); } inline void SetDblWidth(enumDblWidth dw) { c=(c&~(DBLWIDTH)) | dw; } inline cTeletextChar ToDblWidth(enumDblWidth dw) { return cTeletextChar((c&~(DBLWIDTH)) | dw); } inline bool GetConceal() { return c&CONCEAL; } inline void SetConceal(bool Conceal) { c=(Conceal)?(c|CONCEAL):(c&~CONCEAL); } inline cTeletextChar ToConceal(bool Conceal) { return cTeletextChar((Conceal)?(c|CONCEAL):(c&~CONCEAL)); } inline bool GetBlink() { return c&BLINK; } inline void SetBlink(bool Blink) { c=(Blink)?(c|BLINK):(c&~BLINK); } inline cTeletextChar ToBlink(bool Blink) { return cTeletextChar((Blink)?(c|BLINK):(c&~BLINK)); } bool operator==(cTeletextChar &chr) { return c==chr.c; } bool operator!=(cTeletextChar &chr) { return c!=chr.c; } }; class cRenderPage { // Abstraction of a 40x25 teletext character page // with all special attributes and colors // Additionally tracks changes by maintaining a // 'dirty' flag on each character protected: cTeletextChar Page[40][27]; int Flags; // 0x80 C4 - Erase page // 0x40 C5 - News flash // 0x20 C6 - Subtitle // 0x10 C7 - Suppress Header // 0x08 C8 - Update // 0x04 C9 - Interrupt Sequence // 0x02 C10 - Inhibit Display // 0x01 C11 - Magazine Serial mode int Lang; // 3-bit language number from header bool Dirty; // At least one character is dirty bool DirtyAll; // Consider all characters dirty, regardless of flag // Font Code pages int FirstG0CodePage; // 7-bit number, lower 3 bits ignored int SecondG0CodePage; // 7-bit number public: cRenderPage(); #define CHECK_XY_LIMIT(x,y) ((x < 0) || (x >= 40) || (y < 0) || (y >= 27)) cTeletextChar GetChar(int x, int y) { // Read character content from page if (CHECK_XY_LIMIT(x,y)) { esyslog("osdteletext: WARN: out of bounds access to teletext page (GetChar x=%d y=%d)", x, y); return cTeletextChar(); } return Page[x][y].ToDirty(false); } bool IsDirty() { // global dirty status return Dirty; } bool IsDirty(int x, int y) { // local dirty status if (CHECK_XY_LIMIT(x,y)) { esyslog("osdteletext: WARN: out of bounds access to teletext page (IsDirty x=%d y=%d)", x, y); return false; } return Page[x][y].GetDirty() | DirtyAll; } void MakeDirty(int x, int y) { // force one character dirty if (CHECK_XY_LIMIT(x,y)) { esyslog("osdteletext: WARN: out of bounds access to teletext page (MakeDirty x=%d y=%d)", x, y); return; } Page[x][y].SetDirty(true); Dirty=true; } void SetChar(int x, int y, cTeletextChar c) { // Set character at given location if (CHECK_XY_LIMIT(x,y)) { esyslog("osdteletext: WARN: out of bounds access to teletext page (SetChar x=%d y=%d c=%x)", x, y, c.GetC()); return; } if (GetChar(x,y) != c) { Page[x][y]=c.ToDirty(true); Dirty=true; } } void ReadTeletextHeader(unsigned char *Header); // Read header from teletext page // Header must be a 12 bytes buffer void RenderTeletextCode(unsigned char *PageCode); // Interprete teletext code referenced by PageCode // and draw the whole page content into this object // PageCode must be a buffer containing TelePageData structure (see storage.h) }; #endif