From e00b3dd652979f5a7700d0a124832ac913fa9ed4 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Wed, 28 Apr 2010 21:13:43 +0200 Subject: checked in initial version --- GNUmakefile | 8 + makefiles/README | 4 + makefiles/gmake/clean.mk | 41 + makefiles/gmake/compiler.mk | 347 + makefiles/gmake/depend.mk | 76 + makefiles/gmake/dist.mk | 40 + makefiles/gmake/guess_env | 224 + makefiles/gmake/help.mk | 15 + makefiles/gmake/i18n.mk | 103 + makefiles/gmake/install.mk | 64 + makefiles/gmake/libs.mk | 53 + makefiles/gmake/platform.mk | 189 + makefiles/gmake/platform.mk.vars | 16 + makefiles/gmake/sub.mk | 28 + makefiles/gmake/top.mk | 74 + makefiles/nmake/clean.mk | 48 + makefiles/nmake/compiler.mk | 92 + makefiles/nmake/config.mk | 44 + makefiles/nmake/depend.mk | 67 + makefiles/nmake/help.mk | 9 + makefiles/nmake/platform.mk | 28 + makefiles/nmake/sub.mk | 27 + makefiles/nmake/top.mk | 39 + src/GNUmakefile | 68 + tvision/INSTALL.txt | 22 + tvision/Makefile.bcc | 36 + tvision/Makefile.in | 56 + tvision/Makefile.nmk | 16 + tvision/Makefile.wat | 25 + tvision/THANKS | 53 + tvision/TODO | 10 + tvision/borland.txt | 50 + tvision/change.log | 3852 ++++++++++ tvision/change1.log | 1621 +++++ tvision/classes/alcon/alcon.cc | 1632 +++++ tvision/classes/alcon/alcondis.cc | 119 + tvision/classes/alcon/alconkey.cc | 79 + tvision/classes/alcon/alconmouse.cc | 47 + tvision/classes/alcon/alconscr.cc | 509 ++ tvision/classes/calcdisp.cc | 291 + tvision/classes/calculat.cc | 68 + tvision/classes/codepage.cc | 2769 ++++++++ tvision/classes/configfile.cc | 953 +++ tvision/classes/dos/dosdis.cc | 805 +++ tvision/classes/dos/doskey.cc | 543 ++ tvision/classes/dos/dosmouse.cc | 521 ++ tvision/classes/dos/dosscr.cc | 1004 +++ tvision/classes/dos/rhscreen.cc | 253 + tvision/classes/dos/screen.cc | 51 + tvision/classes/dos/sescreen.cc | 1548 ++++ tvision/classes/dos/vesa.cc | 589 ++ tvision/classes/dos/vga.cc | 449 ++ tvision/classes/dos/vgaregs.c | 225 + tvision/classes/dos/vgaregs.h | 320 + tvision/classes/dos/vgastate.c | 207 + tvision/classes/dos/vgastate.h | 19 + tvision/classes/fontcoll.cc | 574 ++ tvision/classes/fpbase.cc | 143 + tvision/classes/fpstream.cc | 83 + tvision/classes/help.cc | 262 + tvision/classes/helpbase.cc | 651 ++ tvision/classes/ifpstrea.cc | 55 + tvision/classes/iopstrea.cc | 34 + tvision/classes/ipstream.cc | 283 + tvision/classes/linux/linuxdis.cc | 382 + tvision/classes/linux/linuxkey.cc | 937 +++ tvision/classes/linux/linuxmouse.cc | 142 + tvision/classes/linux/linuxscr.cc | 1958 ++++++ tvision/classes/ofpstrea.cc | 55 + tvision/classes/opstream.cc | 237 + tvision/classes/osclipboard.cc | 34 + tvision/classes/pstream.cc | 132 + tvision/classes/qnx4/qnx4dis.cc | 230 + tvision/classes/qnx4/qnx4key.cc | 288 + tvision/classes/qnx4/qnx4mouse.cc | 254 + tvision/classes/qnx4/qnx4scr.cc | 723 ++ tvision/classes/qnxrtp/qnxdis.cc | 171 + tvision/classes/qnxrtp/qnxkey.cc | 477 ++ tvision/classes/qnxrtp/qnxmouse.cc | 241 + tvision/classes/qnxrtp/qnxscr.cc | 577 ++ tvision/classes/tapplica.cc | 178 + tvision/classes/tbackgro.cc | 76 + tvision/classes/tbutton.cc | 378 + tvision/classes/tchdirdi.cc | 216 + tvision/classes/tcheckbo.cc | 59 + tvision/classes/tclrdisp.cc | 102 + tvision/classes/tcluster.cc | 408 ++ tvision/classes/tcollect.cc | 44 + tvision/classes/tcolordi.cc | 184 + tvision/classes/tcolorgr.cc | 224 + tvision/classes/tcolorit.cc | 118 + tvision/classes/tcolorse.cc | 187 + tvision/classes/tcommand.cc | 267 + tvision/classes/tdesktop.cc | 281 + tvision/classes/tdialog.cc | 108 + tvision/classes/tdircoll.cc | 40 + tvision/classes/tdirlist.cc | 537 ++ tvision/classes/tdisplay.cc | 493 ++ tvision/classes/tdrawbuf.cc | 257 + tvision/classes/teditor.cc | 1348 ++++ tvision/classes/teditorf.cc | 106 + tvision/classes/teditwin.cc | 126 + tvision/classes/tevent.cc | 223 + tvision/classes/tfilecol.cc | 120 + tvision/classes/tfiledia.cc | 326 + tvision/classes/tfileedi.cc | 370 + tvision/classes/tfileinf.cc | 133 + tvision/classes/tfileinp.cc | 83 + tvision/classes/tfilelis.cc | 623 ++ tvision/classes/tfilterv.cc | 85 + tvision/classes/tframe.cc | 386 + tvision/classes/tgkey.cc | 366 + tvision/classes/tgroup.cc | 743 ++ tvision/classes/thistory.cc | 143 + tvision/classes/thistvie.cc | 89 + tvision/classes/thistwin.cc | 56 + tvision/classes/thwmouse.cc | 162 + tvision/classes/tindicat.cc | 107 + tvision/classes/tinputli.cc | 563 ++ tvision/classes/tlabel.cc | 179 + tvision/classes/tlistbox.cc | 139 + tvision/classes/tlistvie.cc | 530 ++ tvision/classes/tlookupv.cc | 110 + tvision/classes/tmemo.cc | 105 + tvision/classes/tmenubar.cc | 190 + tvision/classes/tmenubox.cc | 164 + tvision/classes/tmenuvie.cc | 650 ++ tvision/classes/tmonosel.cc | 91 + tvision/classes/tmouse.cc | 27 + tvision/classes/tnscolle.cc | 235 + tvision/classes/tnssorte.cc | 114 + tvision/classes/tobject.cc | 23 + tvision/classes/tpalette.cc | 51 + tvision/classes/tparamte.cc | 96 + tvision/classes/tpoint.cc | 42 + tvision/classes/tprogini.cc | 53 + tvision/classes/tprogram.cc | 409 ++ tvision/classes/tpwobj.cc | 20 + tvision/classes/tpwreado.cc | 41 + tvision/classes/tpwritte.cc | 62 + tvision/classes/tpxvalid.cc | 500 ++ tvision/classes/tradiobu.cc | 98 + tvision/classes/trangeva.cc | 142 + tvision/classes/trescoll.cc | 60 + tvision/classes/tresfile.cc | 194 + tvision/classes/tscreen.cc | 454 ++ tvision/classes/tscrollb.cc | 360 + tvision/classes/tscrolle.cc | 215 + tvision/classes/tsortedc.cc | 40 + tvision/classes/tsortedl.cc | 188 + tvision/classes/tstatict.cc | 159 + tvision/classes/tstatusd.cc | 43 + tvision/classes/tstatusl.cc | 371 + tvision/classes/tstrinde.cc | 21 + tvision/classes/tstringc.cc | 65 + tvision/classes/tstringl.cc | 86 + tvision/classes/tstrlist.cc | 76 + tvision/classes/tstrmcla.cc | 26 + tvision/classes/tstrmtyp.cc | 62 + tvision/classes/tsubmenu.cc | 50 + tvision/classes/ttermina.cc | 242 + tvision/classes/ttextdev.cc | 35 + tvision/classes/tvalidat.cc | 77 + tvision/classes/tvedit1.cc | 180 + tvision/classes/tvedit2.cc | 111 + tvision/classes/tvedit3.cc | 208 + tvision/classes/tview.cc | 1249 ++++ tvision/classes/tvintl.cc | 298 + tvision/classes/tvtext1.cc | 142 + tvision/classes/tvtext2.cc | 1 + tvision/classes/twindow.cc | 275 + tvision/classes/unix/unixdis.cc | 130 + tvision/classes/unix/unixkey.cc | 566 ++ tvision/classes/unix/unixmouse.cc | 148 + tvision/classes/unix/unixscr.cc | 1117 +++ tvision/classes/unix/xtermdis.cc | 355 + tvision/classes/unix/xtermkey.cc | 889 +++ tvision/classes/unix/xtermmouse.cc | 93 + tvision/classes/unix/xtermscr.cc | 952 +++ tvision/classes/win32/win32clip.cc | 144 + tvision/classes/win32/win32dis.cc | 226 + tvision/classes/win32/win32key.cc | 464 ++ tvision/classes/win32/win32mouse.cc | 126 + tvision/classes/win32/win32scr.cc | 564 ++ tvision/classes/wingr/wingrdis.cc | 1623 +++++ tvision/classes/wingr/wingrkey.cc | 517 ++ tvision/classes/wingr/wingrmouse.cc | 188 + tvision/classes/wingr/wingrscr.cc | 776 ++ tvision/classes/winnt/winntdis.cc | 218 + tvision/classes/winnt/winntkey.cc | 326 + tvision/classes/winnt/winntmouse.cc | 78 + tvision/classes/winnt/winntscr.cc | 577 ++ tvision/classes/x11/x11dis.cc | 129 + tvision/classes/x11/x11key.cc | 479 ++ tvision/classes/x11/x11mouse.cc | 107 + tvision/classes/x11/x11src.cc | 2710 +++++++ tvision/compat/beep.c | 11 + tvision/compat/compat.gpr | Bin 0 -> 18684 bytes tvision/compat/compat.imk | 226 + tvision/compat/compat.umk | 115 + tvision/compat/drivevalid.c | 44 + tvision/compat/expandpath.c | 41 + tvision/compat/fexpand.c | 114 + tvision/compat/fileattrs.c | 197 + tvision/compat/fileexists.c | 13 + tvision/compat/filelength.c | 23 + tvision/compat/fixpath.c | 305 + tvision/compat/fnmatch.c | 150 + tvision/compat/getcurdir.c | 68 + tvision/compat/getline.c | 189 + tvision/compat/getopt.c | 754 ++ tvision/compat/getopt1.c | 174 + tvision/compat/getshell.c | 20 + tvision/compat/glob.c | 422 ++ tvision/compat/globfree.c | 20 + tvision/compat/iffilelen.cc | 46 + tvision/compat/isdir.c | 19 + tvision/compat/isrelpath.c | 33 + tvision/compat/iswild.c | 12 + tvision/compat/itoa.c | 48 + tvision/compat/mkstemp.c | 48 + tvision/compat/nl_langinfo.c | 71 + tvision/compat/ntdirent.c | 161 + tvision/compat/obj/delete.me | 2 + tvision/compat/pathvalid.c | 62 + tvision/compat/regex.c | 4973 +++++++++++++ tvision/compat/releasec.c | 68 + tvision/compat/snprintf.c | 892 +++ tvision/compat/ssc_streams.cc | 294 + tvision/compat/strlwr.c | 16 + tvision/compat/strupr.c | 16 + tvision/compat/ticks.c | 42 + tvision/compat/unc.c | 96 + tvision/compat/unc_95.c | 112 + tvision/compat/unc_nt.c | 109 + tvision/compat/validfilename.c | 51 + tvision/compat/yieldpro.c | 75 + tvision/config.pl | 1355 ++++ tvision/confignt.pl | 67 + tvision/configset | 30 + tvision/configset.bat | 14 + tvision/configure | 2 + tvision/configure.bat | 3 + tvision/conflib.pl | 1524 ++++ tvision/copying | 339 + tvision/copying.rh | 46 + tvision/debian/.cvsignore | 5 + tvision/debian/README | 34 + tvision/debian/README.debian | 19 + tvision/debian/buildpackage | 5 + tvision/debian/changelog | 543 ++ tvision/debian/control | 43 + tvision/debian/control.in | 43 + tvision/debian/copyright | 15 + tvision/debian/diversions.ex | 1 + tvision/debian/files_to_backup | 1 + tvision/debian/info.ex | 15 + tvision/debian/maintainer.notes | 30 + tvision/debian/rhtvision.postinst | 6 + tvision/debian/rhtvision.postrm | 6 + tvision/debian/rules | 138 + tvision/debian/shlibs.local.ex | 1 + tvision/debian/watch.ex | 5 + tvision/djgpp/compress.bat | 2 + tvision/djgpp/compress.pl | 111 + tvision/djgpp/distlist | 9 + tvision/djgpp/sacadeb.bat | 10 + tvision/djgpp/tmp/delete.me | 2 + tvision/doc/Alcon.txt | 112 + tvision/doc/CodePages.txt | 219 + tvision/doc/ConfigFile.txt | 200 + tvision/doc/DOS.txt | 171 + tvision/doc/Eterm.txt | 59 + tvision/doc/I18n.txt | 251 + tvision/doc/Linux.txt | 274 + tvision/doc/QNX.txt | 31 + tvision/doc/Streams.txt | 88 + tvision/doc/TVReference.html | 3862 ++++++++++ tvision/doc/Win32.txt | 103 + tvision/doc/WinGr.txt | 11 + tvision/doc/X11.txt | 177 + tvision/doc/XTerm.txt | 95 + tvision/doc/html.frt | 272 + tvision/doc/install/bcc.txt | 70 + tvision/doc/install/cygwin.txt | 54 + tvision/doc/install/djgpp.txt | 84 + tvision/doc/install/linux.txt | 41 + tvision/doc/install/mingwin.txt | 51 + tvision/doc/install/msvc.txt | 105 + tvision/doc/install/tools.txt | 137 + tvision/doc/install/unix.txt | 113 + tvision/doc/install/watcom.txt | 54 + tvision/doc/libdocs.epr | Bin 0 -> 1202 bytes tvision/doc/troubleshooting/Linux/1/code.cc | 10 + tvision/doc/troubleshooting/Linux/1/readme.txt | 42 + tvision/doc/troubleshooting/Linux/1/test-utf8.txt | 3 + tvision/doc/troubleshooting/Linux/1/test.txt | 3 + tvision/doc/troubleshooting/Linux/1/utf8.cc | 11 + tvision/doc/troubleshooting/Linux/2/readme.txt | 38 + tvision/doc/troubleshooting/Linux/3/readme.txt | 21 + tvision/doc/troubleshooting/Linux/4/readme.txt | 39 + tvision/doc/troubleshooting/Linux/4/test.cc | 297 + tvision/doc/troubleshooting/Linux/readme.txt | 8 + tvision/doc/troubleshooting/readme.txt | 6 + tvision/drivers2.cc | 86 + tvision/dual.cc | 52 + tvision/examples/Makefile | 118 + tvision/examples/bhelp/.tvrc | 6 + tvision/examples/bhelp/bhelp.cc | 325 + tvision/examples/bhelp/bhelp.h | 80 + tvision/examples/bhelp/rhide.env | 5 + tvision/examples/bhelp/thelp.bmk | 10 + tvision/examples/bhelp/thelp.cc | 221 + tvision/examples/bhelp/thelp.gpr | Bin 0 -> 11230 bytes tvision/examples/bhelp/thelp.mkf | 11 + tvision/examples/bhelp/thelp.umk | 22 + tvision/examples/clipboard/rhide.env | 5 + tvision/examples/clipboard/test.bmk | 10 + tvision/examples/clipboard/test.cc | 174 + tvision/examples/clipboard/test.gpr | Bin 0 -> 10994 bytes tvision/examples/clipboard/test.mkf | 11 + tvision/examples/clipboard/test.umk | 17 + tvision/examples/common.bmk | 12 + tvision/examples/cyrillic/linuxkoi8/README | 43 + tvision/examples/cyrillic/linuxkoi8/koi8-r.acm.gz | Bin 0 -> 994 bytes tvision/examples/cyrillic/linuxkoi8/koi8-r.psf.gz | Bin 0 -> 1936 bytes tvision/examples/cyrillic/linuxkoi8/lat1-16.psf.gz | Bin 0 -> 1973 bytes tvision/examples/cyrillic/linuxkoi8/rhide.env | 5 + tvision/examples/cyrillic/linuxkoi8/ru1.kmap.gz | Bin 0 -> 3489 bytes tvision/examples/cyrillic/linuxkoi8/setkoi8.sh | 16 + tvision/examples/cyrillic/linuxkoi8/setlat1.sh | 17 + tvision/examples/cyrillic/linuxkoi8/test.cc | 54 + tvision/examples/cyrillic/linuxkoi8/test.gpr | Bin 0 -> 10994 bytes tvision/examples/cyrillic/linuxkoi8/test.mkf | 11 + tvision/examples/cyrillic/linuxkoi8/test.umk | 17 + tvision/examples/cyrillic/linuxkoi8/trivial.acm | 129 + tvision/examples/cyrillic/x11koi8/rhide.env | 5 + tvision/examples/cyrillic/x11koi8/test.cc | 110 + tvision/examples/cyrillic/x11koi8/test.gpr | Bin 0 -> 10994 bytes tvision/examples/cyrillic/x11koi8/test.mkf | 11 + tvision/examples/cyrillic/x11koi8/test.umk | 17 + tvision/examples/demo/ascii.cc | 306 + tvision/examples/demo/ascii.h | 140 + tvision/examples/demo/calendar.cc | 297 + tvision/examples/demo/calendar.h | 102 + tvision/examples/demo/demo.bmk | 10 + tvision/examples/demo/demo.gpr | Bin 0 -> 13092 bytes tvision/examples/demo/demo.mkf | 11 + tvision/examples/demo/demo.umk | 57 + tvision/examples/demo/demohelp.h | 40 + tvision/examples/demo/demohelp.h32 | Bin 0 -> 16221 bytes tvision/examples/demo/diffs.cc | 416 ++ tvision/examples/demo/fileview.cc | 186 + tvision/examples/demo/fileview.h | 88 + tvision/examples/demo/gadgets.cc | 185 + tvision/examples/demo/gadgets.h | 57 + tvision/examples/demo/mousedlg.cc | 155 + tvision/examples/demo/mousedlg.h | 44 + tvision/examples/demo/puzzle.cc | 371 + tvision/examples/demo/puzzle.h | 102 + tvision/examples/demo/rhide.env | 5 + tvision/examples/demo/tvcmds.h | 28 + tvision/examples/demo/tvdemo.h | 71 + tvision/examples/demo/tvdemo1.cc | 327 + tvision/examples/demo/tvdemo2.cc | 430 ++ tvision/examples/demo/tvdemo3.cc | 273 + tvision/examples/desklogo/desklogo.bmk | 10 + tvision/examples/desklogo/desklogo.cc | 224 + tvision/examples/desklogo/desklogo.gpr | Bin 0 -> 11002 bytes tvision/examples/desklogo/desklogo.mkf | 11 + tvision/examples/desklogo/desklogo.umk | 17 + tvision/examples/desklogo/rhide.env | 5 + tvision/examples/desklogo/set-logo.bmk | 10 + tvision/examples/desklogo/set-logo.cc | 259 + tvision/examples/desklogo/set-logo.gpr | Bin 0 -> 10987 bytes tvision/examples/desklogo/set-logo.mkf | 11 + tvision/examples/desklogo/set-logo.umk | 17 + tvision/examples/desklogo/tv_logo.bmk | 10 + tvision/examples/desklogo/tv_logo.cc | 258 + tvision/examples/desklogo/tv_logo.gpr | Bin 0 -> 10999 bytes tvision/examples/desklogo/tv_logo.mkf | 11 + tvision/examples/desklogo/tv_logo.umk | 17 + tvision/examples/dlgdsn/codebldr.cc | 510 ++ tvision/examples/dlgdsn/consted.cc | 461 ++ tvision/examples/dlgdsn/consted.h | 91 + tvision/examples/dlgdsn/dsgdata.h | 136 + tvision/examples/dlgdsn/dsgobjs.cc | 1504 ++++ tvision/examples/dlgdsn/dsgobjs.h | 369 + tvision/examples/dlgdsn/fdconsts.h | 105 + tvision/examples/dlgdsn/freedsgn.cc | 370 + tvision/examples/dlgdsn/libtest.gpr | Bin 0 -> 13769 bytes tvision/examples/dlgdsn/libtest.mkf | 11 + tvision/examples/dlgdsn/libtest.umk | 52 + tvision/examples/dlgdsn/propdlgs.cc | 545 ++ tvision/examples/dlgdsn/propdlgs.h | 56 + tvision/examples/dlgdsn/propedit.cc | 1220 ++++ tvision/examples/dlgdsn/propedit.h | 122 + tvision/examples/dlgdsn/rhide.env | 5 + tvision/examples/dlgdsn/strmoper.cc | 108 + tvision/examples/dlgdsn/strmoper.h | 33 + tvision/examples/dlgdsn/tappwnd.cc | 159 + tvision/examples/dyntxt/dyntext.bmk | 10 + tvision/examples/dyntxt/dyntext.cpp | 89 + tvision/examples/dyntxt/dyntext.gpr | Bin 0 -> 11249 bytes tvision/examples/dyntxt/dyntext.h | 59 + tvision/examples/dyntxt/dyntext.mkf | 11 + tvision/examples/dyntxt/dyntext.umk | 22 + tvision/examples/dyntxt/readme | 54 + tvision/examples/dyntxt/rhide.env | 5 + tvision/examples/dyntxt/testdyn.cpp | 195 + tvision/examples/eterm/menus.cfg | 93 + tvision/examples/eterm/theme.cfg | 620 ++ tvision/examples/fonts/font.016 | Bin 0 -> 4096 bytes tvision/examples/fonts/genraw.cc | 113 + tvision/examples/fonts/genraw.gpr | Bin 0 -> 11623 bytes tvision/examples/fonts/genraw.mkf | 11 + tvision/examples/fonts/genraw.umk | 17 + tvision/examples/fonts/ocr.sft | Bin 0 -> 19051 bytes tvision/examples/fonts/rhide.env | 5 + tvision/examples/fonts/test.cc | 260 + tvision/examples/fonts/test.gpr | Bin 0 -> 10994 bytes tvision/examples/fonts/test.mkf | 11 + tvision/examples/fonts/test.umk | 17 + tvision/examples/gen_mkf.pl | 26 + tvision/examples/helpdemo/helpdemo.bmk | 10 + tvision/examples/helpdemo/helpdemo.cc | 207 + tvision/examples/helpdemo/helpdemo.gpr | Bin 0 -> 11006 bytes tvision/examples/helpdemo/helpdemo.mkf | 11 + tvision/examples/helpdemo/helpdemo.umk | 17 + tvision/examples/helpdemo/rhide.env | 5 + tvision/examples/i18n/README | 29 + tvision/examples/i18n/es.po | 4 + tvision/examples/i18n/extract.sh | 2 + tvision/examples/i18n/intl/es/LC_MESSAGES/test.mo | Bin 0 -> 67 bytes .../examples/i18n/intl/es/LC_MESSAGES/tvision.mo | Bin 0 -> 8427 bytes tvision/examples/i18n/rhide.env | 5 + tvision/examples/i18n/test.cc | 71 + tvision/examples/i18n/test.gpr | Bin 0 -> 10994 bytes tvision/examples/i18n/test.mkf | 11 + tvision/examples/i18n/test.po | 4 + tvision/examples/i18n/test.umk | 17 + tvision/examples/inplis/implis.bmk | 10 + tvision/examples/inplis/implis.gpr | Bin 0 -> 11224 bytes tvision/examples/inplis/implis.mkf | 11 + tvision/examples/inplis/implis.umk | 22 + tvision/examples/inplis/inplist.cpp | 167 + tvision/examples/inplis/inplist.h | 69 + tvision/examples/inplis/rhide.env | 5 + tvision/examples/inplis/test.cpp | 116 + tvision/examples/listvi/listbox2.cpp | 163 + tvision/examples/listvi/lst_view.bmk | 10 + tvision/examples/listvi/lst_view.cpp | 175 + tvision/examples/listvi/lst_view.gpr | Bin 0 -> 11244 bytes tvision/examples/listvi/lst_view.h | 46 + tvision/examples/listvi/lst_view.mkf | 11 + tvision/examples/listvi/lst_view.umk | 22 + tvision/examples/listvi/readme.txt | 18 + tvision/examples/listvi/rhide.env | 5 + tvision/examples/msgcls/msgcls.bmk | 10 + tvision/examples/msgcls/msgcls.gpr | Bin 0 -> 11145 bytes tvision/examples/msgcls/msgcls.mkf | 11 + tvision/examples/msgcls/msgcls.umk | 22 + tvision/examples/msgcls/readme.txt | 72 + tvision/examples/msgcls/rhide.env | 5 + tvision/examples/msgcls/testdyn.cpp | 148 + tvision/examples/msgcls/tlnmsg.cpp | 291 + tvision/examples/msgcls/tlnmsg.h | 113 + tvision/examples/patchenv.pl | 123 + tvision/examples/porting.txt | 46 + tvision/examples/progba/example.cpp | 260 + tvision/examples/progba/makerez.cpp | 109 + tvision/examples/progba/readrez.cpp | 239 + tvision/examples/progba/rhide.env | 5 + tvision/examples/progba/test.bmk | 10 + tvision/examples/progba/test.gpr | Bin 0 -> 11128 bytes tvision/examples/progba/test.mkf | 11 + tvision/examples/progba/test.umk | 22 + tvision/examples/progba/tprogbar.cpp | 179 + tvision/examples/progba/tprogbar.h | 93 + tvision/examples/readme.txt | 99 + tvision/examples/sdlg/dlg.h | 100 + tvision/examples/sdlg/main.cpp | 66 + tvision/examples/sdlg/rhide.env | 5 + tvision/examples/sdlg/scrldlg.cpp | 48 + tvision/examples/sdlg/scrlgrp.cpp | 172 + tvision/examples/sdlg/test.bmk | 10 + tvision/examples/sdlg/test.gpr | Bin 0 -> 11343 bytes tvision/examples/sdlg/test.mkf | 11 + tvision/examples/sdlg/test.umk | 27 + tvision/examples/sdlg2/dlg.h | 102 + tvision/examples/sdlg2/main.cpp | 67 + tvision/examples/sdlg2/rhide.env | 5 + tvision/examples/sdlg2/scrldlg.cpp | 48 + tvision/examples/sdlg2/scrlgrp.cpp | 172 + tvision/examples/sdlg2/test.bmk | 10 + tvision/examples/sdlg2/test.gpr | Bin 0 -> 11344 bytes tvision/examples/sdlg2/test.mkf | 11 + tvision/examples/sdlg2/test.umk | 27 + tvision/examples/tcombo/nmcmbobx.cpp | 23 + tvision/examples/tcombo/nmcmbovw.cpp | 23 + tvision/examples/tcombo/nmcmbown.cpp | 23 + tvision/examples/tcombo/nmsinput.cpp | 23 + tvision/examples/tcombo/readme.txt | 51 + tvision/examples/tcombo/rhide.env | 5 + tvision/examples/tcombo/scombobx.cpp | 28 + tvision/examples/tcombo/scombovw.cpp | 29 + tvision/examples/tcombo/scombown.cpp | 28 + tvision/examples/tcombo/ssinputl.cpp | 28 + tvision/examples/tcombo/tcmbovwr.cpp | 155 + tvision/examples/tcombo/tcmbowin.cpp | 106 + tvision/examples/tcombo/tcombo.txt | 189 + tvision/examples/tcombo/tcombobx.cpp | 177 + tvision/examples/tcombo/tcombobx.h | 207 + tvision/examples/tcombo/test.bmk | 10 + tvision/examples/tcombo/test.cpp | 140 + tvision/examples/tcombo/test.gpr | Bin 0 -> 12830 bytes tvision/examples/tcombo/test.mkf | 11 + tvision/examples/tcombo/test.umk | 77 + tvision/examples/tcombo/tsinputl.cpp | 158 + tvision/examples/tcombo/tsinputl.h | 54 + tvision/examples/terminal/rhide.env | 5 + tvision/examples/terminal/terminal.cc | 115 + tvision/examples/terminal/test.bmk | 10 + tvision/examples/terminal/test.gpr | Bin 0 -> 11021 bytes tvision/examples/terminal/test.mkf | 11 + tvision/examples/terminal/test.umk | 17 + tvision/examples/tprogb/calc.cpp | 215 + tvision/examples/tprogb/rhide.env | 5 + tvision/examples/tprogb/test.bmk | 10 + tvision/examples/tprogb/test.gpr | Bin 0 -> 11211 bytes tvision/examples/tprogb/test.mkf | 11 + tvision/examples/tprogb/test.umk | 22 + tvision/examples/tprogb/tprogbar.cpp | 186 + tvision/examples/tprogb/tprogbar.h | 57 + tvision/examples/tutorial/rhide.env | 5 + tvision/examples/tutorial/tvguid01.bmk | 9 + tvision/examples/tutorial/tvguid01.cc | 51 + tvision/examples/tutorial/tvguid01.gpr | Bin 0 -> 11002 bytes tvision/examples/tutorial/tvguid01.mkf | 11 + tvision/examples/tutorial/tvguid01.umk | 17 + tvision/examples/tutorial/tvguid02.bmk | 9 + tvision/examples/tutorial/tvguid02.cc | 72 + tvision/examples/tutorial/tvguid02.gpr | Bin 0 -> 11002 bytes tvision/examples/tutorial/tvguid02.mkf | 11 + tvision/examples/tutorial/tvguid02.umk | 17 + tvision/examples/tutorial/tvguid03.bmk | 9 + tvision/examples/tutorial/tvguid03.cc | 92 + tvision/examples/tutorial/tvguid03.gpr | Bin 0 -> 11002 bytes tvision/examples/tutorial/tvguid03.mkf | 11 + tvision/examples/tutorial/tvguid03.umk | 17 + tvision/examples/tutorial/tvguid04.bmk | 9 + tvision/examples/tutorial/tvguid04.cc | 153 + tvision/examples/tutorial/tvguid04.gpr | Bin 0 -> 11002 bytes tvision/examples/tutorial/tvguid04.mkf | 11 + tvision/examples/tutorial/tvguid04.umk | 17 + tvision/examples/tutorial/tvguid05.bmk | 9 + tvision/examples/tutorial/tvguid05.cc | 179 + tvision/examples/tutorial/tvguid05.gpr | Bin 0 -> 11002 bytes tvision/examples/tutorial/tvguid05.mkf | 11 + tvision/examples/tutorial/tvguid05.umk | 17 + tvision/examples/tutorial/tvguid06.bmk | 9 + tvision/examples/tutorial/tvguid06.cc | 223 + tvision/examples/tutorial/tvguid06.gpr | Bin 0 -> 11002 bytes tvision/examples/tutorial/tvguid06.mkf | 11 + tvision/examples/tutorial/tvguid06.umk | 17 + tvision/examples/tutorial/tvguid07.bmk | 9 + tvision/examples/tutorial/tvguid07.cc | 232 + tvision/examples/tutorial/tvguid07.gpr | Bin 0 -> 11002 bytes tvision/examples/tutorial/tvguid07.mkf | 11 + tvision/examples/tutorial/tvguid07.umk | 17 + tvision/examples/tutorial/tvguid08.bmk | 9 + tvision/examples/tutorial/tvguid08.cc | 254 + tvision/examples/tutorial/tvguid08.gpr | Bin 0 -> 11002 bytes tvision/examples/tutorial/tvguid08.mkf | 11 + tvision/examples/tutorial/tvguid08.umk | 17 + tvision/examples/tutorial/tvguid09.bmk | 9 + tvision/examples/tutorial/tvguid09.cc | 282 + tvision/examples/tutorial/tvguid09.gpr | Bin 0 -> 11002 bytes tvision/examples/tutorial/tvguid09.mkf | 11 + tvision/examples/tutorial/tvguid09.umk | 17 + tvision/examples/tutorial/tvguid10.bmk | 9 + tvision/examples/tutorial/tvguid10.cc | 294 + tvision/examples/tutorial/tvguid10.gpr | Bin 0 -> 11002 bytes tvision/examples/tutorial/tvguid10.mkf | 11 + tvision/examples/tutorial/tvguid10.umk | 17 + tvision/examples/tutorial/tvguid11.bmk | 9 + tvision/examples/tutorial/tvguid11.cc | 317 + tvision/examples/tutorial/tvguid11.gpr | Bin 0 -> 11002 bytes tvision/examples/tutorial/tvguid11.mkf | 11 + tvision/examples/tutorial/tvguid11.umk | 17 + tvision/examples/tutorial/tvguid12.bmk | 9 + tvision/examples/tutorial/tvguid12.cc | 314 + tvision/examples/tutorial/tvguid12.gpr | Bin 0 -> 11002 bytes tvision/examples/tutorial/tvguid12.mkf | 11 + tvision/examples/tutorial/tvguid12.umk | 17 + tvision/examples/tutorial/tvguid13.bmk | 9 + tvision/examples/tutorial/tvguid13.cc | 324 + tvision/examples/tutorial/tvguid13.gpr | Bin 0 -> 11002 bytes tvision/examples/tutorial/tvguid13.mkf | 11 + tvision/examples/tutorial/tvguid13.umk | 17 + tvision/examples/tutorial/tvguid14.bmk | 9 + tvision/examples/tutorial/tvguid14.cc | 342 + tvision/examples/tutorial/tvguid14.gpr | Bin 0 -> 11002 bytes tvision/examples/tutorial/tvguid14.mkf | 11 + tvision/examples/tutorial/tvguid14.umk | 17 + tvision/examples/tutorial/tvguid15.bmk | 9 + tvision/examples/tutorial/tvguid15.cc | 349 + tvision/examples/tutorial/tvguid15.gpr | Bin 0 -> 11002 bytes tvision/examples/tutorial/tvguid15.mkf | 11 + tvision/examples/tutorial/tvguid15.umk | 17 + tvision/examples/tutorial/tvguid16.bmk | 9 + tvision/examples/tutorial/tvguid16.cc | 401 ++ tvision/examples/tutorial/tvguid16.gpr | Bin 0 -> 11002 bytes tvision/examples/tutorial/tvguid16.mkf | 11 + tvision/examples/tutorial/tvguid16.umk | 17 + tvision/examples/tvedit/rhide.env | 5 + tvision/examples/tvedit/tvedit.bmk | 10 + tvision/examples/tvedit/tvedit.cc | 28 + tvision/examples/tvedit/tvedit.gpr | Bin 0 -> 11010 bytes tvision/examples/tvedit/tvedit.mkf | 11 + tvision/examples/tvedit/tvedit.umk | 17 + tvision/examples/tvhc/demohelp.txt | 505 ++ tvision/examples/tvhc/rhide.env | 5 + tvision/examples/tvhc/tvhc.bmk | 10 + tvision/examples/tvhc/tvhc.cc | 992 +++ tvision/examples/tvhc/tvhc.gpr | Bin 0 -> 11711 bytes tvision/examples/tvhc/tvhc.h | 95 + tvision/examples/tvhc/tvhc.mkf | 11 + tvision/examples/tvhc/tvhc.umk | 17 + tvision/examples/videomode/rhide.env | 5 + tvision/examples/videomode/test.bmk | 10 + tvision/examples/videomode/test.cc | 286 + tvision/examples/videomode/test.gpr | Bin 0 -> 10994 bytes tvision/examples/videomode/test.mkf | 11 + tvision/examples/videomode/test.umk | 17 + tvision/examples/viewers/test.bmk | 10 + tvision/examples/viewers/test.mkf | 11 + tvision/examples/viewers/test.umk | 17 + tvision/examples/xterm/Xterm.res | 299 + tvision/extra/doskeys/kextend.asm | 202 + tvision/extra/doskeys/kextend.com | Bin 0 -> 397 bytes tvision/extra/doskeys/kextend.txt | 118 + tvision/extra/eterm/Setedit/MAIN | 178 + tvision/extra/eterm/Setedit/Setedit.menu | 28 + tvision/extra/eterm/readme.txt | 87 + tvision/extra/eterm/xterm-eterm-tv | 35 + tvision/extra/pifexamp/setedit.pif | Bin 0 -> 995 bytes tvision/fileview.cc | 282 + tvision/fromdos.pl | 52 + tvision/fromunix.pl | 28 + tvision/histlist.cc | 208 + tvision/include/cl/dir.h | 53 + tvision/include/cl/dirent.h | 43 + tvision/include/cl/fnmatch.h | 22 + tvision/include/cl/getopt.h | 112 + tvision/include/cl/glob.h | 36 + tvision/include/cl/needs.h | 153 + tvision/include/cl/regex.h | 499 ++ tvision/include/cl/strstream.h | 6 + tvision/include/cl/unistd.h | 26 + tvision/include/cl/utime.h | 20 + tvision/include/cl/utsname.h | 1 + tvision/include/compatlayer.h | 2605 +++++++ tvision/include/tv.h | 822 +++ tvision/include/tv/alcon/alcon.h | 309 + tvision/include/tv/alcon/key.h | 59 + tvision/include/tv/alcon/mouse.h | 58 + tvision/include/tv/alcon/screen.h | 173 + tvision/include/tv/app.h | 40 + tvision/include/tv/applictn.h | 31 + tvision/include/tv/backgrnd.h | 65 + tvision/include/tv/button.h | 127 + tvision/include/tv/calc.h | 143 + tvision/include/tv/chdirdlg.h | 82 + tvision/include/tv/checkbox.h | 107 + tvision/include/tv/clrdisp.h | 65 + tvision/include/tv/clrdlg.h | 83 + tvision/include/tv/clrgroup.h | 41 + tvision/include/tv/clrgrpli.h | 74 + tvision/include/tv/clritem.h | 40 + tvision/include/tv/clriteml.h | 70 + tvision/include/tv/clrselct.h | 75 + tvision/include/tv/cluster.h | 103 + tvision/include/tv/cmdset.h | 85 + tvision/include/tv/codepage.h | 203 + tvision/include/tv/collectn.h | 60 + tvision/include/tv/colorsel.h | 83 + tvision/include/tv/configfile.h | 99 + tvision/include/tv/desktop.h | 94 + tvision/include/tv/dialog.h | 98 + tvision/include/tv/dialogs.h | 109 + tvision/include/tv/dircoll.h | 88 + tvision/include/tv/direntr.h | 51 + tvision/include/tv/dirlibo.h | 100 + tvision/include/tv/dos/key.h | 53 + tvision/include/tv/dos/mouse.h | 94 + tvision/include/tv/dos/screen.h | 185 + tvision/include/tv/drawbuf.h | 53 + tvision/include/tv/drivers.h | 14 + tvision/include/tv/editors.h | 532 ++ tvision/include/tv/event.h | 226 + tvision/include/tv/eventqu.h | 71 + tvision/include/tv/filecoll.h | 104 + tvision/include/tv/filedlg.h | 98 + tvision/include/tv/filelist.h | 91 + tvision/include/tv/fileview.h | 119 + tvision/include/tv/filinfpn.h | 66 + tvision/include/tv/filinpln.h | 58 + tvision/include/tv/findrepl.h | 47 + tvision/include/tv/fontcoll.h | 112 + tvision/include/tv/fpbase.h | 79 + tvision/include/tv/fpstream.h | 44 + tvision/include/tv/frame.h | 97 + tvision/include/tv/gkey.h | 208 + tvision/include/tv/group.h | 126 + tvision/include/tv/help.h | 57 + tvision/include/tv/helpbase.h | 189 + tvision/include/tv/history.h | 75 + tvision/include/tv/histvwer.h | 54 + tvision/include/tv/histwind.h | 65 + tvision/include/tv/ifpstrm.h | 47 + tvision/include/tv/indicato.h | 75 + tvision/include/tv/inputln.h | 145 + tvision/include/tv/intl.h | 131 + tvision/include/tv/iopstrm.h | 36 + tvision/include/tv/ipstream.h | 90 + tvision/include/tv/label.h | 99 + tvision/include/tv/linux/key.h | 116 + tvision/include/tv/linux/log.h | 25 + tvision/include/tv/linux/mouse.h | 28 + tvision/include/tv/linux/screen.h | 236 + tvision/include/tv/listbox.h | 94 + tvision/include/tv/lstviewr.h | 102 + tvision/include/tv/menu.h | 36 + tvision/include/tv/menubar.h | 76 + tvision/include/tv/menubox.h | 82 + tvision/include/tv/menuitem.h | 77 + tvision/include/tv/menus.h | 97 + tvision/include/tv/menuview.h | 137 + tvision/include/tv/mnoselct.h | 66 + tvision/include/tv/msgbox.h | 83 + tvision/include/tv/no_mss.h | 9 + tvision/include/tv/nointl.h | 54 + tvision/include/tv/nscoll.h | 88 + tvision/include/tv/nssorcol.h | 47 + tvision/include/tv/object.h | 57 + tvision/include/tv/objects.h | 38 + tvision/include/tv/ofpstrm.h | 45 + tvision/include/tv/opstream.h | 88 + tvision/include/tv/osclipboard.h | 44 + tvision/include/tv/otstream.h | 26 + tvision/include/tv/palette.h | 38 + tvision/include/tv/parmtext.h | 64 + tvision/include/tv/parttree.h | 5 + tvision/include/tv/point.h | 58 + tvision/include/tv/preadobj.h | 51 + tvision/include/tv/program.h | 154 + tvision/include/tv/pstream.h | 72 + tvision/include/tv/pwritobj.h | 77 + tvision/include/tv/qnx4/key.h | 29 + tvision/include/tv/qnx4/mouse.h | 33 + tvision/include/tv/qnx4/screen.h | 94 + tvision/include/tv/qnxrtp/key.h | 52 + tvision/include/tv/qnxrtp/mouse.h | 38 + tvision/include/tv/qnxrtp/screen.h | 88 + tvision/include/tv/radiobtn.h | 121 + tvision/include/tv/rect.h | 122 + tvision/include/tv/rescoll.h | 56 + tvision/include/tv/resfile.h | 45 + tvision/include/tv/resitem.h | 26 + tvision/include/tv/resource.h | 56 + tvision/include/tv/screen.h | 477 ++ tvision/include/tv/scrlbar.h | 99 + tvision/include/tv/scroller.h | 95 + tvision/include/tv/searchrc.h | 27 + tvision/include/tv/sitem.h | 46 + tvision/include/tv/skeleton/key.h | 46 + tvision/include/tv/skeleton/mouse.h | 44 + tvision/include/tv/skeleton/screen.h | 152 + tvision/include/tv/sortcoll.h | 59 + tvision/include/tv/sortlibo.h | 80 + tvision/include/tv/ssc_streams.h | 101 + tvision/include/tv/statsdef.h | 44 + tvision/include/tv/statsitm.h | 53 + tvision/include/tv/statslin.h | 103 + tvision/include/tv/stddlg.h | 105 + tvision/include/tv/streambl.h | 47 + tvision/include/tv/strilist.h | 69 + tvision/include/tv/strinrec.h | 31 + tvision/include/tv/strlistm.h | 70 + tvision/include/tv/strmblcl.h | 54 + tvision/include/tv/strmblty.h | 54 + tvision/include/tv/strncoll.h | 60 + tvision/include/tv/sttctext.h | 94 + tvision/include/tv/submenu.h | 27 + tvision/include/tv/system.h | 76 + tvision/include/tv/terminal.h | 51 + tvision/include/tv/textdev.h | 40 + tvision/include/tv/textview.h | 32 + tvision/include/tv/tkeyext.h | 237 + tvision/include/tv/tkeys.h | 96 + tvision/include/tv/tobjstrm.h | 165 + tvision/include/tv/ttypes.h | 24 + tvision/include/tv/tvconfig.h | 39 + tvision/include/tv/tvedit.h | 57 + tvision/include/tv/tvobjs.h | 32 + tvision/include/tv/tvutil.h | 98 + tvision/include/tv/unix/key.h | 38 + tvision/include/tv/unix/mouse.h | 37 + tvision/include/tv/unix/screen.h | 135 + tvision/include/tv/unix/xtkey.h | 90 + tvision/include/tv/unix/xtmouse.h | 32 + tvision/include/tv/unix/xtscreen.h | 136 + tvision/include/tv/validate.h | 333 + tvision/include/tv/video.h | 135 + tvision/include/tv/view.h | 212 + tvision/include/tv/views.h | 269 + tvision/include/tv/win32/key.h | 64 + tvision/include/tv/win32/mouse.h | 40 + tvision/include/tv/win32/screen.h | 98 + tvision/include/tv/win32/win32clip.h | 40 + tvision/include/tv/window.h | 113 + tvision/include/tv/wingr/key.h | 69 + tvision/include/tv/wingr/mouse.h | 51 + tvision/include/tv/wingr/screen.h | 275 + tvision/include/tv/winnt/key.h | 39 + tvision/include/tv/winnt/mouse.h | 27 + tvision/include/tv/winnt/screen.h | 120 + tvision/include/tv/x11/key.h | 63 + tvision/include/tv/x11/mouse.h | 27 + tvision/include/tv/x11/screen.h | 308 + tvision/include/tv/yes_mss.h | 8 + tvision/intl/Makefile | 41 + tvision/intl/dummy/Makefile | 5 + tvision/intl/dummy/intldummy.c | 35 + tvision/intl/es.po | 677 ++ tvision/intl/gnumake.in | 41 + tvision/intl/pl.po | 642 ++ tvision/intl/ru.po | 657 ++ tvision/intl/tvision.po | 632 ++ tvision/intl/utod.pl | 15 + tvision/linux/compress | 151 + tvision/linux/inclubin.txt | 7 + tvision/linux/includbi.txt | 7 + tvision/linux/sacadeb | 10 + tvision/lista | 874 +++ tvision/lista.dos | 40 + tvision/makes/blink.c | 72 + tvision/makes/common.bmk | 65 + tvision/makes/common.imk | 71 + tvision/makes/common.nmk | 69 + tvision/makes/common.wat | 54 + tvision/makes/config.bcc | 36 + tvision/makes/config.nmk | 33 + tvision/makes/config.wat | 53 + tvision/makes/extrimk.cc | 879 +++ tvision/makes/genimk.cc | 193 + tvision/makes/includer.bmk | 35 + tvision/makes/includer.imk | 35 + tvision/makes/librhtv.bmk | 63 + tvision/makes/librhtv.gpr | Bin 0 -> 436379 bytes tvision/makes/librhtv.imk | 7405 ++++++++++++++++++++ tvision/makes/librhtv.mkf | 50 + tvision/makes/librhtv.umk | 1463 ++++ tvision/makes/maintain.mak | 183 + tvision/makes/mlink.c | 76 + tvision/makes/obj/delete.me | 2 + tvision/misc.cc | 56 + tvision/miscperl.pl | 40 + tvision/msgbox.cc | 244 + tvision/names/nbackgro.cc | 5 + tvision/names/nbutton.cc | 5 + tvision/names/ncalcdis.cc | 5 + tvision/names/ncalcula.cc | 5 + tvision/names/nchdirdi.cc | 5 + tvision/names/ncheckbo.cc | 6 + tvision/names/nclrdisp.cc | 5 + tvision/names/ncluster.cc | 5 + tvision/names/ncollect.cc | 5 + tvision/names/ncolordi.cc | 5 + tvision/names/ncolorgr.cc | 5 + tvision/names/ncolorit.cc | 5 + tvision/names/ncolorse.cc | 5 + tvision/names/ndesktop.cc | 5 + tvision/names/ndialog.cc | 5 + tvision/names/ndircoll.cc | 5 + tvision/names/ndirlist.cc | 5 + tvision/names/neditor.cc | 4 + tvision/names/neditwi.cc | 4 + tvision/names/nfilecol.cc | 5 + tvision/names/nfiledia.cc | 5 + tvision/names/nfiledtr.cc | 4 + tvision/names/nfileinf.cc | 5 + tvision/names/nfileinp.cc | 5 + tvision/names/nfilelis.cc | 5 + tvision/names/nfilterv.cc | 5 + tvision/names/nframe.cc | 5 + tvision/names/ngroup.cc | 5 + tvision/names/nhistory.cc | 5 + tvision/names/nindicat.cc | 5 + tvision/names/ninputli.cc | 5 + tvision/names/nlabel.cc | 3 + tvision/names/nlistbox.cc | 3 + tvision/names/nlistvie.cc | 3 + tvision/names/nlookupv.cc | 4 + tvision/names/nmemo.cc | 4 + tvision/names/nmenubar.cc | 3 + tvision/names/nmenubox.cc | 3 + tvision/names/nmenuvie.cc | 3 + tvision/names/nmonosel.cc | 3 + tvision/names/nparamte.cc | 3 + tvision/names/npxvalid.cc | 3 + tvision/names/nradiobu.cc | 4 + tvision/names/nrangeva.cc | 3 + tvision/names/nresourc.cc | 3 + tvision/names/nscrollb.cc | 3 + tvision/names/nscrolle.cc | 3 + tvision/names/nsortedc.cc | 3 + tvision/names/nsortedl.cc | 3 + tvision/names/nstatict.cc | 3 + tvision/names/nstatusl.cc | 3 + tvision/names/nstringc.cc | 3 + tvision/names/nstringl.cc | 3 + tvision/names/nvalidat.cc | 3 + tvision/names/nview.cc | 3 + tvision/names/nwindow.cc | 3 + tvision/newstr.cc | 24 + tvision/qnxrtp/tvision.qpg | 152 + tvision/qnxrtp/tvision.qpg.in | 152 + tvision/readme.in | 456 ++ tvision/readme.txt | 456 ++ tvision/redhat/.cvsignore | 2 + tvision/redhat/README | 79 + tvision/redhat/config-rpm.sh | 7 + tvision/redhat/create-dirs.sh | 13 + tvision/redhat/create-rpms.sh | 27 + tvision/redhat/librhtv.spec.in | 133 + tvision/rhide.env | 33 + tvision/rhtv-config.c | 192 + tvision/searchstrs.sh | 2 + tvision/snapshot.pl | 177 + tvision/stream/sbackgro.cc | 14 + tvision/stream/sbutton.cc | 14 + tvision/stream/scalcdis.cc | 14 + tvision/stream/scalcula.cc | 16 + tvision/stream/schdirdi.cc | 16 + tvision/stream/scheckbo.cc | 18 + tvision/stream/sclrdisp.cc | 14 + tvision/stream/scluster.cc | 15 + tvision/stream/scolordi.cc | 22 + tvision/stream/scolorgr.cc | 14 + tvision/stream/scolorit.cc | 14 + tvision/stream/scolorse.cc | 14 + tvision/stream/sdesktop.cc | 13 + tvision/stream/sdialog.cc | 15 + tvision/stream/sdircoll.cc | 13 + tvision/stream/sdirlist.cc | 13 + tvision/stream/seditor.cc | 16 + tvision/stream/seditwin.cc | 15 + tvision/stream/sfilecol.cc | 13 + tvision/stream/sfiledia.cc | 16 + tvision/stream/sfileedi.cc | 14 + tvision/stream/sfileinf.cc | 13 + tvision/stream/sfileinp.cc | 14 + tvision/stream/sfilelis.cc | 13 + tvision/stream/sfilterv.cc | 13 + tvision/stream/sframe.cc | 12 + tvision/stream/sgroup.cc | 14 + tvision/stream/shistory.cc | 15 + tvision/stream/sindicat.cc | 14 + tvision/stream/sinputli.cc | 14 + tvision/stream/slabel.cc | 14 + tvision/stream/slistbox.cc | 14 + tvision/stream/slistvie.cc | 15 + tvision/stream/slookupv.cc | 18 + tvision/stream/smemo.cc | 14 + tvision/stream/smenubar.cc | 13 + tvision/stream/smenubox.cc | 13 + tvision/stream/smenuvie.cc | 14 + tvision/stream/smonosel.cc | 14 + tvision/stream/sparamte.cc | 15 + tvision/stream/spxvalid.cc | 13 + tvision/stream/sradiobu.cc | 18 + tvision/stream/srangeva.cc | 14 + tvision/stream/sresourc.cc | 12 + tvision/stream/sscrollb.cc | 14 + tvision/stream/sscrolle.cc | 14 + tvision/stream/sstatict.cc | 14 + tvision/stream/sstatusl.cc | 14 + tvision/stream/sstringc.cc | 13 + tvision/stream/sstringl.cc | 13 + tvision/stream/sview.cc | 13 + tvision/stream/swindow.cc | 15 + tvision/update | 16 + tvision/update.bat | 15 + tvision/version.txt | 1 + tvision/win32/readme.txt | 71 + tvision/winnt/Makefile | 169 + tvision/winnt/Makefile.nmk | 151 + tvision/winnt/bccmake.in | 119 + tvision/winnt/include/msvc/dir.h | 53 + tvision/winnt/include/msvc/dirent.h | 42 + tvision/winnt/include/msvc/strstream.h | 6 + tvision/winnt/include/tv/configtv.h | 23 + tvision/winnt/msvcmake.in | 101 + tvision/winnt/obj_ms/delete.me | 2 + tvision/winnt/objs/delete.me | 2 + tvision/winnt/readme.txt | 50 + tvision/winnt/tvex.cc | 52 + tvision/www-site/bvucs-n1.jpg | Bin 0 -> 2297 bytes tvision/www-site/contrib.html | 105 + tvision/www-site/envelp.gif | Bin 0 -> 1664 bytes tvision/www-site/history.html | 198 + tvision/www-site/index.html | 320 + tvision/www-site/sf.css | 18 + tvision/www-site/update | 2 + 1016 files changed, 151051 insertions(+) create mode 100644 GNUmakefile create mode 100644 makefiles/README create mode 100644 makefiles/gmake/clean.mk create mode 100644 makefiles/gmake/compiler.mk create mode 100644 makefiles/gmake/depend.mk create mode 100644 makefiles/gmake/dist.mk create mode 100755 makefiles/gmake/guess_env create mode 100644 makefiles/gmake/help.mk create mode 100644 makefiles/gmake/i18n.mk create mode 100644 makefiles/gmake/install.mk create mode 100644 makefiles/gmake/libs.mk create mode 100644 makefiles/gmake/platform.mk create mode 100644 makefiles/gmake/platform.mk.vars create mode 100644 makefiles/gmake/sub.mk create mode 100644 makefiles/gmake/top.mk create mode 100644 makefiles/nmake/clean.mk create mode 100644 makefiles/nmake/compiler.mk create mode 100644 makefiles/nmake/config.mk create mode 100644 makefiles/nmake/depend.mk create mode 100644 makefiles/nmake/help.mk create mode 100644 makefiles/nmake/platform.mk create mode 100644 makefiles/nmake/sub.mk create mode 100644 makefiles/nmake/top.mk create mode 100644 src/GNUmakefile create mode 100644 tvision/INSTALL.txt create mode 100644 tvision/Makefile.bcc create mode 100644 tvision/Makefile.in create mode 100644 tvision/Makefile.nmk create mode 100644 tvision/Makefile.wat create mode 100644 tvision/THANKS create mode 100644 tvision/TODO create mode 100644 tvision/borland.txt create mode 100644 tvision/change.log create mode 100644 tvision/change1.log create mode 100644 tvision/classes/alcon/alcon.cc create mode 100644 tvision/classes/alcon/alcondis.cc create mode 100644 tvision/classes/alcon/alconkey.cc create mode 100644 tvision/classes/alcon/alconmouse.cc create mode 100644 tvision/classes/alcon/alconscr.cc create mode 100644 tvision/classes/calcdisp.cc create mode 100644 tvision/classes/calculat.cc create mode 100644 tvision/classes/codepage.cc create mode 100644 tvision/classes/configfile.cc create mode 100644 tvision/classes/dos/dosdis.cc create mode 100644 tvision/classes/dos/doskey.cc create mode 100644 tvision/classes/dos/dosmouse.cc create mode 100644 tvision/classes/dos/dosscr.cc create mode 100644 tvision/classes/dos/rhscreen.cc create mode 100644 tvision/classes/dos/screen.cc create mode 100644 tvision/classes/dos/sescreen.cc create mode 100644 tvision/classes/dos/vesa.cc create mode 100644 tvision/classes/dos/vga.cc create mode 100644 tvision/classes/dos/vgaregs.c create mode 100644 tvision/classes/dos/vgaregs.h create mode 100644 tvision/classes/dos/vgastate.c create mode 100644 tvision/classes/dos/vgastate.h create mode 100644 tvision/classes/fontcoll.cc create mode 100644 tvision/classes/fpbase.cc create mode 100644 tvision/classes/fpstream.cc create mode 100644 tvision/classes/help.cc create mode 100644 tvision/classes/helpbase.cc create mode 100644 tvision/classes/ifpstrea.cc create mode 100644 tvision/classes/iopstrea.cc create mode 100644 tvision/classes/ipstream.cc create mode 100644 tvision/classes/linux/linuxdis.cc create mode 100644 tvision/classes/linux/linuxkey.cc create mode 100644 tvision/classes/linux/linuxmouse.cc create mode 100644 tvision/classes/linux/linuxscr.cc create mode 100644 tvision/classes/ofpstrea.cc create mode 100644 tvision/classes/opstream.cc create mode 100644 tvision/classes/osclipboard.cc create mode 100644 tvision/classes/pstream.cc create mode 100644 tvision/classes/qnx4/qnx4dis.cc create mode 100644 tvision/classes/qnx4/qnx4key.cc create mode 100644 tvision/classes/qnx4/qnx4mouse.cc create mode 100644 tvision/classes/qnx4/qnx4scr.cc create mode 100644 tvision/classes/qnxrtp/qnxdis.cc create mode 100644 tvision/classes/qnxrtp/qnxkey.cc create mode 100644 tvision/classes/qnxrtp/qnxmouse.cc create mode 100644 tvision/classes/qnxrtp/qnxscr.cc create mode 100644 tvision/classes/tapplica.cc create mode 100644 tvision/classes/tbackgro.cc create mode 100644 tvision/classes/tbutton.cc create mode 100644 tvision/classes/tchdirdi.cc create mode 100644 tvision/classes/tcheckbo.cc create mode 100644 tvision/classes/tclrdisp.cc create mode 100644 tvision/classes/tcluster.cc create mode 100644 tvision/classes/tcollect.cc create mode 100644 tvision/classes/tcolordi.cc create mode 100644 tvision/classes/tcolorgr.cc create mode 100644 tvision/classes/tcolorit.cc create mode 100644 tvision/classes/tcolorse.cc create mode 100644 tvision/classes/tcommand.cc create mode 100644 tvision/classes/tdesktop.cc create mode 100644 tvision/classes/tdialog.cc create mode 100644 tvision/classes/tdircoll.cc create mode 100644 tvision/classes/tdirlist.cc create mode 100644 tvision/classes/tdisplay.cc create mode 100644 tvision/classes/tdrawbuf.cc create mode 100644 tvision/classes/teditor.cc create mode 100644 tvision/classes/teditorf.cc create mode 100644 tvision/classes/teditwin.cc create mode 100644 tvision/classes/tevent.cc create mode 100644 tvision/classes/tfilecol.cc create mode 100644 tvision/classes/tfiledia.cc create mode 100644 tvision/classes/tfileedi.cc create mode 100644 tvision/classes/tfileinf.cc create mode 100644 tvision/classes/tfileinp.cc create mode 100644 tvision/classes/tfilelis.cc create mode 100644 tvision/classes/tfilterv.cc create mode 100644 tvision/classes/tframe.cc create mode 100644 tvision/classes/tgkey.cc create mode 100644 tvision/classes/tgroup.cc create mode 100644 tvision/classes/thistory.cc create mode 100644 tvision/classes/thistvie.cc create mode 100644 tvision/classes/thistwin.cc create mode 100644 tvision/classes/thwmouse.cc create mode 100644 tvision/classes/tindicat.cc create mode 100644 tvision/classes/tinputli.cc create mode 100644 tvision/classes/tlabel.cc create mode 100644 tvision/classes/tlistbox.cc create mode 100644 tvision/classes/tlistvie.cc create mode 100644 tvision/classes/tlookupv.cc create mode 100644 tvision/classes/tmemo.cc create mode 100644 tvision/classes/tmenubar.cc create mode 100644 tvision/classes/tmenubox.cc create mode 100644 tvision/classes/tmenuvie.cc create mode 100644 tvision/classes/tmonosel.cc create mode 100644 tvision/classes/tmouse.cc create mode 100644 tvision/classes/tnscolle.cc create mode 100644 tvision/classes/tnssorte.cc create mode 100644 tvision/classes/tobject.cc create mode 100644 tvision/classes/tpalette.cc create mode 100644 tvision/classes/tparamte.cc create mode 100644 tvision/classes/tpoint.cc create mode 100644 tvision/classes/tprogini.cc create mode 100644 tvision/classes/tprogram.cc create mode 100644 tvision/classes/tpwobj.cc create mode 100644 tvision/classes/tpwreado.cc create mode 100644 tvision/classes/tpwritte.cc create mode 100644 tvision/classes/tpxvalid.cc create mode 100644 tvision/classes/tradiobu.cc create mode 100644 tvision/classes/trangeva.cc create mode 100644 tvision/classes/trescoll.cc create mode 100644 tvision/classes/tresfile.cc create mode 100644 tvision/classes/tscreen.cc create mode 100644 tvision/classes/tscrollb.cc create mode 100644 tvision/classes/tscrolle.cc create mode 100644 tvision/classes/tsortedc.cc create mode 100644 tvision/classes/tsortedl.cc create mode 100644 tvision/classes/tstatict.cc create mode 100644 tvision/classes/tstatusd.cc create mode 100644 tvision/classes/tstatusl.cc create mode 100644 tvision/classes/tstrinde.cc create mode 100644 tvision/classes/tstringc.cc create mode 100644 tvision/classes/tstringl.cc create mode 100644 tvision/classes/tstrlist.cc create mode 100644 tvision/classes/tstrmcla.cc create mode 100644 tvision/classes/tstrmtyp.cc create mode 100644 tvision/classes/tsubmenu.cc create mode 100644 tvision/classes/ttermina.cc create mode 100644 tvision/classes/ttextdev.cc create mode 100644 tvision/classes/tvalidat.cc create mode 100644 tvision/classes/tvedit1.cc create mode 100644 tvision/classes/tvedit2.cc create mode 100644 tvision/classes/tvedit3.cc create mode 100644 tvision/classes/tview.cc create mode 100644 tvision/classes/tvintl.cc create mode 100644 tvision/classes/tvtext1.cc create mode 100644 tvision/classes/tvtext2.cc create mode 100644 tvision/classes/twindow.cc create mode 100644 tvision/classes/unix/unixdis.cc create mode 100644 tvision/classes/unix/unixkey.cc create mode 100644 tvision/classes/unix/unixmouse.cc create mode 100644 tvision/classes/unix/unixscr.cc create mode 100644 tvision/classes/unix/xtermdis.cc create mode 100644 tvision/classes/unix/xtermkey.cc create mode 100644 tvision/classes/unix/xtermmouse.cc create mode 100644 tvision/classes/unix/xtermscr.cc create mode 100644 tvision/classes/win32/win32clip.cc create mode 100644 tvision/classes/win32/win32dis.cc create mode 100644 tvision/classes/win32/win32key.cc create mode 100644 tvision/classes/win32/win32mouse.cc create mode 100644 tvision/classes/win32/win32scr.cc create mode 100644 tvision/classes/wingr/wingrdis.cc create mode 100644 tvision/classes/wingr/wingrkey.cc create mode 100644 tvision/classes/wingr/wingrmouse.cc create mode 100644 tvision/classes/wingr/wingrscr.cc create mode 100644 tvision/classes/winnt/winntdis.cc create mode 100644 tvision/classes/winnt/winntkey.cc create mode 100644 tvision/classes/winnt/winntmouse.cc create mode 100644 tvision/classes/winnt/winntscr.cc create mode 100644 tvision/classes/x11/x11dis.cc create mode 100644 tvision/classes/x11/x11key.cc create mode 100644 tvision/classes/x11/x11mouse.cc create mode 100644 tvision/classes/x11/x11src.cc create mode 100644 tvision/compat/beep.c create mode 100644 tvision/compat/compat.gpr create mode 100644 tvision/compat/compat.imk create mode 100644 tvision/compat/compat.umk create mode 100644 tvision/compat/drivevalid.c create mode 100644 tvision/compat/expandpath.c create mode 100644 tvision/compat/fexpand.c create mode 100644 tvision/compat/fileattrs.c create mode 100644 tvision/compat/fileexists.c create mode 100644 tvision/compat/filelength.c create mode 100644 tvision/compat/fixpath.c create mode 100644 tvision/compat/fnmatch.c create mode 100644 tvision/compat/getcurdir.c create mode 100644 tvision/compat/getline.c create mode 100644 tvision/compat/getopt.c create mode 100644 tvision/compat/getopt1.c create mode 100644 tvision/compat/getshell.c create mode 100644 tvision/compat/glob.c create mode 100644 tvision/compat/globfree.c create mode 100644 tvision/compat/iffilelen.cc create mode 100644 tvision/compat/isdir.c create mode 100644 tvision/compat/isrelpath.c create mode 100644 tvision/compat/iswild.c create mode 100644 tvision/compat/itoa.c create mode 100644 tvision/compat/mkstemp.c create mode 100644 tvision/compat/nl_langinfo.c create mode 100644 tvision/compat/ntdirent.c create mode 100644 tvision/compat/obj/delete.me create mode 100644 tvision/compat/pathvalid.c create mode 100644 tvision/compat/regex.c create mode 100644 tvision/compat/releasec.c create mode 100644 tvision/compat/snprintf.c create mode 100644 tvision/compat/ssc_streams.cc create mode 100644 tvision/compat/strlwr.c create mode 100644 tvision/compat/strupr.c create mode 100644 tvision/compat/ticks.c create mode 100644 tvision/compat/unc.c create mode 100644 tvision/compat/unc_95.c create mode 100644 tvision/compat/unc_nt.c create mode 100644 tvision/compat/validfilename.c create mode 100644 tvision/compat/yieldpro.c create mode 100644 tvision/config.pl create mode 100644 tvision/confignt.pl create mode 100755 tvision/configset create mode 100644 tvision/configset.bat create mode 100755 tvision/configure create mode 100644 tvision/configure.bat create mode 100644 tvision/conflib.pl create mode 100644 tvision/copying create mode 100644 tvision/copying.rh create mode 100644 tvision/debian/.cvsignore create mode 100644 tvision/debian/README create mode 100644 tvision/debian/README.debian create mode 100644 tvision/debian/buildpackage create mode 100644 tvision/debian/changelog create mode 100644 tvision/debian/control create mode 100644 tvision/debian/control.in create mode 100644 tvision/debian/copyright create mode 100644 tvision/debian/diversions.ex create mode 100644 tvision/debian/files_to_backup create mode 100644 tvision/debian/info.ex create mode 100644 tvision/debian/maintainer.notes create mode 100644 tvision/debian/rhtvision.postinst create mode 100644 tvision/debian/rhtvision.postrm create mode 100644 tvision/debian/rules create mode 100644 tvision/debian/shlibs.local.ex create mode 100644 tvision/debian/watch.ex create mode 100644 tvision/djgpp/compress.bat create mode 100644 tvision/djgpp/compress.pl create mode 100644 tvision/djgpp/distlist create mode 100644 tvision/djgpp/sacadeb.bat create mode 100644 tvision/djgpp/tmp/delete.me create mode 100644 tvision/doc/Alcon.txt create mode 100644 tvision/doc/CodePages.txt create mode 100644 tvision/doc/ConfigFile.txt create mode 100644 tvision/doc/DOS.txt create mode 100644 tvision/doc/Eterm.txt create mode 100644 tvision/doc/I18n.txt create mode 100644 tvision/doc/Linux.txt create mode 100644 tvision/doc/QNX.txt create mode 100644 tvision/doc/Streams.txt create mode 100644 tvision/doc/TVReference.html create mode 100644 tvision/doc/Win32.txt create mode 100644 tvision/doc/WinGr.txt create mode 100644 tvision/doc/X11.txt create mode 100644 tvision/doc/XTerm.txt create mode 100644 tvision/doc/html.frt create mode 100644 tvision/doc/install/bcc.txt create mode 100644 tvision/doc/install/cygwin.txt create mode 100644 tvision/doc/install/djgpp.txt create mode 100644 tvision/doc/install/linux.txt create mode 100644 tvision/doc/install/mingwin.txt create mode 100644 tvision/doc/install/msvc.txt create mode 100644 tvision/doc/install/tools.txt create mode 100644 tvision/doc/install/unix.txt create mode 100644 tvision/doc/install/watcom.txt create mode 100644 tvision/doc/libdocs.epr create mode 100755 tvision/doc/troubleshooting/Linux/1/code.cc create mode 100755 tvision/doc/troubleshooting/Linux/1/readme.txt create mode 100755 tvision/doc/troubleshooting/Linux/1/test-utf8.txt create mode 100755 tvision/doc/troubleshooting/Linux/1/test.txt create mode 100755 tvision/doc/troubleshooting/Linux/1/utf8.cc create mode 100755 tvision/doc/troubleshooting/Linux/2/readme.txt create mode 100755 tvision/doc/troubleshooting/Linux/3/readme.txt create mode 100755 tvision/doc/troubleshooting/Linux/4/readme.txt create mode 100755 tvision/doc/troubleshooting/Linux/4/test.cc create mode 100755 tvision/doc/troubleshooting/Linux/readme.txt create mode 100755 tvision/doc/troubleshooting/readme.txt create mode 100644 tvision/drivers2.cc create mode 100644 tvision/dual.cc create mode 100644 tvision/examples/Makefile create mode 100644 tvision/examples/bhelp/.tvrc create mode 100644 tvision/examples/bhelp/bhelp.cc create mode 100644 tvision/examples/bhelp/bhelp.h create mode 100644 tvision/examples/bhelp/rhide.env create mode 100644 tvision/examples/bhelp/thelp.bmk create mode 100644 tvision/examples/bhelp/thelp.cc create mode 100644 tvision/examples/bhelp/thelp.gpr create mode 100644 tvision/examples/bhelp/thelp.mkf create mode 100644 tvision/examples/bhelp/thelp.umk create mode 100644 tvision/examples/clipboard/rhide.env create mode 100644 tvision/examples/clipboard/test.bmk create mode 100644 tvision/examples/clipboard/test.cc create mode 100644 tvision/examples/clipboard/test.gpr create mode 100644 tvision/examples/clipboard/test.mkf create mode 100644 tvision/examples/clipboard/test.umk create mode 100644 tvision/examples/common.bmk create mode 100644 tvision/examples/cyrillic/linuxkoi8/README create mode 100644 tvision/examples/cyrillic/linuxkoi8/koi8-r.acm.gz create mode 100644 tvision/examples/cyrillic/linuxkoi8/koi8-r.psf.gz create mode 100644 tvision/examples/cyrillic/linuxkoi8/lat1-16.psf.gz create mode 100644 tvision/examples/cyrillic/linuxkoi8/rhide.env create mode 100644 tvision/examples/cyrillic/linuxkoi8/ru1.kmap.gz create mode 100755 tvision/examples/cyrillic/linuxkoi8/setkoi8.sh create mode 100755 tvision/examples/cyrillic/linuxkoi8/setlat1.sh create mode 100644 tvision/examples/cyrillic/linuxkoi8/test.cc create mode 100644 tvision/examples/cyrillic/linuxkoi8/test.gpr create mode 100644 tvision/examples/cyrillic/linuxkoi8/test.mkf create mode 100644 tvision/examples/cyrillic/linuxkoi8/test.umk create mode 100644 tvision/examples/cyrillic/linuxkoi8/trivial.acm create mode 100644 tvision/examples/cyrillic/x11koi8/rhide.env create mode 100644 tvision/examples/cyrillic/x11koi8/test.cc create mode 100644 tvision/examples/cyrillic/x11koi8/test.gpr create mode 100644 tvision/examples/cyrillic/x11koi8/test.mkf create mode 100644 tvision/examples/cyrillic/x11koi8/test.umk create mode 100644 tvision/examples/demo/ascii.cc create mode 100644 tvision/examples/demo/ascii.h create mode 100644 tvision/examples/demo/calendar.cc create mode 100644 tvision/examples/demo/calendar.h create mode 100644 tvision/examples/demo/demo.bmk create mode 100644 tvision/examples/demo/demo.gpr create mode 100644 tvision/examples/demo/demo.mkf create mode 100644 tvision/examples/demo/demo.umk create mode 100644 tvision/examples/demo/demohelp.h create mode 100644 tvision/examples/demo/demohelp.h32 create mode 100644 tvision/examples/demo/diffs.cc create mode 100644 tvision/examples/demo/fileview.cc create mode 100644 tvision/examples/demo/fileview.h create mode 100644 tvision/examples/demo/gadgets.cc create mode 100644 tvision/examples/demo/gadgets.h create mode 100644 tvision/examples/demo/mousedlg.cc create mode 100644 tvision/examples/demo/mousedlg.h create mode 100644 tvision/examples/demo/puzzle.cc create mode 100644 tvision/examples/demo/puzzle.h create mode 100644 tvision/examples/demo/rhide.env create mode 100644 tvision/examples/demo/tvcmds.h create mode 100644 tvision/examples/demo/tvdemo.h create mode 100644 tvision/examples/demo/tvdemo1.cc create mode 100644 tvision/examples/demo/tvdemo2.cc create mode 100644 tvision/examples/demo/tvdemo3.cc create mode 100644 tvision/examples/desklogo/desklogo.bmk create mode 100644 tvision/examples/desklogo/desklogo.cc create mode 100644 tvision/examples/desklogo/desklogo.gpr create mode 100644 tvision/examples/desklogo/desklogo.mkf create mode 100644 tvision/examples/desklogo/desklogo.umk create mode 100644 tvision/examples/desklogo/rhide.env create mode 100644 tvision/examples/desklogo/set-logo.bmk create mode 100644 tvision/examples/desklogo/set-logo.cc create mode 100644 tvision/examples/desklogo/set-logo.gpr create mode 100644 tvision/examples/desklogo/set-logo.mkf create mode 100644 tvision/examples/desklogo/set-logo.umk create mode 100644 tvision/examples/desklogo/tv_logo.bmk create mode 100644 tvision/examples/desklogo/tv_logo.cc create mode 100644 tvision/examples/desklogo/tv_logo.gpr create mode 100644 tvision/examples/desklogo/tv_logo.mkf create mode 100644 tvision/examples/desklogo/tv_logo.umk create mode 100644 tvision/examples/dlgdsn/codebldr.cc create mode 100644 tvision/examples/dlgdsn/consted.cc create mode 100644 tvision/examples/dlgdsn/consted.h create mode 100644 tvision/examples/dlgdsn/dsgdata.h create mode 100644 tvision/examples/dlgdsn/dsgobjs.cc create mode 100644 tvision/examples/dlgdsn/dsgobjs.h create mode 100644 tvision/examples/dlgdsn/fdconsts.h create mode 100644 tvision/examples/dlgdsn/freedsgn.cc create mode 100644 tvision/examples/dlgdsn/libtest.gpr create mode 100644 tvision/examples/dlgdsn/libtest.mkf create mode 100644 tvision/examples/dlgdsn/libtest.umk create mode 100644 tvision/examples/dlgdsn/propdlgs.cc create mode 100644 tvision/examples/dlgdsn/propdlgs.h create mode 100644 tvision/examples/dlgdsn/propedit.cc create mode 100644 tvision/examples/dlgdsn/propedit.h create mode 100644 tvision/examples/dlgdsn/rhide.env create mode 100644 tvision/examples/dlgdsn/strmoper.cc create mode 100644 tvision/examples/dlgdsn/strmoper.h create mode 100644 tvision/examples/dlgdsn/tappwnd.cc create mode 100644 tvision/examples/dyntxt/dyntext.bmk create mode 100644 tvision/examples/dyntxt/dyntext.cpp create mode 100644 tvision/examples/dyntxt/dyntext.gpr create mode 100644 tvision/examples/dyntxt/dyntext.h create mode 100644 tvision/examples/dyntxt/dyntext.mkf create mode 100644 tvision/examples/dyntxt/dyntext.umk create mode 100644 tvision/examples/dyntxt/readme create mode 100644 tvision/examples/dyntxt/rhide.env create mode 100644 tvision/examples/dyntxt/testdyn.cpp create mode 100644 tvision/examples/eterm/menus.cfg create mode 100644 tvision/examples/eterm/theme.cfg create mode 100644 tvision/examples/fonts/font.016 create mode 100644 tvision/examples/fonts/genraw.cc create mode 100644 tvision/examples/fonts/genraw.gpr create mode 100644 tvision/examples/fonts/genraw.mkf create mode 100644 tvision/examples/fonts/genraw.umk create mode 100644 tvision/examples/fonts/ocr.sft create mode 100644 tvision/examples/fonts/rhide.env create mode 100644 tvision/examples/fonts/test.cc create mode 100644 tvision/examples/fonts/test.gpr create mode 100644 tvision/examples/fonts/test.mkf create mode 100644 tvision/examples/fonts/test.umk create mode 100644 tvision/examples/gen_mkf.pl create mode 100644 tvision/examples/helpdemo/helpdemo.bmk create mode 100644 tvision/examples/helpdemo/helpdemo.cc create mode 100644 tvision/examples/helpdemo/helpdemo.gpr create mode 100644 tvision/examples/helpdemo/helpdemo.mkf create mode 100644 tvision/examples/helpdemo/helpdemo.umk create mode 100644 tvision/examples/helpdemo/rhide.env create mode 100644 tvision/examples/i18n/README create mode 100644 tvision/examples/i18n/es.po create mode 100755 tvision/examples/i18n/extract.sh create mode 100644 tvision/examples/i18n/intl/es/LC_MESSAGES/test.mo create mode 100644 tvision/examples/i18n/intl/es/LC_MESSAGES/tvision.mo create mode 100644 tvision/examples/i18n/rhide.env create mode 100644 tvision/examples/i18n/test.cc create mode 100644 tvision/examples/i18n/test.gpr create mode 100644 tvision/examples/i18n/test.mkf create mode 100644 tvision/examples/i18n/test.po create mode 100644 tvision/examples/i18n/test.umk create mode 100644 tvision/examples/inplis/implis.bmk create mode 100644 tvision/examples/inplis/implis.gpr create mode 100644 tvision/examples/inplis/implis.mkf create mode 100644 tvision/examples/inplis/implis.umk create mode 100644 tvision/examples/inplis/inplist.cpp create mode 100644 tvision/examples/inplis/inplist.h create mode 100644 tvision/examples/inplis/rhide.env create mode 100644 tvision/examples/inplis/test.cpp create mode 100644 tvision/examples/listvi/listbox2.cpp create mode 100644 tvision/examples/listvi/lst_view.bmk create mode 100644 tvision/examples/listvi/lst_view.cpp create mode 100644 tvision/examples/listvi/lst_view.gpr create mode 100644 tvision/examples/listvi/lst_view.h create mode 100644 tvision/examples/listvi/lst_view.mkf create mode 100644 tvision/examples/listvi/lst_view.umk create mode 100644 tvision/examples/listvi/readme.txt create mode 100644 tvision/examples/listvi/rhide.env create mode 100644 tvision/examples/msgcls/msgcls.bmk create mode 100644 tvision/examples/msgcls/msgcls.gpr create mode 100644 tvision/examples/msgcls/msgcls.mkf create mode 100644 tvision/examples/msgcls/msgcls.umk create mode 100644 tvision/examples/msgcls/readme.txt create mode 100644 tvision/examples/msgcls/rhide.env create mode 100644 tvision/examples/msgcls/testdyn.cpp create mode 100644 tvision/examples/msgcls/tlnmsg.cpp create mode 100644 tvision/examples/msgcls/tlnmsg.h create mode 100644 tvision/examples/patchenv.pl create mode 100644 tvision/examples/porting.txt create mode 100644 tvision/examples/progba/example.cpp create mode 100644 tvision/examples/progba/makerez.cpp create mode 100644 tvision/examples/progba/readrez.cpp create mode 100644 tvision/examples/progba/rhide.env create mode 100644 tvision/examples/progba/test.bmk create mode 100644 tvision/examples/progba/test.gpr create mode 100644 tvision/examples/progba/test.mkf create mode 100644 tvision/examples/progba/test.umk create mode 100644 tvision/examples/progba/tprogbar.cpp create mode 100644 tvision/examples/progba/tprogbar.h create mode 100644 tvision/examples/readme.txt create mode 100644 tvision/examples/sdlg/dlg.h create mode 100644 tvision/examples/sdlg/main.cpp create mode 100644 tvision/examples/sdlg/rhide.env create mode 100644 tvision/examples/sdlg/scrldlg.cpp create mode 100644 tvision/examples/sdlg/scrlgrp.cpp create mode 100644 tvision/examples/sdlg/test.bmk create mode 100644 tvision/examples/sdlg/test.gpr create mode 100644 tvision/examples/sdlg/test.mkf create mode 100644 tvision/examples/sdlg/test.umk create mode 100644 tvision/examples/sdlg2/dlg.h create mode 100644 tvision/examples/sdlg2/main.cpp create mode 100644 tvision/examples/sdlg2/rhide.env create mode 100644 tvision/examples/sdlg2/scrldlg.cpp create mode 100644 tvision/examples/sdlg2/scrlgrp.cpp create mode 100644 tvision/examples/sdlg2/test.bmk create mode 100644 tvision/examples/sdlg2/test.gpr create mode 100644 tvision/examples/sdlg2/test.mkf create mode 100644 tvision/examples/sdlg2/test.umk create mode 100644 tvision/examples/tcombo/nmcmbobx.cpp create mode 100644 tvision/examples/tcombo/nmcmbovw.cpp create mode 100644 tvision/examples/tcombo/nmcmbown.cpp create mode 100644 tvision/examples/tcombo/nmsinput.cpp create mode 100644 tvision/examples/tcombo/readme.txt create mode 100644 tvision/examples/tcombo/rhide.env create mode 100644 tvision/examples/tcombo/scombobx.cpp create mode 100644 tvision/examples/tcombo/scombovw.cpp create mode 100644 tvision/examples/tcombo/scombown.cpp create mode 100644 tvision/examples/tcombo/ssinputl.cpp create mode 100644 tvision/examples/tcombo/tcmbovwr.cpp create mode 100644 tvision/examples/tcombo/tcmbowin.cpp create mode 100644 tvision/examples/tcombo/tcombo.txt create mode 100644 tvision/examples/tcombo/tcombobx.cpp create mode 100644 tvision/examples/tcombo/tcombobx.h create mode 100644 tvision/examples/tcombo/test.bmk create mode 100644 tvision/examples/tcombo/test.cpp create mode 100644 tvision/examples/tcombo/test.gpr create mode 100644 tvision/examples/tcombo/test.mkf create mode 100644 tvision/examples/tcombo/test.umk create mode 100644 tvision/examples/tcombo/tsinputl.cpp create mode 100644 tvision/examples/tcombo/tsinputl.h create mode 100644 tvision/examples/terminal/rhide.env create mode 100644 tvision/examples/terminal/terminal.cc create mode 100644 tvision/examples/terminal/test.bmk create mode 100644 tvision/examples/terminal/test.gpr create mode 100644 tvision/examples/terminal/test.mkf create mode 100644 tvision/examples/terminal/test.umk create mode 100644 tvision/examples/tprogb/calc.cpp create mode 100644 tvision/examples/tprogb/rhide.env create mode 100644 tvision/examples/tprogb/test.bmk create mode 100644 tvision/examples/tprogb/test.gpr create mode 100644 tvision/examples/tprogb/test.mkf create mode 100644 tvision/examples/tprogb/test.umk create mode 100644 tvision/examples/tprogb/tprogbar.cpp create mode 100644 tvision/examples/tprogb/tprogbar.h create mode 100644 tvision/examples/tutorial/rhide.env create mode 100644 tvision/examples/tutorial/tvguid01.bmk create mode 100644 tvision/examples/tutorial/tvguid01.cc create mode 100644 tvision/examples/tutorial/tvguid01.gpr create mode 100644 tvision/examples/tutorial/tvguid01.mkf create mode 100644 tvision/examples/tutorial/tvguid01.umk create mode 100644 tvision/examples/tutorial/tvguid02.bmk create mode 100644 tvision/examples/tutorial/tvguid02.cc create mode 100644 tvision/examples/tutorial/tvguid02.gpr create mode 100644 tvision/examples/tutorial/tvguid02.mkf create mode 100644 tvision/examples/tutorial/tvguid02.umk create mode 100644 tvision/examples/tutorial/tvguid03.bmk create mode 100644 tvision/examples/tutorial/tvguid03.cc create mode 100644 tvision/examples/tutorial/tvguid03.gpr create mode 100644 tvision/examples/tutorial/tvguid03.mkf create mode 100644 tvision/examples/tutorial/tvguid03.umk create mode 100644 tvision/examples/tutorial/tvguid04.bmk create mode 100644 tvision/examples/tutorial/tvguid04.cc create mode 100644 tvision/examples/tutorial/tvguid04.gpr create mode 100644 tvision/examples/tutorial/tvguid04.mkf create mode 100644 tvision/examples/tutorial/tvguid04.umk create mode 100644 tvision/examples/tutorial/tvguid05.bmk create mode 100644 tvision/examples/tutorial/tvguid05.cc create mode 100644 tvision/examples/tutorial/tvguid05.gpr create mode 100644 tvision/examples/tutorial/tvguid05.mkf create mode 100644 tvision/examples/tutorial/tvguid05.umk create mode 100644 tvision/examples/tutorial/tvguid06.bmk create mode 100644 tvision/examples/tutorial/tvguid06.cc create mode 100644 tvision/examples/tutorial/tvguid06.gpr create mode 100644 tvision/examples/tutorial/tvguid06.mkf create mode 100644 tvision/examples/tutorial/tvguid06.umk create mode 100644 tvision/examples/tutorial/tvguid07.bmk create mode 100644 tvision/examples/tutorial/tvguid07.cc create mode 100644 tvision/examples/tutorial/tvguid07.gpr create mode 100644 tvision/examples/tutorial/tvguid07.mkf create mode 100644 tvision/examples/tutorial/tvguid07.umk create mode 100644 tvision/examples/tutorial/tvguid08.bmk create mode 100644 tvision/examples/tutorial/tvguid08.cc create mode 100644 tvision/examples/tutorial/tvguid08.gpr create mode 100644 tvision/examples/tutorial/tvguid08.mkf create mode 100644 tvision/examples/tutorial/tvguid08.umk create mode 100644 tvision/examples/tutorial/tvguid09.bmk create mode 100644 tvision/examples/tutorial/tvguid09.cc create mode 100644 tvision/examples/tutorial/tvguid09.gpr create mode 100644 tvision/examples/tutorial/tvguid09.mkf create mode 100644 tvision/examples/tutorial/tvguid09.umk create mode 100644 tvision/examples/tutorial/tvguid10.bmk create mode 100644 tvision/examples/tutorial/tvguid10.cc create mode 100644 tvision/examples/tutorial/tvguid10.gpr create mode 100644 tvision/examples/tutorial/tvguid10.mkf create mode 100644 tvision/examples/tutorial/tvguid10.umk create mode 100644 tvision/examples/tutorial/tvguid11.bmk create mode 100644 tvision/examples/tutorial/tvguid11.cc create mode 100644 tvision/examples/tutorial/tvguid11.gpr create mode 100644 tvision/examples/tutorial/tvguid11.mkf create mode 100644 tvision/examples/tutorial/tvguid11.umk create mode 100644 tvision/examples/tutorial/tvguid12.bmk create mode 100644 tvision/examples/tutorial/tvguid12.cc create mode 100644 tvision/examples/tutorial/tvguid12.gpr create mode 100644 tvision/examples/tutorial/tvguid12.mkf create mode 100644 tvision/examples/tutorial/tvguid12.umk create mode 100644 tvision/examples/tutorial/tvguid13.bmk create mode 100644 tvision/examples/tutorial/tvguid13.cc create mode 100644 tvision/examples/tutorial/tvguid13.gpr create mode 100644 tvision/examples/tutorial/tvguid13.mkf create mode 100644 tvision/examples/tutorial/tvguid13.umk create mode 100644 tvision/examples/tutorial/tvguid14.bmk create mode 100644 tvision/examples/tutorial/tvguid14.cc create mode 100644 tvision/examples/tutorial/tvguid14.gpr create mode 100644 tvision/examples/tutorial/tvguid14.mkf create mode 100644 tvision/examples/tutorial/tvguid14.umk create mode 100644 tvision/examples/tutorial/tvguid15.bmk create mode 100644 tvision/examples/tutorial/tvguid15.cc create mode 100644 tvision/examples/tutorial/tvguid15.gpr create mode 100644 tvision/examples/tutorial/tvguid15.mkf create mode 100644 tvision/examples/tutorial/tvguid15.umk create mode 100644 tvision/examples/tutorial/tvguid16.bmk create mode 100644 tvision/examples/tutorial/tvguid16.cc create mode 100644 tvision/examples/tutorial/tvguid16.gpr create mode 100644 tvision/examples/tutorial/tvguid16.mkf create mode 100644 tvision/examples/tutorial/tvguid16.umk create mode 100644 tvision/examples/tvedit/rhide.env create mode 100644 tvision/examples/tvedit/tvedit.bmk create mode 100644 tvision/examples/tvedit/tvedit.cc create mode 100644 tvision/examples/tvedit/tvedit.gpr create mode 100644 tvision/examples/tvedit/tvedit.mkf create mode 100644 tvision/examples/tvedit/tvedit.umk create mode 100644 tvision/examples/tvhc/demohelp.txt create mode 100644 tvision/examples/tvhc/rhide.env create mode 100644 tvision/examples/tvhc/tvhc.bmk create mode 100644 tvision/examples/tvhc/tvhc.cc create mode 100644 tvision/examples/tvhc/tvhc.gpr create mode 100644 tvision/examples/tvhc/tvhc.h create mode 100644 tvision/examples/tvhc/tvhc.mkf create mode 100644 tvision/examples/tvhc/tvhc.umk create mode 100644 tvision/examples/videomode/rhide.env create mode 100644 tvision/examples/videomode/test.bmk create mode 100644 tvision/examples/videomode/test.cc create mode 100644 tvision/examples/videomode/test.gpr create mode 100644 tvision/examples/videomode/test.mkf create mode 100644 tvision/examples/videomode/test.umk create mode 100644 tvision/examples/viewers/test.bmk create mode 100644 tvision/examples/viewers/test.mkf create mode 100644 tvision/examples/viewers/test.umk create mode 100755 tvision/examples/xterm/Xterm.res create mode 100644 tvision/extra/doskeys/kextend.asm create mode 100644 tvision/extra/doskeys/kextend.com create mode 100644 tvision/extra/doskeys/kextend.txt create mode 100644 tvision/extra/eterm/Setedit/MAIN create mode 100644 tvision/extra/eterm/Setedit/Setedit.menu create mode 100644 tvision/extra/eterm/readme.txt create mode 100644 tvision/extra/eterm/xterm-eterm-tv create mode 100644 tvision/extra/pifexamp/setedit.pif create mode 100644 tvision/fileview.cc create mode 100644 tvision/fromdos.pl create mode 100644 tvision/fromunix.pl create mode 100644 tvision/histlist.cc create mode 100644 tvision/include/cl/dir.h create mode 100644 tvision/include/cl/dirent.h create mode 100644 tvision/include/cl/fnmatch.h create mode 100644 tvision/include/cl/getopt.h create mode 100644 tvision/include/cl/glob.h create mode 100644 tvision/include/cl/needs.h create mode 100644 tvision/include/cl/regex.h create mode 100644 tvision/include/cl/strstream.h create mode 100644 tvision/include/cl/unistd.h create mode 100644 tvision/include/cl/utime.h create mode 100644 tvision/include/cl/utsname.h create mode 100644 tvision/include/compatlayer.h create mode 100644 tvision/include/tv.h create mode 100644 tvision/include/tv/alcon/alcon.h create mode 100644 tvision/include/tv/alcon/key.h create mode 100644 tvision/include/tv/alcon/mouse.h create mode 100644 tvision/include/tv/alcon/screen.h create mode 100644 tvision/include/tv/app.h create mode 100644 tvision/include/tv/applictn.h create mode 100644 tvision/include/tv/backgrnd.h create mode 100644 tvision/include/tv/button.h create mode 100644 tvision/include/tv/calc.h create mode 100644 tvision/include/tv/chdirdlg.h create mode 100644 tvision/include/tv/checkbox.h create mode 100644 tvision/include/tv/clrdisp.h create mode 100644 tvision/include/tv/clrdlg.h create mode 100644 tvision/include/tv/clrgroup.h create mode 100644 tvision/include/tv/clrgrpli.h create mode 100644 tvision/include/tv/clritem.h create mode 100644 tvision/include/tv/clriteml.h create mode 100644 tvision/include/tv/clrselct.h create mode 100644 tvision/include/tv/cluster.h create mode 100644 tvision/include/tv/cmdset.h create mode 100644 tvision/include/tv/codepage.h create mode 100644 tvision/include/tv/collectn.h create mode 100644 tvision/include/tv/colorsel.h create mode 100644 tvision/include/tv/configfile.h create mode 100644 tvision/include/tv/desktop.h create mode 100644 tvision/include/tv/dialog.h create mode 100644 tvision/include/tv/dialogs.h create mode 100644 tvision/include/tv/dircoll.h create mode 100644 tvision/include/tv/direntr.h create mode 100644 tvision/include/tv/dirlibo.h create mode 100644 tvision/include/tv/dos/key.h create mode 100644 tvision/include/tv/dos/mouse.h create mode 100644 tvision/include/tv/dos/screen.h create mode 100644 tvision/include/tv/drawbuf.h create mode 100644 tvision/include/tv/drivers.h create mode 100644 tvision/include/tv/editors.h create mode 100644 tvision/include/tv/event.h create mode 100644 tvision/include/tv/eventqu.h create mode 100644 tvision/include/tv/filecoll.h create mode 100644 tvision/include/tv/filedlg.h create mode 100644 tvision/include/tv/filelist.h create mode 100644 tvision/include/tv/fileview.h create mode 100644 tvision/include/tv/filinfpn.h create mode 100644 tvision/include/tv/filinpln.h create mode 100644 tvision/include/tv/findrepl.h create mode 100644 tvision/include/tv/fontcoll.h create mode 100644 tvision/include/tv/fpbase.h create mode 100644 tvision/include/tv/fpstream.h create mode 100644 tvision/include/tv/frame.h create mode 100644 tvision/include/tv/gkey.h create mode 100644 tvision/include/tv/group.h create mode 100644 tvision/include/tv/help.h create mode 100644 tvision/include/tv/helpbase.h create mode 100644 tvision/include/tv/history.h create mode 100644 tvision/include/tv/histvwer.h create mode 100644 tvision/include/tv/histwind.h create mode 100644 tvision/include/tv/ifpstrm.h create mode 100644 tvision/include/tv/indicato.h create mode 100644 tvision/include/tv/inputln.h create mode 100644 tvision/include/tv/intl.h create mode 100644 tvision/include/tv/iopstrm.h create mode 100644 tvision/include/tv/ipstream.h create mode 100644 tvision/include/tv/label.h create mode 100644 tvision/include/tv/linux/key.h create mode 100644 tvision/include/tv/linux/log.h create mode 100644 tvision/include/tv/linux/mouse.h create mode 100644 tvision/include/tv/linux/screen.h create mode 100644 tvision/include/tv/listbox.h create mode 100644 tvision/include/tv/lstviewr.h create mode 100644 tvision/include/tv/menu.h create mode 100644 tvision/include/tv/menubar.h create mode 100644 tvision/include/tv/menubox.h create mode 100644 tvision/include/tv/menuitem.h create mode 100644 tvision/include/tv/menus.h create mode 100644 tvision/include/tv/menuview.h create mode 100644 tvision/include/tv/mnoselct.h create mode 100644 tvision/include/tv/msgbox.h create mode 100644 tvision/include/tv/no_mss.h create mode 100644 tvision/include/tv/nointl.h create mode 100644 tvision/include/tv/nscoll.h create mode 100644 tvision/include/tv/nssorcol.h create mode 100644 tvision/include/tv/object.h create mode 100644 tvision/include/tv/objects.h create mode 100644 tvision/include/tv/ofpstrm.h create mode 100644 tvision/include/tv/opstream.h create mode 100644 tvision/include/tv/osclipboard.h create mode 100644 tvision/include/tv/otstream.h create mode 100644 tvision/include/tv/palette.h create mode 100644 tvision/include/tv/parmtext.h create mode 100644 tvision/include/tv/parttree.h create mode 100644 tvision/include/tv/point.h create mode 100644 tvision/include/tv/preadobj.h create mode 100644 tvision/include/tv/program.h create mode 100644 tvision/include/tv/pstream.h create mode 100644 tvision/include/tv/pwritobj.h create mode 100644 tvision/include/tv/qnx4/key.h create mode 100644 tvision/include/tv/qnx4/mouse.h create mode 100644 tvision/include/tv/qnx4/screen.h create mode 100644 tvision/include/tv/qnxrtp/key.h create mode 100644 tvision/include/tv/qnxrtp/mouse.h create mode 100644 tvision/include/tv/qnxrtp/screen.h create mode 100644 tvision/include/tv/radiobtn.h create mode 100644 tvision/include/tv/rect.h create mode 100644 tvision/include/tv/rescoll.h create mode 100644 tvision/include/tv/resfile.h create mode 100644 tvision/include/tv/resitem.h create mode 100644 tvision/include/tv/resource.h create mode 100644 tvision/include/tv/screen.h create mode 100644 tvision/include/tv/scrlbar.h create mode 100644 tvision/include/tv/scroller.h create mode 100644 tvision/include/tv/searchrc.h create mode 100644 tvision/include/tv/sitem.h create mode 100644 tvision/include/tv/skeleton/key.h create mode 100644 tvision/include/tv/skeleton/mouse.h create mode 100644 tvision/include/tv/skeleton/screen.h create mode 100644 tvision/include/tv/sortcoll.h create mode 100644 tvision/include/tv/sortlibo.h create mode 100644 tvision/include/tv/ssc_streams.h create mode 100644 tvision/include/tv/statsdef.h create mode 100644 tvision/include/tv/statsitm.h create mode 100644 tvision/include/tv/statslin.h create mode 100644 tvision/include/tv/stddlg.h create mode 100644 tvision/include/tv/streambl.h create mode 100644 tvision/include/tv/strilist.h create mode 100644 tvision/include/tv/strinrec.h create mode 100644 tvision/include/tv/strlistm.h create mode 100644 tvision/include/tv/strmblcl.h create mode 100644 tvision/include/tv/strmblty.h create mode 100644 tvision/include/tv/strncoll.h create mode 100644 tvision/include/tv/sttctext.h create mode 100644 tvision/include/tv/submenu.h create mode 100644 tvision/include/tv/system.h create mode 100644 tvision/include/tv/terminal.h create mode 100644 tvision/include/tv/textdev.h create mode 100644 tvision/include/tv/textview.h create mode 100644 tvision/include/tv/tkeyext.h create mode 100644 tvision/include/tv/tkeys.h create mode 100644 tvision/include/tv/tobjstrm.h create mode 100644 tvision/include/tv/ttypes.h create mode 100644 tvision/include/tv/tvconfig.h create mode 100644 tvision/include/tv/tvedit.h create mode 100644 tvision/include/tv/tvobjs.h create mode 100644 tvision/include/tv/tvutil.h create mode 100644 tvision/include/tv/unix/key.h create mode 100644 tvision/include/tv/unix/mouse.h create mode 100644 tvision/include/tv/unix/screen.h create mode 100644 tvision/include/tv/unix/xtkey.h create mode 100644 tvision/include/tv/unix/xtmouse.h create mode 100644 tvision/include/tv/unix/xtscreen.h create mode 100644 tvision/include/tv/validate.h create mode 100644 tvision/include/tv/video.h create mode 100644 tvision/include/tv/view.h create mode 100644 tvision/include/tv/views.h create mode 100644 tvision/include/tv/win32/key.h create mode 100644 tvision/include/tv/win32/mouse.h create mode 100644 tvision/include/tv/win32/screen.h create mode 100644 tvision/include/tv/win32/win32clip.h create mode 100644 tvision/include/tv/window.h create mode 100644 tvision/include/tv/wingr/key.h create mode 100644 tvision/include/tv/wingr/mouse.h create mode 100644 tvision/include/tv/wingr/screen.h create mode 100644 tvision/include/tv/winnt/key.h create mode 100644 tvision/include/tv/winnt/mouse.h create mode 100644 tvision/include/tv/winnt/screen.h create mode 100644 tvision/include/tv/x11/key.h create mode 100644 tvision/include/tv/x11/mouse.h create mode 100644 tvision/include/tv/x11/screen.h create mode 100644 tvision/include/tv/yes_mss.h create mode 100644 tvision/intl/Makefile create mode 100644 tvision/intl/dummy/Makefile create mode 100644 tvision/intl/dummy/intldummy.c create mode 100644 tvision/intl/es.po create mode 100644 tvision/intl/gnumake.in create mode 100644 tvision/intl/pl.po create mode 100644 tvision/intl/ru.po create mode 100644 tvision/intl/tvision.po create mode 100644 tvision/intl/utod.pl create mode 100755 tvision/linux/compress create mode 100644 tvision/linux/inclubin.txt create mode 100644 tvision/linux/includbi.txt create mode 100644 tvision/linux/sacadeb create mode 100644 tvision/lista create mode 100644 tvision/lista.dos create mode 100644 tvision/makes/blink.c create mode 100644 tvision/makes/common.bmk create mode 100644 tvision/makes/common.imk create mode 100644 tvision/makes/common.nmk create mode 100644 tvision/makes/common.wat create mode 100644 tvision/makes/config.bcc create mode 100644 tvision/makes/config.nmk create mode 100644 tvision/makes/config.wat create mode 100644 tvision/makes/extrimk.cc create mode 100644 tvision/makes/genimk.cc create mode 100644 tvision/makes/includer.bmk create mode 100644 tvision/makes/includer.imk create mode 100644 tvision/makes/librhtv.bmk create mode 100644 tvision/makes/librhtv.gpr create mode 100644 tvision/makes/librhtv.imk create mode 100644 tvision/makes/librhtv.mkf create mode 100644 tvision/makes/librhtv.umk create mode 100644 tvision/makes/maintain.mak create mode 100644 tvision/makes/mlink.c create mode 100644 tvision/makes/obj/delete.me create mode 100644 tvision/misc.cc create mode 100644 tvision/miscperl.pl create mode 100644 tvision/msgbox.cc create mode 100644 tvision/names/nbackgro.cc create mode 100644 tvision/names/nbutton.cc create mode 100644 tvision/names/ncalcdis.cc create mode 100644 tvision/names/ncalcula.cc create mode 100644 tvision/names/nchdirdi.cc create mode 100644 tvision/names/ncheckbo.cc create mode 100644 tvision/names/nclrdisp.cc create mode 100644 tvision/names/ncluster.cc create mode 100644 tvision/names/ncollect.cc create mode 100644 tvision/names/ncolordi.cc create mode 100644 tvision/names/ncolorgr.cc create mode 100644 tvision/names/ncolorit.cc create mode 100644 tvision/names/ncolorse.cc create mode 100644 tvision/names/ndesktop.cc create mode 100644 tvision/names/ndialog.cc create mode 100644 tvision/names/ndircoll.cc create mode 100644 tvision/names/ndirlist.cc create mode 100644 tvision/names/neditor.cc create mode 100644 tvision/names/neditwi.cc create mode 100644 tvision/names/nfilecol.cc create mode 100644 tvision/names/nfiledia.cc create mode 100644 tvision/names/nfiledtr.cc create mode 100644 tvision/names/nfileinf.cc create mode 100644 tvision/names/nfileinp.cc create mode 100644 tvision/names/nfilelis.cc create mode 100644 tvision/names/nfilterv.cc create mode 100644 tvision/names/nframe.cc create mode 100644 tvision/names/ngroup.cc create mode 100644 tvision/names/nhistory.cc create mode 100644 tvision/names/nindicat.cc create mode 100644 tvision/names/ninputli.cc create mode 100644 tvision/names/nlabel.cc create mode 100644 tvision/names/nlistbox.cc create mode 100644 tvision/names/nlistvie.cc create mode 100644 tvision/names/nlookupv.cc create mode 100644 tvision/names/nmemo.cc create mode 100644 tvision/names/nmenubar.cc create mode 100644 tvision/names/nmenubox.cc create mode 100644 tvision/names/nmenuvie.cc create mode 100644 tvision/names/nmonosel.cc create mode 100644 tvision/names/nparamte.cc create mode 100644 tvision/names/npxvalid.cc create mode 100644 tvision/names/nradiobu.cc create mode 100644 tvision/names/nrangeva.cc create mode 100644 tvision/names/nresourc.cc create mode 100644 tvision/names/nscrollb.cc create mode 100644 tvision/names/nscrolle.cc create mode 100644 tvision/names/nsortedc.cc create mode 100644 tvision/names/nsortedl.cc create mode 100644 tvision/names/nstatict.cc create mode 100644 tvision/names/nstatusl.cc create mode 100644 tvision/names/nstringc.cc create mode 100644 tvision/names/nstringl.cc create mode 100644 tvision/names/nvalidat.cc create mode 100644 tvision/names/nview.cc create mode 100644 tvision/names/nwindow.cc create mode 100644 tvision/newstr.cc create mode 100644 tvision/qnxrtp/tvision.qpg create mode 100644 tvision/qnxrtp/tvision.qpg.in create mode 100644 tvision/readme.in create mode 100644 tvision/readme.txt create mode 100644 tvision/redhat/.cvsignore create mode 100644 tvision/redhat/README create mode 100755 tvision/redhat/config-rpm.sh create mode 100755 tvision/redhat/create-dirs.sh create mode 100755 tvision/redhat/create-rpms.sh create mode 100644 tvision/redhat/librhtv.spec.in create mode 100644 tvision/rhide.env create mode 100644 tvision/rhtv-config.c create mode 100755 tvision/searchstrs.sh create mode 100644 tvision/snapshot.pl create mode 100644 tvision/stream/sbackgro.cc create mode 100644 tvision/stream/sbutton.cc create mode 100644 tvision/stream/scalcdis.cc create mode 100644 tvision/stream/scalcula.cc create mode 100644 tvision/stream/schdirdi.cc create mode 100644 tvision/stream/scheckbo.cc create mode 100644 tvision/stream/sclrdisp.cc create mode 100644 tvision/stream/scluster.cc create mode 100644 tvision/stream/scolordi.cc create mode 100644 tvision/stream/scolorgr.cc create mode 100644 tvision/stream/scolorit.cc create mode 100644 tvision/stream/scolorse.cc create mode 100644 tvision/stream/sdesktop.cc create mode 100644 tvision/stream/sdialog.cc create mode 100644 tvision/stream/sdircoll.cc create mode 100644 tvision/stream/sdirlist.cc create mode 100644 tvision/stream/seditor.cc create mode 100644 tvision/stream/seditwin.cc create mode 100644 tvision/stream/sfilecol.cc create mode 100644 tvision/stream/sfiledia.cc create mode 100644 tvision/stream/sfileedi.cc create mode 100644 tvision/stream/sfileinf.cc create mode 100644 tvision/stream/sfileinp.cc create mode 100644 tvision/stream/sfilelis.cc create mode 100644 tvision/stream/sfilterv.cc create mode 100644 tvision/stream/sframe.cc create mode 100644 tvision/stream/sgroup.cc create mode 100644 tvision/stream/shistory.cc create mode 100644 tvision/stream/sindicat.cc create mode 100644 tvision/stream/sinputli.cc create mode 100644 tvision/stream/slabel.cc create mode 100644 tvision/stream/slistbox.cc create mode 100644 tvision/stream/slistvie.cc create mode 100644 tvision/stream/slookupv.cc create mode 100644 tvision/stream/smemo.cc create mode 100644 tvision/stream/smenubar.cc create mode 100644 tvision/stream/smenubox.cc create mode 100644 tvision/stream/smenuvie.cc create mode 100644 tvision/stream/smonosel.cc create mode 100644 tvision/stream/sparamte.cc create mode 100644 tvision/stream/spxvalid.cc create mode 100644 tvision/stream/sradiobu.cc create mode 100644 tvision/stream/srangeva.cc create mode 100644 tvision/stream/sresourc.cc create mode 100644 tvision/stream/sscrollb.cc create mode 100644 tvision/stream/sscrolle.cc create mode 100644 tvision/stream/sstatict.cc create mode 100644 tvision/stream/sstatusl.cc create mode 100644 tvision/stream/sstringc.cc create mode 100644 tvision/stream/sstringl.cc create mode 100644 tvision/stream/sview.cc create mode 100644 tvision/stream/swindow.cc create mode 100755 tvision/update create mode 100755 tvision/update.bat create mode 100644 tvision/version.txt create mode 100644 tvision/win32/readme.txt create mode 100644 tvision/winnt/Makefile create mode 100644 tvision/winnt/Makefile.nmk create mode 100644 tvision/winnt/bccmake.in create mode 100644 tvision/winnt/include/msvc/dir.h create mode 100644 tvision/winnt/include/msvc/dirent.h create mode 100644 tvision/winnt/include/msvc/strstream.h create mode 100644 tvision/winnt/include/tv/configtv.h create mode 100644 tvision/winnt/msvcmake.in create mode 100644 tvision/winnt/obj_ms/delete.me create mode 100644 tvision/winnt/objs/delete.me create mode 100644 tvision/winnt/readme.txt create mode 100644 tvision/winnt/tvex.cc create mode 100644 tvision/www-site/bvucs-n1.jpg create mode 100644 tvision/www-site/contrib.html create mode 100644 tvision/www-site/envelp.gif create mode 100644 tvision/www-site/history.html create mode 100644 tvision/www-site/index.html create mode 100644 tvision/www-site/sf.css create mode 100755 tvision/www-site/update diff --git a/GNUmakefile b/GNUmakefile new file mode 100644 index 0000000..3163197 --- /dev/null +++ b/GNUmakefile @@ -0,0 +1,8 @@ +TOPDIR = . + +SUBDIRS = src + +PACKAGE_NAME = tvisiontests +PACKAGE_VERSION = 0.0.1 + +-include $(TOPDIR)/makefiles/gmake/top.mk diff --git a/makefiles/README b/makefiles/README new file mode 100644 index 0000000..d5dcaff --- /dev/null +++ b/makefiles/README @@ -0,0 +1,4 @@ +Snippets and other goodies for makefiles + +gmake - include snippets for GNU makefiles +nmake - include snippets for Windows NMAKE makefiles diff --git a/makefiles/gmake/clean.mk b/makefiles/gmake/clean.mk new file mode 100644 index 0000000..92061d4 --- /dev/null +++ b/makefiles/gmake/clean.mk @@ -0,0 +1,41 @@ +# cleans up directories +# +# requires: +# - SUBDIRS: for recursive cleaning +# - local_clean, local_distclean targets in local GNUmakefile +# - all artifacts to clean: +# - BINS, TEST_BINS, TEST_CPP_BINS, CPP_BINS +# - OBJS, CPPOBJS, BIN_OBJS, TEST_BIN_OBJS, CPP_BIN_OBJS, TEST_CPP_BIN_OBJS +# - CMODULES, CPPMODULES +# +# provides: +# - target: clean +# - target: distclean + +.PHONY: clean_recursive clean local_clean + +clean_recursive: + @test -z "$(SUBDIRS)" || ( set -e; for d in $(SUBDIRS)""; do \ + (set -e; $(MAKE) -C $$d clean || exit 1); done) + +clean: clean_recursive clean_po local_clean + -@rm -f *.bak 2>/dev/null + -@rm -f *~ 2>/dev/null + -@rm -f *.d port/*.d 2>/dev/null + -@rm -f $(BINS) $(CPP_BINS) $(TEST_BINS) $(TEST_CPP_BINS) 2>/dev/null + -@rm -f $(OBJS) $(CPP_OBJS) $(BIN_OBJS) $(TEST_BIN_OBJS) $(CPP_BIN_OBJS) $(TEST_CPP_BIN_OBJS) 2>/dev/null + -@rm -f exec/* 2>/dev/null + -@rm -f *.core 2>/dev/null + -@rm -f $(CMODULES) $(CPPMODULES) 2>/dev/null + -@rm -f $(CMODULES:.o=.d) $(CPPMODULES:.o=.d) 2>/dev/null + -@rm -rf $(STATIC_LIB) 2>/dev/null + -@rm -rf $(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR).$(DYNAMIC_LIB_MINOR).$(DYNAMIC_LIB_PATCH) 2>/dev/null + -@rm -f $(SH_OBJS) rm -f $(SHPP_OBJS) 2>/dev/null + +.PHONY: distclean_recursive distclean local_distclean + +distclean_recursive: + @test -z "$(SUBDIRS)" || ( set -e; for d in $(SUBDIRS)""; do \ + (set -e; $(MAKE) -C $$d distclean || exit 1); done) + +distclean: distclean_recursive local_distclean clean diff --git a/makefiles/gmake/compiler.mk b/makefiles/gmake/compiler.mk new file mode 100644 index 0000000..4629fd1 --- /dev/null +++ b/makefiles/gmake/compiler.mk @@ -0,0 +1,347 @@ +# sets compiler settings +# +# requires: +# - INCLUDE_DIRS +# +# provides: +# - BIN_OBJS: the object files we need for the binaries which we build always +# - CPP_BIN_OBJS: same for binaries which have C++ code in them +# - TEST_BIN_OBJS: same as BIN_OBJS but for test binaries compiled only when +# testing +# - TEST_CPP_BIN_OBJS: same for C++ tests +# + +# start of gcc section + +ifeq "$(COMPILER)" "gcc" + +GCC_MAJOR_VERSION ?= $(shell $(TOPDIR)/makefiles/gmake/guess_env --gcc-major-version $(CC) "$(CURDIR)" $(TOPDIR)) +GCC_MINOR_VERSION ?= $(shell $(TOPDIR)/makefiles/gmake/guess_env --gcc-minor-version $(CC) "$(CURDIR)" $(TOPDIR)) + +# -Wswitch-default: not good for switches with enums +# -Wsystem-headers: bad idea, as header files are usually happily broken :-) +# -Wtraditional: we don't want to program tradition K&R C anymore! +# -Wunsafe-loop-optimizations: ?? +# -Wno-attributes, -Wmissing-format-attribute: ?? later +# -Wpacked -Wpadded: ?? very questionable +# -Wunreachable-code: doesn't work +# -Wno-div-by-zero: we get NaN and friend over macros, so need for funny tricks :-) +# -Wstrict-overflow=5 is relatively new, later maybe +# -fstack-protector or -fstack-protector-all: should be used, but U +# have currently big problems to get it around compiler gcc and -lssl +# probing! FIXME later +# -fstack-protector-all: does something funny to the shared objects.. +# -Wstack-protector makes no sense without SSP +# everything implied by -Wall is not explicitly specified (gcc 4.2.3) +# TODO: reenable -O2 +# -Waggregate-return: is for K&R code and mostly useless nowadays +# -Wno-long-long: some boost code header require 'long long' + +# compilation flags and compilers +COMMON_COMPILE_FLAGS = \ + -g \ + -fstrict-aliasing \ + -pedantic -Wall -Werror \ + -Wno-long-long \ + -Wunused -Wno-import \ + -Wformat -Wformat-y2k -Wformat-nonliteral -Wformat-security -Wformat-y2k \ + -Wswitch-enum -Wunknown-pragmas -Wfloat-equal \ + -Wundef -Wshadow -Wpointer-arith \ + -Wcast-qual -Wcast-align \ + -Wwrite-strings \ + -Wmissing-noreturn \ + -Wno-multichar -Wparentheses -Wredundant-decls \ + -Winline \ + -Wdisabled-optimization +ifeq "$(GCC_MAJOR_VERSION)" "4" +COMMON_COMPILE_FLAGS += \ + -Wfatal-errors -Wmissing-include-dirs -Wvariadic-macros \ + -Wvolatile-register-var \ + -Wstrict-aliasing=2 -Wextra -Winit-self +# -Wconversion had to meanings before gcc 4.3 (warn about ABI changes when porting +# old K&R code without function prototypes) and warn about conversions loosing +# precision. So we enable only -Wconversion (not -Wtraditional-conversion) for gcc +# >= 4.3 and no -Wconversion for older gcc versions! +# (see also http://gcc.gnu.org/wiki/NewWconversion) +ifeq "$(GCC_MINOR_VERSION)" "3" +COMMON_COMPILE_FLAGS += -Wconversion +endif + +endif + +ifeq "$(GCC_MAJOR_VERSION)" "3" + +# gcc 3.3, testend on OpenBSD 4.2 +ifeq "$(GCC_MINOR_VERSION)" "3" +COMMON_COMPILE_FLAGS += \ + -W +endif + +# gcc 3.4, not tested yet +ifeq "$(GCC_MINOR_VERSION)" "4" +COMMON_COMPILE_FLAGS += \ + -Wstrict-aliasing=2 -Wextra -Winit-self +endif + +endif + +STD99_COMPILE_FLAGS = \ + -std=c99 + +COMPILE_FLAGS = \ + $(COMMON_COMPILE_FLAGS) \ + $(STD99_COMPILE_FLAGS) \ + -Wnonnull \ + -Wbad-function-cast -Wstrict-prototypes \ + -Wmissing-prototypes -Wmissing-declarations \ + -Wnested-externs + +# gcc 4.x +ifeq "$(GCC_MAJOR_VERSION)" "4" +COMPILE_FLAGS += \ + -Wc++-compat -Wdeclaration-after-statement -Wold-style-definition \ + -funit-at-a-time +endif + +ifeq "$(GCC_MAJOR_VERSION)" "3" + +# gcc 3.4, not tested yet +ifeq "$(GCC_MINOR_VERSION)" "4" +COMPILE_FLAGS += \ + -Wdeclaration-after-statement -Wold-style-definition \ + -funit-at-a-time +endif + +# gcc 3.3, testend on OpenBSD 4.2 +ifeq "$(GCC_MINOR_VERSION)" "3" +#COMPILE_FLAGS += \ +# -Wdeclaration-after-statement +endif + +endif + +CCPP_COMPILE_FLAGS = \ + $(COMMON_COMPILE_FLAGS) \ + -std=c++98 + +# gcc 4.x +ifeq "$(GCC_MAJOR_VERSION)" "4" +CCPP_COMPILE_FLAGS += \ + -Wno-invalid-offsetof -funit-at-a-time +endif + +ifeq "$(GCC_MAJOR_VERSION)" "3" + +# gcc 3.4, not tested yet +ifeq "$(GCC_MINOR_VERSION)" "4" +CCPP_COMPILE_FLAGS += \ + -Wno-invalid-offsetof +endif + +# gcc 3.3, testend on OpenBSD 4.2 +ifeq "$(GCC_MINOR_VERSION)" "3" +#CCPP_COMPILE_FLAGS += \ +# -Wdeclaration-after-statement +endif + +endif + +#CC = gcc +CCPP = g++ + +endif + +# end of gcc section + +# start of tcc section + +# currently we don't need this, the tcc flags are fairly consistent +#TCC_MAJOR_VERSION ?= $(shell $(TOPDIR)/makefiles/gmake/guess_env --tcc-major-version $(CC) "$(CURDIR)" $(TOPDIR)) +#TCC_MINOR_VERSION ?= $(shell $(TOPDIR)/makefiles/gmake/guess_env --tcc-minor-version $(CC) "$(CURDIR)" $(TOPDIR)) + +ifeq "$(COMPILER)" "tcc" +COMPILE_FLAGS = \ + -Wall -Werror +endif + +# end of tcc section + +# start of icc section + +# currently we don't need this, the icc flags are fairly consistent +#ICC_MAJOR_VERSION ?= $(shell $(TOPDIR)/makefiles/gmake/guess_env --icc-major-version $(CC) "$(CURDIR)" $(TOPDIR)) +#ICC_MINOR_VERSION ?= $(shell $(TOPDIR)/makefiles/gmake/guess_env --icc-minor-version $(CC) "$(CURDIR)" $(TOPDIR)) + +# -vec-report0: turn of SSE2 vector usage messages (they are common since P-4 anyway!) + +ifeq "$(COMPILER)" "icc" +COMPILE_FLAGS = \ + -Wall -Werror -w1 -vec-report0 +endif + +# end of icc section + +# start of spro section + +# -xc99=all: full C99 compliance for the code (syntax and library functions) +# -Xc: full ISO compliance, no K&R stuf +# -mt: enable mutlithreading (-D_REENTRANT for header files, -lthread for ld) +# -errwarn=%all: convert all warnings to errors +# -v: do more restrictive syntax checking +# TODO: enable -O2 + +ifeq "$(COMPILER)" "spro" +STD99_COMPILE_FLAGS = \ + -xc99=all +COMPILE_FLAGS = \ + $(STD99_COMPILE_FLAGS) -Xc -errwarn=%all -mt -v +endif + +# end of spro section + +# start of pcc section + +# currently we don't need this, the pcc flags are fairly consistent +#PCC_MAJOR_VERSION ?= $(shell $(TOPDIR)/makefiles/gmake/guess_env --pcc-major-version $(CC) "$(CURDIR)" $(TOPDIR)) +#PCC_MINOR_VERSION ?= $(shell $(TOPDIR)/makefiles/gmake/guess_env --pcc-minor-version $(CC) "$(CURDIR)" $(TOPDIR)) + +ifeq "$(COMPILER)" "pcc" +COMPILE_FLAGS = \ + --fatal-warnings +endif + +# end of pcc section + +# set flags for threading support using POSIX threads. This is completly different +# between compiler/platforms +ifeq "$(COMPILER)" "gcc" +ifeq "$(PLATFORM)" "LINUX" +PTHREADS_CFLAGS = -D_REENTRANT -pthread +PTHREADS_LDFLAGS = -pthread +PTHREADS_LIBS = +endif +ifeq "$(PLATFORM)" "SUNOS" +PTHREADS_CFLAGS = -D_REENTRANT -pthreads +PTHREADS_LDFLAGS = -pthreads +PTHREADS_LIBS = +endif +ifeq "$(PLATFORM)" "FREEBSD" +PTHREADS_CFLAGS = -D_REENTRANT -pthread +PTHREADS_LDFLAGS = -pthread +PTHREADS_LIBS = +endif +ifeq "$(PLATFORM)" "NETBSD" +PTHREADS_CFLAGS = -D_REENTRANT -pthread +PTHREADS_LDFLAGS = -pthread +PTHREADS_LIBS = +endif +ifeq "$(PLATFORM)" "OPENBSD" +PTHREADS_CFLAGS = -D_REENTRANT -pthread +PTHREADS_LDFLAGS = -pthread +PTHREADS_LIBS = +endif +ifeq "$(PLATFORM)" "CYGWIN" +PTHREADS_CFLAGS = +PTHREADS_LDFLAGS = +PTHREADS_LIBS = +endif +endif + +ifeq "$(COMPILER)" "tcc" +ifeq "$(PLATFORM)" "LINUX" +PTHREADS_CFLAGS = -D_REENTRANT +PTHREADS_LDFLAGS = +PTHREADS_LIBS = -lpthread +endif +endif + +ifeq "$(COMPILER)" "pcc" +ifeq "$(PLATFORM)" "LINUX" +PTHREADS_CFLAGS = -D_REENTRANT -pthread +PTHREADS_LDFLAGS = -pthread +PTHREADS_LIBS = +endif +endif + +ifeq "$(COMPILER)" "icc" +ifeq "$(PLATFORM)" "LINUX" +PTHREADS_CFLAGS = -D_REENTRANT -pthread +PTHREADS_LDFLAGS = -pthread +PTHREADS_LIBS = +endif +endif + +# set flags for position independend code (as required for shared libraries +# on some platforms) +ifeq "$(COMPILER)" "gcc" +ifeq "$(PLATFORM)" "LINUX" +SO_COMPILE_FLAGS = -fPIC +endif +ifeq "$(PLATFORM)" "SUNOS" +SO_COMPILE_FLAGS = -fPIC +endif +ifeq "$(PLATFORM)" "FREEBSD" +SO_COMPILE_FLAGS = -fPIC +endif +ifeq "$(PLATFORM)" "NETBSD" +SO_COMPILE_FLAGS = -fPIC +endif +ifeq "$(PLATFORM)" "OPENBSD" +SO_COMPILE_FLAGS = -fPIC +endif +ifeq "$(PLATFORM)" "CYGWIN" +# code on Cygwin is always position independend +SO_COMPILE_FLAGS = +endif +endif + +ifeq "$(COMPILER)" "icc" +ifeq "$(PLATFORM)" "LINUX" +SO_COMPILE_FLAGS = -fPIC +endif +endif + +# TODO: test this +#ifeq "$(COMPILER)" "spro" +#ifeq "$(PLATFORM)" "SUNOS" +#ifeq "$(ARCH)" "sun4u" +#SO_COMPILE_FLAGS = -xcode=pic32 +#endif +#endif +#endif + +CFLAGS = $(COMPILE_FLAGS) $(PLATFORM_COMPILE_FLAGS) $(INCLUDE_DIRS) $(INCLUDE_CFLAGS) $(PTHREADS_CFLAGS) +CCPPFLAGS = $(CCPP_COMPILE_FLAGS) $(PLATFORM_COMPILE_FLAGS) $(INCLUDE_DIRS) $(INCLUDE_CPPFLAGS) $(PTHREADS_CFLAGS) + +LDFLAGS = $(INCLUDE_LDFLAGS) $(PTHREADS_LDFLAGS) $(LDFLAGS_NET) $(LDFLAGS_LT) +LIBS = $(INCLUDE_LIBS) $(PTHREADS_LIBS) $(LIBS_NET) $(LIBS_LT) +LINK = $(CC) +CCPP_LINK = $(CCPP) + +%.o : %.c + $(CC) -c -o $@ $(CFLAGS) $< + +%.o : %.cpp + $(CCPP) -c -o $@ $(CCPPFLAGS) $< + +%$(EXE): %.o $(OBJS) $(TEST_OBJS) + $(CCPP_LINK) -o $@ $(LDFLAGS) $(OBJS) $(TEST_OBJS) $< $(LIBS) + +%.sho : %.c + $(CC) -c -o $@ $(SO_COMPILE_FLAGS) -DSHARED $(CFLAGS) $< + +#%$(SO) : %.sho $(OBJS) +# $(LINK) -shared -o $@ $(LDFLAGS) $(LIBS) $(OBJS) $< + +%.sho++ : %.cpp + $(CCPP) -c -o $@ $(SO_COMPILE_FLAGS) -DSHARED $(CCPPFLAGS) $< + +#%$(SO) : %.sho++ $(OBJS) $(CPPOBJS) +# $(CCPP_LINK) -shared -o $@ $(LDFLAGS) $(LIBS) $(OBJS) $(CPPOBJS) $< + +BIN_OBJS = $(BINS:$(EXE)=.o) +TEST_BIN_OBJS = $(TEST_BINS:$(EXE)=.o) +CPP_BIN_OBJS = $(CPP_BINS:$(EXE)=.o) +TEST_CPP_BIN_OBJS = $(TEST_CPP_BINS:$(EXE)=.o) +SH_OBJS = $(OBJS:.o=.sho) +SHPP_OBJS = $(CPP_OBJS:.o=.sho++) diff --git a/makefiles/gmake/depend.mk b/makefiles/gmake/depend.mk new file mode 100644 index 0000000..eb832e7 --- /dev/null +++ b/makefiles/gmake/depend.mk @@ -0,0 +1,76 @@ +# provides generic rules for C/C++ dependeny generation using +# 'makedepend', 'gcc -MM' or similar mechanisms +# +# requires: +# - compilers CC and CCPP +# - INCLUDEDIRS +# - OBJS, CPP_OBJS and BIN_OBJS, CPP_BIN_OBJS +# - TEST_BINS, TEST_BIN_OBJS, TEST_CPP_BINS, TEST_CPP_BIN_OBJS +# +# provides: +# - included dependency files +# +# author: Andreas Baumann, abaumann at yahoo dot com + +ifeq "$(COMPILER)" "gcc" + +%.d : %.c + @echo Generating dependencies for $< + @$(CC) -DMAKE_DEPENDENCIES -MM -MT $(@:.d=.o) $(CFLAGS) $< | \ + sed "s,\($*\.o\)[ :]*\(.*\),$@ : $$\(wildcard \2\)\&\&\&\1 : \2,g" | tr -s '&' "\n" > $@ + +%.d : %.cpp + @echo Generating dependencies for $< + @$(CCPP) -DMAKE_DEPENDENCIES -MM -MT $(@:.d=.o) $(CCPPFLAGS) $< | \ + sed "s,\($*\.o\)[ :]*\(.*\),$@ : $$\(wildcard \2\)\&\&\&\1 : \2,g" | tr -s '&' "\n" > $@ + +endif + +ifeq "$(COMPILER)" "tcc" + +%.d : %.c + @echo Generating dependencies for $< + @makedepend -DMAKE_DEPENDENCIES $(PLATFORM_COMPILE_FLAGS) $(INCLUDE_DIRS) -I/usr/lib/tcc/include -f - $< > $@ + +endif + +ifeq "$(COMPILER)" "icc" + +%.d : %.c + @echo Generating dependencies for $< + @$(CC) -DMAKE_DEPENDENCIES -MM -MT $(@:.d=.o) $(CFLAGS) $< | \ + sed "s,\($*\.o\)[ :]*\(.*\),$@ : $$\(wildcard \2\)\&\&\&\1 : \2,g" | tr -s '&' "\n" > $@ + +%.d : %.cpp + @echo Generating dependencies for $< + @$(CCPP) -DMAKE_DEPENDENCIES -MM -MT $(@:.d=.o) $(CCPPFLAGS) $< | \ + sed "s,\($*\.o\)[ :]*\(.*\),$@ : $$\(wildcard \2\)\&\&\&\1 : \2,g" | tr -s '&' "\n" > $@ + +endif + +ifeq "$(COMPILER)" "spro" + +%.d : %.c + @echo Generating dependencies for $< + @$(CC) -DMAKE_DEPENDENCIES -xM1 $(CFLAGS) $< > $@ + +%.d : %.cpp + @echo Generating dependencies for $< + @$(CCPP) -DMAKE_DEPENDENCIES -xM1 $(CCPPFLAGS) $< > $@ +endif + +ifeq "$(COMPILER)" "pcc" + +# FIXME: platform in path of compiler include files, mmh, how to fix? +%.d : %.c + @echo Generating dependencies for $< + @$(CC) -DMAKE_DEPENDENCIES $(CFLAGS) -M $< > $@ + +endif + +-include $(OBJS:.o=.d) +-include $(CPP_OBJS:.o=.d) +-include $(BIN_OBJS:.o=.d) +-include $(CPP_BIN_OBJS:.o=.d) +-include $(TEST_BIN_OBJS:.o=.d) +-include $(TEST_CPP_BIN_OBJS:.o=.d) diff --git a/makefiles/gmake/dist.mk b/makefiles/gmake/dist.mk new file mode 100644 index 0000000..85ceae7 --- /dev/null +++ b/makefiles/gmake/dist.mk @@ -0,0 +1,40 @@ +# creates a source tarball ready for distribution +# +# requires: +# - PACKAGE_NAME +# - PACKAGE_VERSION +# +# provides: +# - target: dist +# - target: dist-bz2, dist-gz, dist-Z + +.PHONY: dist dist-bz2 dist-gz dist-Z + +dist: + -@rm -rf $(PACKAGE_NAME)-$(PACKAGE_VERSION) + -@rm -rf /tmp/$(PACKAGE_NAME)-$(PACKAGE_VERSION) + mkdir /tmp/$(PACKAGE_NAME)-$(PACKAGE_VERSION) + cp -r * /tmp/$(PACKAGE_NAME)-$(PACKAGE_VERSION)/. + -@cd /tmp/$(PACKAGE_NAME)-$(PACKAGE_VERSION) ; \ + $(MAKE) distclean ; \ + rm -f makefiles/gmake/platform.mk.vars; \ + find . -name .svn -exec rm -rf {} \; ; \ + find . -name .git -exec rm -rf {} \; ; \ + cd .. ; \ + tar cvf $(PACKAGE_NAME)-$(PACKAGE_VERSION).tar \ + $(PACKAGE_NAME)-$(PACKAGE_VERSION) + -@rm -rf /tmp/$(PACKAGE_NAME)-$(PACKAGE_VERSION) + @mv /tmp/$(PACKAGE_NAME)-$(PACKAGE_VERSION).tar . + +dist-bz2: dist + -@rm -rf $(PACKAGE_NAME)-$(PACKAGE_VERSION).bz2 + @bzip2 -f $(PACKAGE_NAME)-$(PACKAGE_VERSION).tar + +dist-gz: dist + -@rm -rf $(PACKAGE_NAME)-$(PACKAGE_VERSION).gz + @gzip $(PACKAGE_NAME)-$(PACKAGE_VERSION).tar + +dist-Z: dist + -@rm -rf $(PACKAGE_NAME)-$(PACKAGE_VERSION).Z + @compress -f $(PACKAGE_NAME)-$(PACKAGE_VERSION).tar + diff --git a/makefiles/gmake/guess_env b/makefiles/gmake/guess_env new file mode 100755 index 0000000..2e4f3de --- /dev/null +++ b/makefiles/gmake/guess_env @@ -0,0 +1,224 @@ +#!/bin/sh + +# operating system and major, minor version, more should not be necessary + +UNAME_SYSTEM=`(uname -s) 2>/dev/null` +UNAME_RELEASE=`(uname -r) 2>/dev/null` +UNAME_VERSION=`(uname -v) 2>/dev/null` +UNAME_MACHINE=`(uname -m) 2>/dev/null` + +case "$UNAME_SYSTEM.$UNAME_RELEASE" in + Linux*) PLATFORM=LINUX + OS_MAJOR_VERSION=`echo $UNAME_RELEASE | cut -d . -f 1` + OS_MINOR_VERSION=`echo $UNAME_RELEASE | cut -d . -f 2` + + if test -f /etc/arch-release; then + LINUX_DIST='arch' + LINUX_REV='current' + elif test -f /etc/debian_version; then + LINUX_DIST='debian' + LINUX_REV=`cat /etc/debian_version | cut -d . -f 1` + elif test -f /etc/slackware-version; then + LINUX_DIST='slackware' + LINUX_REV=`cat /etc/slackware-version | cut -d ' ' -f 2 | cut -d . -f 1` + elif test -f /etc/redhat-release; then + LINUX_DIST='redhat' + LINUX_REV=`cat /etc/redhat-release | sed s/.*release\ // | sed s/\ .*// | cut -f 1 -d .` + else + LINUX_DIST='unknown' + LINUX_REV='unknown' + fi + ;; + + FreeBSD*) PLATFORM=FREEBSD + OS_MAJOR_VERSION=`echo $UNAME_RELEASE | cut -d . -f 1` + OS_MINOR_VERSION=`echo $UNAME_RELEASE | cut -d . -f 2 | cut -d - -f 1` + ;; + + OpenBSD*) PLATFORM=OPENBSD + OS_MAJOR_VERSION=`echo $UNAME_RELEASE | cut -d . -f 1` + OS_MINOR_VERSION=`echo $UNAME_RELEASE | cut -d . -f 2 | cut -d - -f 1` + ;; + + NetBSD*) PLATFORM=NETBSD + OS_MAJOR_VERSION=`echo $UNAME_RELEASE | cut -d . -f 1` + OS_MINOR_VERSION=`echo $UNAME_RELEASE | cut -d . -f 2 | cut -d - -f 1` + ;; + + SunOS*) PLATFORM=SUNOS + OS_MAJOR_VERSION=`echo $UNAME_RELEASE | cut -d . -f 1` + OS_MINOR_VERSION=`echo $UNAME_RELEASE | cut -d . -f 2` + ;; + + CYGWIN_NT*) PLATFORM=CYGWIN + _tmp=`echo $UNAME_SYSTEM | cut -d - -f 2` + OS_MAJOR_VERSION=`echo $_tmp | cut -d . -f 1` + OS_MINOR_VERSION=`echo $_tmp | cut -d . -f 2` + ;; + + *) + PLATFORM=UNKNOWN + echo "Unknown platform '$UNAME_SYSTEM $UNAME_RELEASE'" + exit 1 +esac + +# the architecture + +case "$UNAME_MACHINE" in + i*86*) ARCH=x86 + ;; + x86_64) ARCH=x86_64 + ;; + sun4u) ARCH=sun4u + ;; + + *) ARCH=UNKNOWN + echo "Unknown architecture '$UNAME_MACHINE'" + exit 1 + +esac + +# get last line, old 'tail' syntax and POSIX syntax, both exist out there +if test "x${PLATFORM}" = "xSUNOS"; then + TAIL1='tail -1' +else + TAIL1='tail -n 1' +fi + +# the compiler and version + +# what compiler do we have (we can't relly on it's name as it may be a cc link to the binary!) +CC=$2 +(( $CC -v 2>&1 | $TAIL1 ) | grep -i GCC ) 2>/dev/null 1>/dev/null +if test $? = 0; then + COMPILER='gcc' +else + ( $CC -v | grep tcc ) 2>/dev/null 1>/dev/null + if test $? = 0; then + COMPILER='tcc' + else + ( $CC -V 2>&1 | grep l_cproc_p ) >/dev/null + if test $? = 0; then + COMPILER='icc' + else + ( $CC -xhelp=readme | head -n 1 | grep 'Sun Studio' ) >/dev/null + if test $? = 0; then + COMPILER='spro' + else + ( $CC -v | head -n 1 | grep 'pcc' ) >/dev/null + if test $? = 0; then + COMPILER='pcc' + else + COMPILER='unknown' + fi + fi + fi + fi +fi + +# version of gcc (GNU C compiler) + +if test $COMPILER = "gcc"; then + GCC_VERSION=`gcc -dumpversion` + GCC_MAJOR_VERSION=`echo $GCC_VERSION | cut -d . -f 1` + GCC_MINOR_VERSION=`echo $GCC_VERSION | cut -d . -f 2` +fi + +# version of tcc (Tiny C compiler) + +if test $COMPILER = "tcc"; then + TCC_VERSION=`tcc -v | cut -d ' ' -f 3` + TCC_MAJOR_VERSION=`echo $ICC_VERSION | cut -d . -f 1` + TCC_MINOR_VERSION=`echo $ICC_VERSION | cut -d . -f 2` +fi + +# version of icc (Intel C compiler) + +if test $COMPILER = "icc"; then + ICC_VERSION=`icc -dumpversion` + ICC_MAJOR_VERSION=`echo $ICC_VERSION | cut -d . -f 1` + ICC_MINOR_VERSION=`echo $ICC_VERSION | cut -d . -f 2` +fi + +# version of spro (Sun Pro compiler, Sun Studio) + +if test $COMPILER = "spro"; then + SPRO_VERSION=`$CC -xhelp=readme | head -n 1 | cut -d ' ' -f 3` + SPRO_MAJOR_VERSION=`echo $SPRO_VERSION | cut -d : -f 1` +fi + +# version of pcc (Portable C Compiler) + +if test $COMPILER = "pcc"; then + PCC_VERSION=`$CC -v | head -n 1 | cut -d ' ' -f 2` + PCC_MAJOR_VERSION=`echo $PCC_VERSION | cut -d . -f 1` + PCC_MINOR_VERSION=`echo $PCC_VERSION | cut -d . -f 2` +fi + +case "$1" in + --platform) echo $PLATFORM + ;; + + --os-major-version) echo $OS_MAJOR_VERSION + ;; + + --os-minor-version) echo $OS_MINOR_VERSION + ;; + + --arch) echo $ARCH + ;; + + --compiler) echo $COMPILER + ;; + + --gcc-major-version) echo $GCC_MAJOR_VERSION + ;; + + --gcc-minor-version) echo $GCC_MINOR_VERSION + ;; + + --tcc-major-version) echo $TCC_MAJOR_VERSION + ;; + + --tcc-minor-version) echo $TCC_MINOR_VERSION + ;; + + --icc-major-version) echo $ICC_MAJOR_VERSION + ;; + + --icc-minor-version) echo $ICC_MINOR_VERSION + ;; + + --spro-major-version) echo $SPRO_MAJOR_VERSION + ;; + + --pcc-major-version) echo $PCC_MAJOR_VERSION + ;; + + --pcc-minor-version) echo $PCC_MINOR_VERSION + ;; +esac + +MAKEFILE_DIR="$3/$4" + +# regenerate the cache file, otherwise building is far too slow! +if test ! -f "${MAKEFILE_DIR}/makefiles/gmake/platform.mk.vars"; then + cat >"${MAKEFILE_DIR}/makefiles/gmake/platform.mk.vars" </dev/null + @-rm -f po/$(CATALOG_NAME).pot 2>/dev/null + @-rm -f po/*.bak 2>/dev/null + @-rm -f po/*~ 2>/dev/null + +# hooks for the standard targets handling gettext stuff + +all_po: $(MO_FILES) + +install_po: + @test -z "$(GETTEXT_LANGUAGES)" || \ + for lang in $(GETTEXT_LANGUAGES)""; do ( \ + echo "installing po/$$lang.mo to $(localedir)/$$lang/LC_MESSAGES.." && \ + $(INSTALL) -d -m 755 $(localedir)/$$lang/LC_MESSAGES && \ + $(INSTALL) -m 644 po/$$lang.mo $(localedir)/$$lang/LC_MESSAGES/$(CATALOG_NAME).mo || exit 1 \ + ) done + +uninstall_po: + @test -z "$(GETTEXT_LANGUAGES)" || \ + for lang in $(GETTEXT_LANGUAGES)""; do ( \ + echo "uninstalling $(localedir)/$$lang/LC_MESSAGES.." && \ + rm $(localedir)/$$lang/LC_MESSAGES/$(CATALOG_NAME).mo && \ + rmdir $(localedir)/$$lang/LC_MESSAGES || exit 1 \ + ) done + +else + +# No NLS supported wanted, provide dummy targets + +init-po: +merge-po: +check-po: + +all_po: +clean_po: +install_po: +uninstall_po: + +endif diff --git a/makefiles/gmake/install.mk b/makefiles/gmake/install.mk new file mode 100644 index 0000000..ac6d49d --- /dev/null +++ b/makefiles/gmake/install.mk @@ -0,0 +1,64 @@ +# install +# +# requires: +# - DESTDIR: temporary or final destination dir for installation +# - prefix: prefix for the directory root (e.g. /usr) +# +# provides: +# - target: install +# - target: uninstall + +# default values +DESTDIR= +prefix=/usr + +# standard directories following FHS +execdir=$(DESTDIR)$(prefix) +bindir=$(execdir)/bin +sbindir=$(execdir)/sbin +libdir=$(execdir)/lib +sysconfdir=$(execdir)/etc +includedir=$(execdir)/include +datadir=$(execdir)/share +localedir=$(datadir)/locale + +.PHONY: install_recursive install local_install + +install_recursive: + @test -z "$(SUBDIRS)" || ( set -e; for d in $(SUBDIRS)""; do \ + (set -e; $(MAKE) -C $$d install || exit 1); done) + +install: install_recursive local_install install_po + @test -d "$(libdir)" || mkdir -p "$(libdir)" + @test -z "$(STATIC_LIB)" || ( \ + $(INSTALL) -m 644 $(STATIC_LIB) $(libdir)/$(STATIC_LIB) ) + @test -z "$(DYNAMIC_LIB)" || ( \ + $(INSTALL) -m 755 $(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR).$(DYNAMIC_LIB_MINOR).$(DYNAMIC_LIB_PATCH) \ + $(libdir)/$(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR).$(DYNAMIC_LIB_MINOR).$(DYNAMIC_LIB_PATCH) ) + @test -z "$(DYNAMIC_LIB)" || ( \ + rm -f "$(libdir)/$(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR)" && \ + ln -s "$(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR).$(DYNAMIC_LIB_MINOR).$(DYNAMIC_LIB_PATCH)" \ + "$(libdir)/$(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR)" ) + @test -z "$(DYNAMIC_LIB)" || ( \ + rm -f "$(libdir)/$(DYNAMIC_LIB)" && \ + ln -s "$(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR).$(DYNAMIC_LIB_MINOR).$(DYNAMIC_LIB_PATCH)" \ + "$(libdir)/$(DYNAMIC_LIB)" ) + +.PHONY: uninstall_recursive uninstall local_uninstall + +uninstall_recursive: + @test -z "$(SUBDIRS)" || ( set -e; for d in $(SUBDIRS)""; do \ + (set -e; $(MAKE) -C $$d uninstall || exit 1); done) + +uninstall: uninstall_recursive local_uninstall uninstall_po + test -z "$(DYNAMIC_LIB)" || ( \ + test ! -f "$(libdir)/$(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR).$(DYNAMIC_LIB_MINOR).$(DYNAMIC_LIB_PATCH)" || \ + rm "$(libdir)/$(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR).$(DYNAMIC_LIB_MINOR).$(DYNAMIC_LIB_PATCH)" ) + test -z "$(DYNAMIC_LIB)" || ( \ + test ! -h "$(libdir)/$(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR)" || \ + rm "$(libdir)/$(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR)" ) + test -z "$(DYNAMIC_LIB)" || ( \ + test ! -h "$(libdir)/$(DYNAMIC_LIB)" || \ + rm "$(libdir)/$(DYNAMIC_LIB)" ) + test -z "$(STATIC_LIB)" || ( \ + test ! -f "$(libdir)/$(STATIC_LIB)" || rm "$(libdir)/$(STATIC_LIB)" ) diff --git a/makefiles/gmake/libs.mk b/makefiles/gmake/libs.mk new file mode 100644 index 0000000..08899c3 --- /dev/null +++ b/makefiles/gmake/libs.mk @@ -0,0 +1,53 @@ +# provides explicit library rules +# +# requires: +# - STATIC_LIB: name of the static library +# - DYNAMIC_LIB: soname and versions of the shared library +# - all others like OBJS, CPP_OBJS, LIBS, SH_OBJS, SHPP_OBJS, LDFLAGS +# +# provides: +# - targets to build the static and dynamic version of the project's library +# + +ifeq "$(PLATFORM)" "LINUX" +SO_FLAGS = -shared -Wl,-soname,$(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR) +endif + +ifeq "$(PLATFORM)" "SUNOS" +ifeq "$(COMPILER)" "gcc" +SO_FLAGS = -shared -Wl,-h,$(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR) +endif +ifeq "$(COMPILER)" "spro" +SO_FLAGS = -G -h $(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR) +endif +endif + +ifeq "$(PLATFORM)" "FREEBSD" +SO_FLAGS = -shared -Wl,-x,-soname,$(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR) +endif + +ifeq "$(PLATFORM)" "OPENBSD" +SO_FLAGS = -shared -Wl,-soname,$(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR) +endif + +ifeq "$(PLATFORM)" "NETBSD" +SO_FLAGS = -shared -Wl,-soname,$(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR) +endif + +ifeq "$(PLATFORM)" "CYGWIN" +SO_FLAGS = -shared -Wl,-soname,$(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR) +endif + +ifneq "$(STATIC_LIB)" "" +$(STATIC_LIB) : $(OBJS) $(CPP_OBJS) + $(AR) cr $@ $(OBJS) $(CPP_OBJS) +else +$(STATIC_LIB) : +endif + +ifneq "$(DYNAMIC_LIB)" "" +$(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR).$(DYNAMIC_LIB_MINOR).$(DYNAMIC_LIB_PATCH) : $(SH_OBJS) $(SHPP_OBJS) + $(CCPP_LINK) $(SO_FLAGS) -o $@ $(LDFLAGS) $(SH_OBJS) $(SHPP_OBJS) $(LIBS) +else +$(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR).$(DYNAMIC_LIB_MINOR).$(DYNAMIC_LIB_PATCH) : +endif diff --git a/makefiles/gmake/platform.mk b/makefiles/gmake/platform.mk new file mode 100644 index 0000000..7499a1e --- /dev/null +++ b/makefiles/gmake/platform.mk @@ -0,0 +1,189 @@ +# sets e. g. to LINUX, OS_MAJOR_VERSION to 2 and OS_MINOR_VERSION to 6 +# by calling the 'guess_env' shell script, where the actual probing happens +# Also sets PLATFORM_COMPILE_FLAGS to be included when compiling C/C++ code +# +# requires: +# - TOPDIR +# +# provides: +# - PLATFORM +# - OS_MAJOR_VERSION and OS_MINOR_VERSION +# - GCC_MAJOR_VERSION and GCC_MINOR_VERSION +# - PLATFORM_COMPILE_FLAGS +# - EXE +# - SO +# - INSTALL +# - BOOST_LIBRARY_TAG +# +# author: Andreas Baumann, abaumann at yahoo dot com + +-include $(TOPDIR)/makefiles/gmake/platform.mk.vars + +PLATFORM ?= $(shell $(SHELL) $(TOPDIR)/makefiles/gmake/guess_env --platform $(CC) "$(CURDIR)" $(TOPDIR)) +OS_MAJOR_VERSION ?= $(shell $(SHELL) $(TOPDIR)/makefiles/gmake/guess_env --os-major-version $(CC) "$(CURDIR)" $(TOPDIR)) +OS_MINOR_VERSION ?= $(shell $(SHELL) $(TOPDIR)/makefiles/gmake/guess_env --os-minor-version $(CC) "$(CURDIR)" $(TOPDIR)) +COMPILER ?= $(shell $(SHELL) $(TOPDIR)/makefiles/gmake/guess_env --compiler $(CC) "$(CURDIR)" $(TOPDIR)) +ifeq "$(PLATFORM)" "LINUX" +LINUX_DIST ?= $(shell $(SHELL) $(TOPDIR)/makefiles/gmake/guess_env --linux-dist $(CC) "$(CURDIR)" $(TOPDIR)) +LINUX_REV ?= $(shell $(SHELL) $(TOPDIR)/makefiles/gmake/guess_env --linux-rev $(CC) "$(CURDIR)" $(TOPDIR)) +endif + +# platform specific flags +######################### + +PLATFORM_COMPILE_FLAGS = \ + -D$(PLATFORM) \ + -DOS_MAJOR_VERSION=$(OS_MAJOR_VERSION) \ + -DOS_MINOR_VERSION=$(OS_MINOR_VERSION) + +ifeq "$(PLATFORM)" "LINUX" +PLATFORM_COMPILE_FLAGS += \ + -DLINUX_DIST=$(LINUX_DIST) -DLINUX_REV=$(LINUX_REV) +endif + +# extensions for binaries +ifeq "$(PLATFORM)" "CYGWIN" +EXE = .exe +else +EXE = +endif + +# extensions for shared libraries +# (TOOD: HP/Unix has .shlib, Mac/X has .lib, but we can't test it currently) +SO = .so + +# name if the installation program +# (TODO: use the MIT or openradio install-sh script instead?) +INSTALL = $(shell $(SHELL) $(TOPDIR)/makefiles/gmake/guess_env --install) +ifeq "$(PLATFORM)" "SUNOS" +INSTALL = /usr/ucb/install +else +INSTALL = install +endif + +# dynamic linker +################ + +# the linker library for dynamically loadable modules +# (TODO: check for all platforms, as soon we add loadable modules here from +# old TextWolf) +ifeq "$(PLATFORM)" "LINUX" +LIBS_DL = -ldl +else +LIBS_DL = +endif + +# i18n, gettext/libintl +####################### + +# enable or disable internationalization code +ENABLE_NLS = 1 + +ifeq "$(ENABLE_NLS)" "1" + +# we relly only on the GNU version, other versions (e.g. Solaris) are not +# so nice.. + +MSGFMT=msgfmt +MSGMERGE=msgmerge +XGETTEXT=xgettext + +# the GNU internationalization support is sometimes in separate libarries +ifeq "$(PLATFORM)" "LINUX" +INCLUDE_FLAGS_LT = +LDFLAGS_LT = +LIBS_LT = +endif + +ifeq "$(PLATFORM)" "SUNOS" +INCLUDE_FLAGS_LT = -I/usr/local/include +LDFLAGS_LT = -L/usr/local/lib +LIBS_LT = -lintl +endif + +ifeq "$(PLATFORM)" "FREEBSD" +INCLUDE_FLAGS_LT = -I/usr/local/include +LDFLAGS_LT = -L/usr/local/lib +LIBS_LT = -lintl +endif + +ifeq "$(PLATFORM)" "OPENBSD" +INCLUDE_FLAGS_LT = -I/usr/local/include +LDFLAGS_LT = -L/usr/local/lib +LIBS_LT = -lintl -liconv +endif + +ifeq "$(PLATFORM)" "CYGWIN" +INCLUDE_FLAGS_LT = +LDFLAGS_LT = +LIBS_LT = -lintl +endif + +ifeq "$(PLATFORM)" "NETBSD" +INCLUDE_FLAGS_LT = +LDFLAGS_LT = +LIBS_LT = -lintl +endif + +PLATFORM_COMPILE_FLAGS += $(INCLUDE_FLAGS_LT) + +endif + +PLATFORM_COMPILE_FLAGS += \ + -DENABLE_NLS=$(ENABLE_NLS) -DLOCALEDIR=\"$(localedir)\" + +# TCP/IP, DNS +############# + +ifeq "$(PLATFORM)" "LINUX" +INCLUDE_FLAGS_NET = +LDFLAGS_NET = +LIBS_NET = +endif + +ifeq "$(PLATFORM)" "SUNOS" +INCLUDE_FLAGS_NET = +LDFLAGS_NET = +LIBS_NET = -lsocket -lnsl +endif + +ifeq "$(PLATFORM)" "FREEBSD" +INCLUDE_FLAGS_NET = +LDFLAGS_NET = +LIBS_NET = +endif + +ifeq "$(PLATFORM)" "OPENBSD" +INCLUDE_FLAGS_NET = +LDFLAGS_NET = +LIBS_NET = +endif + +ifeq "$(PLATFORM)" "CYGWIN" +INCLUDE_FLAGS_NET = +LDFLAGS_NET = +LIBS_NET = +endif + +ifeq "$(PLATFORM)" "NETBSD" +INCLUDE_FLAGS_NET = +LDFLAGS_NET = +LIBS_NET = +endif + +PLATFORM_COMPILE_FLAGS += $(INCLUDE_FLAGS_NET) + +# XSLT processor +################ + +XSLTPROC = xsltproc + +# Boost +####### + +ifeq "$(PLATFORM)" "LINUX" +ifeq "$(LINUX_DIST)" "arch" +BOOST_DIR = /usr +BOOST_LIBRARY_TAG = "-mt" +endif +endif diff --git a/makefiles/gmake/platform.mk.vars b/makefiles/gmake/platform.mk.vars new file mode 100644 index 0000000..348ca3b --- /dev/null +++ b/makefiles/gmake/platform.mk.vars @@ -0,0 +1,16 @@ +ARCH=x86 +PLATFORM=LINUX +OS_MAJOR_VERSION=2 +OS_MINOR_VERSION=6 +COMPILER=gcc +GCC_MAJOR_VERSION=4 +GCC_MINOR_VERSION=5 +TCC_MAJOR_VERSION= +TCC_MINOR_VERSION= +ICC_MAJOR_VERSION= +ICC_MINOR_VERSION= +SPRO_MAJOR_VERSION= +PCC_MAJOR_VERSION= +PCC_MINOR_VERSION= +LINUX_DIST=arch +LINUX_REV=current diff --git a/makefiles/gmake/sub.mk b/makefiles/gmake/sub.mk new file mode 100644 index 0000000..962c63f --- /dev/null +++ b/makefiles/gmake/sub.mk @@ -0,0 +1,28 @@ +# makefile for a sub package +# +# requires: +# - TOPDIR +# - SUBDIRS +# - INCLUDE_DIRS +# +# provides: +# - target: all targets + +-include $(TOPDIR)/makefiles/gmake/platform.mk +-include $(TOPDIR)/makefiles/gmake/compiler.mk + +.PHONY: all $(SUBDIRS) local_all +all: $(OBJS) $(CPPOBJS) $(BIN_OBJS) $(CPP_BIN_OBJS) $(BINS) $(CPP_BINS) $(CMODULES) $(CPPMODULES) $(STATIC_LIB) $(DYNAMIC_LIB).$(DYNAMIC_LIB_MAJOR).$(DYNAMIC_LIB_MINOR).$(DYNAMIC_LIB_PATCH) local_all all_po + @test -z "$(SUBDIRS)" || ( set -e; for d in $(SUBDIRS)""; do \ + (set -e; $(MAKE) -C $$d all || exit 1); done) + +.PHONY: test local_test +test: $(OBJS) $(TEST_OBJS) $(CPPOBJS) $(BIN_OBJS) $(BINS) $(CPP_BINS) $(TEST_BIN_OBJS) $(TEST_BINS) $(TEST_CPP_BINS) $(CMODULES) $(CPPMODULES) $(STATIC_LIB) local_test + @test -z "$(SUBDIRS)" || ( set -e; for d in $(SUBDIRS)""; do \ + (set -e; $(MAKE) -C $$d test || exit 1); done) + +-include $(TOPDIR)/makefiles/gmake/depend.mk +-include $(TOPDIR)/makefiles/gmake/clean.mk +-include $(TOPDIR)/makefiles/gmake/install.mk +-include $(TOPDIR)/makefiles/gmake/i18n.mk +-include $(TOPDIR)/makefiles/gmake/libs.mk diff --git a/makefiles/gmake/top.mk b/makefiles/gmake/top.mk new file mode 100644 index 0000000..810bedc --- /dev/null +++ b/makefiles/gmake/top.mk @@ -0,0 +1,74 @@ +# top-level makefile for a package +# +# requires: +# - TOPDIR +# - SUBDIRS +# +# provides: +# - target 'all' +# - target 'clean' +# - target 'distclean' +# - target 'test' +# - target 'doc' +# - target 'dist' +# - target 'help' +# - target 'install' +# - target 'uninstall' + +-include makefiles/gmake/platform.mk + +.PHONY: all +all: + @test -z "$(SUBDIRS)" || ( set -e; for d in $(SUBDIRS)""; do \ + (set -e; $(MAKE) -C $$d all || exit 1); done) + +.PHONY: clean +clean: + @test -z "$(SUBDIRS)" || ( set -e; for d in $(SUBDIRS)""; do \ + (set -e; $(MAKE) -C $$d clean || exit 1); done) + @-rm $(TOPDIR)/makefiles/gmake/platform.mk.vars + +.PHONY: distclean +distclean: + @test -z "$(SUBDIRS)" || ( set -e; for d in $(SUBDIRS)""; do \ + (set -e; $(MAKE) -C $$d distclean || exit 1); done) + @-rm $(TOPDIR)/makefiles/gmake/platform.mk.vars + +.PHONY: install +install: + @test -z "$(SUBDIRS)" || ( set -e; for d in $(SUBDIRS)""; do \ + (set -e; $(MAKE) -C $$d install || exit 1); done) + +.PHONY: uninstall +uninstall: + @test -z "$(SUBDIRS)" || ( set -e; for d in $(SUBDIRS)""; do \ + (set -e; $(MAKE) -C $$d uninstall || exit 1); done) + +.PHONY: test +test: all + @$(MAKE) -C tests test + +.PHONY: doc +doc: + cd docs; $(MAKE) doc + +.PHONY: help +help: + @cat $(TOPDIR)/makefiles/gmake/help.mk + +.PHONY: init-po +init-po: + @test -z "$(SUBDIRS)" || ( set -e; for d in $(SUBDIRS)""; do \ + (set -e; $(MAKE) -C $$d init-po || exit 1); done) + +.PHONY: merge-po +merge-po: + @test -z "$(SUBDIRS)" || ( set -e; for d in $(SUBDIRS)""; do \ + (set -e; $(MAKE) -C $$d merge-po || exit 1); done) + +.PHONY: check-po +check-po: + @test -z "$(SUBDIRS)" || ( set -e; for d in $(SUBDIRS)""; do \ + (set -e; $(MAKE) -C $$d check-po || exit 1); done) + +-include $(TOPDIR)/makefiles/gmake/dist.mk diff --git a/makefiles/nmake/clean.mk b/makefiles/nmake/clean.mk new file mode 100644 index 0000000..91d941b --- /dev/null +++ b/makefiles/nmake/clean.mk @@ -0,0 +1,48 @@ +# cleans up directories +# +# requires: +# - SUBDIRS: for recursive cleaning +# - local_clean, local_distclean targets in local GNUmakefile +# - all artifacts to clean: +# - BINS, TEST_BINS, TEST_CPP_BINS, CPP_BINS +# - OBJS, CPPOBJS, BIN_OBJS, TEST_BIN_OBJS, CPP_BIN_OBJS, TEST_CPP_BIN_OBJS +# - CMODULES, CPPMODULES +# +# provides: +# - target: clean +# - target: distclean + +clean_recursive: + @if not "$(SUBDIRS)" == "" @for %%d IN ( $(SUBDIRS) ) do @cd %%d & $(MAKE) /nologo /f Makefile.w32 clean & cd .. + +#clean: clean_recursive local_clean +# -@rm -f *.d port/*.d 2>/dev/null +# -@rm -f $(BINS) $(CPP_BINS) $(TEST_BINS) $(TEST_CPP_BINS) 2>/dev/null +# -@rm -f $(OBJS) $(CPP_OBJS) $(BIN_OBJS) $(TEST_BIN_OBJS) $(CPP_BIN_OBJS) $(TEST_CPP_BIN_OBJS) 2>/dev/null +# -@rm -f exec/* +# -@rm -f *.core +# -@rm -f $(CMODULES) $(CPPMODULES) +# -@rm -f $(CMODULES .o=.d) $(CPPMODULES .o=.d) +clean: clean_recursive local_clean + -@erase *.bak 2>NUL + -@erase *~ 2>NUL + -@erase *.d 2>NUL + -@erase *.exe 2>NUL + -@erase *.exe.manifest 2>NUL + -@erase *.obj 2>NUL + -@erase $(OBJS) 2>NUL + -@erase *.pdb 2>NUL + -@erase *.rc 2>NUL + -@erase *.res 2>NUL + -@erase MSG*.bin 2>NUL + -@erase *.dllobj 2>NUL + -@erase $(DLL_OBJS) 2>NUL + -@erase *.exp 2>NUL + -@erase *.ilk 2>NUL + -@erase *.idb 2>NUL + -@erase *.manifest 2>NUL + +distclean_recursive: + @if not "$(SUBDIRS)" == "" @for %%d IN ( $(SUBDIRS) ) do @cd %%d & $(MAKE) /nologo /f Makefile.w32 distclean & cd .. + +distclean: distclean_recursive local_distclean clean diff --git a/makefiles/nmake/compiler.mk b/makefiles/nmake/compiler.mk new file mode 100644 index 0000000..2cfcb17 --- /dev/null +++ b/makefiles/nmake/compiler.mk @@ -0,0 +1,92 @@ +# sets compiler settings +# +# requires: +# - INCLUDE_DIRS +# +# provides: +# - BIN_OBJS: the object files we need for the binaries which we build always +# - CPP_BIN_OBJS: same for binaries which have C++ code in them +# - TEST_BIN_OBJS: same as BIN_OBJS but for test binaries compiled only when +# testing +# - TEST_CPP_BIN_OBJS: same for C++ tests +# + +# TODO: which flags to enable? +# /nologo: disable MS disclaimer +# /MT: create a multi-thread binary +# /EHsc: enable C++ exception handling +# /Ox: optimize what you can +# /Zi: enable debug information +# /MTD: create multi-threaded debug binary +# /we: show warnings (level 1 to 4) +# /Wall: enable all warnings + +# compilation flags and compilers (release) +COMMON_COMPILE_FLAGS = /MD /nologo /O2 /c $(INCLUDE_DIRS) + +# compilation flags and compilers (debug) +#COMMON_COMPILE_FLAGS = /MDd /ZI /nologo /c $(INCLUDE_DIRS) /RTC1 + +COMPILE_FLAGS = $(COMMON_COMPILE_FLAGS) + +CCPP_COMPILE_FLAGS = $(COMMON_COMPILE_FLAGS) /EHsc + +CFLAGS = $(COMPILE_FLAGS) $(PLATFORM_COMPILE_FLAGS) $(DEBUGLEVELFLAGS) +CCPPFLAGS = $(CCPP_COMPILE_FLAGS) $(PLATFORM_COMPILE_FLAGS) $(DEBUGLEVELFLAGS) +CC = cl.exe +CCPP = cl.exe +MC = "$(PLATFORM_SDK_DIR)\Bin\mc.exe" +RC = "$(PLATFORM_SDK_DIR)\Bin\rc.exe" + +# linking flags (release) +LDFLAGS = /nologo $(INCLUDE_LDFLAGS) + +# linking flags (debug) +#LDFLAGS = /nologo /debug $(INCLUDE_LDFLAGS) + +LIBS = $(INCLUDE_LIBS) +LINK = link.exe +CCPP_LINK = link.exe + +.SUFFIXES: .c .cpp .obj .exe .mc .rc .res + +.c.obj: + $(CC) $(CFLAGS) /Fo$@ $< + +.cpp.obj: + $(CCPP) $(CCPPFLAGS) /Fo$@ $< + +.c.dllobj: + $(CC) $(CFLAGS) /D "BUILD_SHARED" /Fo$@ $< + +.cpp.dllobj: + $(CCPP) $(CCPPFLAGS) /D "BUILD_SHARED" /Fo$@ $< + +.obj.exe: + $(CCPP_LINK) $(LDFLAGS) $(LIBS) /out:$@ $< $(OBJS) + +.mc.rc: + $(MC) -h $(@D) -r $(@D) $< + +.rc.res: + $(RC) $< + +#%$(EXE): %.o $(OBJS) $(TEST_OBJS) +# $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(TEST_OBJS) $< $(LIBS) + +#%.sho : %.c +# $(CC) -c -o $@ -fPIC -DSHARED $(CFLAGS) $< + +#%$(SO) : %.sho $(OBJS) +# $(LINK) -shared -o $@ $(LDFLAGS) $(LIBS) $(OBJS) $< + +#%.sho++ : %.cpp +# $(CCPP) -c -o $@ -fPIC -DSHARED $(CCPPFLAGS) $< + +#%$(SO) : %.sho++ $(OBJS) $(CPPOBJS) +# $(CCPP_LINK) -shared -o $@ $(LDFLAGS) $(LIBS) $(OBJS) $(CPPOBJS) $< + +#BIN_OBJS = $(BINS:$(EXE)=.o) +#TEST_BIN_OBJS = $(TEST_BINS:$(EXE)=.o) +#CPP_BIN_OBJS = $(CPP_BINS:$(EXE)=.o) +#TEST_CPP_BIN_OBJS = $(TEST_CPP_BINS:$(EXE)=.o) diff --git a/makefiles/nmake/config.mk b/makefiles/nmake/config.mk new file mode 100644 index 0000000..3dcdef4 --- /dev/null +++ b/makefiles/nmake/config.mk @@ -0,0 +1,44 @@ +# Configuration supposed to be configured here by the user +# +# provides: +# - PLATFORM_SDK_DIR +# - BOOST_DIR +# - OPENSSL_DIR + +# please customize + +# Windows Platform SDK +###################### + +# The location of the Windows Platform SDK +# newer versions of Visual Studio integrate the header files of the SDK +# some versions of Visual Studio miss the mc.exe binary + +PLATFORM_SDK_DIR = C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2 +#PLATFORM_SDK_DIR = C:\Programme\Microsoft Platform SDK for Windows Server 2003 R2 + +# Boost (http://www.boostpro.com/download) +########################################### + +# version of the boost library + +BOOST_VERSION=1_42 + +# base dir where boost is installed + +BOOST_DIR=C:\Program Files\boost\boost_$(BOOST_VERSION) +#BOOST_DIR=C:\Programme\boost\boost_$(BOOST_VERSION) + +# visual studio version used for compiling + +BOOST_VC_VER=vc90 +#BOOST_VC_VER=vc80 + +# TODO: probe those +BOOST_MT=-mt + +# OpenSSL (http://www.slproweb.com/products/Win32OpenSSL.html) +############################################################## + +OPENSSL_DIR=C:\Program Files\OpenSSL +#OPENSSL_DIR=C:\Programme\OpenSSL diff --git a/makefiles/nmake/depend.mk b/makefiles/nmake/depend.mk new file mode 100644 index 0000000..bcdb5b2 --- /dev/null +++ b/makefiles/nmake/depend.mk @@ -0,0 +1,67 @@ +# provides generic rules for C/C++ dependeny generation using +# 'makedepend', 'gcc -MM' or similar mechanisms +# +# requires: +# - compilers CC and CCPP +# - INCLUDEDIRS +# - OBJS, CPP_OBJS and BIN_OBJS, CPP_BIN_OBJS +# - TEST_BINS, TEST_BIN_OBJS, TEST_CPP_BINS, TEST_CPP_BIN_OBJS +# +# provides: +# - included dependency files +# +# author: Andreas Baumann, abaumann at yahoo dot com + +ifeq "$(COMPILER)" "gcc" + +%.d : %.c + @echo Generating dependencies for $< + @$(CC) -DMAKE_DEPENDENCIES -MM -MT $@ $(CFLAGS) $< | \ + sed "s,\($*\.o\)[ :]*\(.*\),$@ : $$\(wildcard \2\)\&\&\&\1 : \2,g" | tr -s '&' "\n" > $@ + +%.d : %.cpp + @echo Generating dependencies for $< + @$(CCPP) -DMAKE_DEPENDENCIES -MM -MT $@ $(CCPPFLAGS) $< | \ + sed "s,\($*\.o\)[ :]*\(.*\),$@ : $$\(wildcard \2\)\&\&\&\1 : \2,g" | tr -s '&' "\n" > $@ + +endif + +ifeq "$(COMPILER)" "tcc" + +%.d : %.c + @echo Generating dependencies for $< + @makedepend -DMAKE_DEPENDENCIES $(INCLUDE_DIRS) -I/usr/lib/tcc/include -f - $< > $@ + +endif + +ifeq "$(COMPILER)" "icc" + +%.d : %.c + @echo Generating dependencies for $< + @$(CC) -DMAKE_DEPENDENCIES -MM -MT $@ $(CFLAGS) $< | \ + sed "s,\($*\.o\)[ :]*\(.*\),$@ : $$\(wildcard \2\)\&\&\&\1 : \2,g" | tr -s '&' "\n" > $@ + +%.d : %.cpp + @echo Generating dependencies for $< + @$(CCPP) -DMAKE_DEPENDENCIES -MM -MT $@ $(CCPPFLAGS) $< | \ + sed "s,\($*\.o\)[ :]*\(.*\),$@ : $$\(wildcard \2\)\&\&\&\1 : \2,g" | tr -s '&' "\n" > $@ + +endif + +ifeq "$(COMPILER)" "spro" + +%.d : %.c + @echo Generating dependencies for $< + @$(CC) -DMAKE_DEPENDENCIES -xM1 $(INCLUDE_DIRS) $< > $@ + +%.d : %.cpp + @echo Generating dependencies for $< + @$(CCPP) -DMAKE_DEPENDENCIES -xM1 $(INCLUDE_DIRS) $< > $@ +endif + +-include $(OBJS:.o=.d) +-include $(CPP_OBJS:.o=.d) +-include $(BIN_OBJS:.o=.d) +-include $(CPP_BIN_OBJS:.o=.d) +-include $(TEST_BIN_OBJS:.o=.d) +-include $(TEST_CPP_BIN_OBJS:.o=.d) diff --git a/makefiles/nmake/help.mk b/makefiles/nmake/help.mk new file mode 100644 index 0000000..3e42448 --- /dev/null +++ b/makefiles/nmake/help.mk @@ -0,0 +1,9 @@ + +Available targets: + +make [all] create all artifacts +make test create test binaries and execute tests +make doc build the documentation +make clean clean up build artifacts +make distclean clean up all generated artifacts +make help show this very help page diff --git a/makefiles/nmake/platform.mk b/makefiles/nmake/platform.mk new file mode 100644 index 0000000..bdc9c2f --- /dev/null +++ b/makefiles/nmake/platform.mk @@ -0,0 +1,28 @@ +# Sets Windows specific variables +# +# provides: +# - BOOST_LIBRARY_TAG: how libraries are auto-tagged, for example +# libboost_log-vc90-mt-1_42 +# +# author: Andreas Baumann, abaumann at yahoo dot com + +!include $(TOPDIR)\makefiles\nmake\config.mk + +# TODO: maybe we have to probe certain things like the version +# of the visual studio or the availability of certain addons +# like Windows Unix Services, MOSS stuff or SDKs + +#PLATFORM = $(shell $(TOPDIR)/makefiles/gmake/guess_env --platform $(CC)) +#OS_MAJOR_VERSION = $(shell $(TOPDIR)/makefiles/gmake/guess_env --os-major-version $(CC)) +#OS_MINOR_VERSION = $(shell $(TOPDIR)/makefiles/gmake/guess_env --os-minor-version $(CC)) +#COMPILER = $(shell $(TOPDIR)/makefiles/gmake/guess_env --compiler $(CC)) + +#PLATFORM_COMPILE_FLAGS = \ +# -D$(PLATFORM) \ +# -DOS_MAJOR_VERSION=$(OS_MAJOR_VERSION) \ +# -DOS_MINOR_VERSION=$(OS_MINOR_VERSION) + +# Boost +####### + +BOOST_LIBRARY_TAG=-$(BOOST_VC_VER)$(BOOST_MT)-$(BOOST_VERSION) diff --git a/makefiles/nmake/sub.mk b/makefiles/nmake/sub.mk new file mode 100644 index 0000000..f300e9b --- /dev/null +++ b/makefiles/nmake/sub.mk @@ -0,0 +1,27 @@ +# makefile for a sub package +# +# requires: +# - TOPDIR +# - SUBDIRS +# - INCLUDE_DIRS +# +# provides: +# - target: all targets + +!include $(TOPDIR)\makefiles\nmake\platform.mk +!include $(TOPDIR)\makefiles\nmake\compiler.mk + +all: local_all + @if not "$(SUBDIRS)" == "" @for %%d IN ( $(SUBDIRS) ) do @cd %%d & $(MAKE) /nologo /f Makefile.w32 all & cd .. + +#.PHONY: all $(SUBDIRS) local_all +#all: $(OBJS) $(CPPOBJS) $(BIN_OBJS) $(CPP_BIN_OBJS) $(BINS) $(CPP_BINS) $(CMODULES) $(CPPMODULES) local_all +# @test -z "$(SUBDIRS)" || ( set -e; for d in $(SUBDIRS)""; do \ +# (set -e; $(MAKE) -C $$d all || exit 1); done) + +test: $(OBJS) $(TEST_OBJS) $(CPPOBJS) $(BIN_OBJS) $(BINS) $(CPP_BINS) $(TEST_BIN_OBJS) $(TEST_BINS) $(TEST_CPP_BINS) $(CMODULES) $(CPPMODULES) local_test + @if not "$(SUBDIRS)" == "" @for %%d IN ( $(SUBDIRS) ) do @cd %%d & $(MAKE) /nologo /f Makefile.w32 test & cd .. + +#-include $(TOPDIR)/makefiles/gmake/depend.mk +!include $(TOPDIR)\makefiles\nmake\clean.mk +#-include $(TOPDIR)/makefiles/gmake/install.mk diff --git a/makefiles/nmake/top.mk b/makefiles/nmake/top.mk new file mode 100644 index 0000000..188375a --- /dev/null +++ b/makefiles/nmake/top.mk @@ -0,0 +1,39 @@ +# top-level makefile for a package +# +# requires: +# - TOPDIR +# - SUBDIRS +# +# provides: +# - target 'all' +# - target 'clean' +# - target 'distclean' +# - target 'test' +# - target 'doc' +# - target 'dist' +# - target 'help' + +all: + @if not "$(SUBDIRS)" == "" @for %%d IN ( $(SUBDIRS) ) do @cd %%d & $(MAKE) /nologo /f Makefile.w32 all & cd .. + +clean: + @if not "$(SUBDIRS)" == "" @for %%d IN ( $(SUBDIRS) ) do @cd %%d & $(MAKE) /nologo /f Makefile.w32 clean & cd .. + +distclean: + @if not "$(SUBDIRS)" == "" @for %%d IN ( $(SUBDIRS) ) do @cd %%d & $(MAKE) /nologo /f Makefile.w32 distclean & cd .. + +#.PHONY: install +#install: +# @test -z "$(SUBDIRS)" || ( set -e; for d in $(SUBDIRS)""; do \ +# (set -e; $(MAKE) -C $$d install || exit 1); done) + +test: all + @cd tests & $(MAKE) /nologo /f Makefile.W32 test + +doc: + @cd docs & $(MAKE) /nologo /f Makefile.W32 doc + +help: + @type makefiles\nmake\help.mk + +#-include $(TOPDIR)/makefiles/gmake/dist.mk diff --git a/src/GNUmakefile b/src/GNUmakefile new file mode 100644 index 0000000..55d0e3b --- /dev/null +++ b/src/GNUmakefile @@ -0,0 +1,68 @@ +TOPDIR = .. + +SUBDIRS = + +INCLUDE_CPPFLAGS = \ + -DBOOST_LOG_USE_NATIVE_SYSLOG + +INCLUDE_LDFLAGS = \ + -L$(TOPDIR)/libs/boost/log + +INCLUDE_DIRS = -I. \ + -I$(TOPDIR)/include -I$(TOPDIR) + +-include $(TOPDIR)/makefiles/gmake/platform.mk + +INCLUDE_LIBS = \ + -lboost_thread$(BOOST_LIBRARY_TAG) -lboost_system \ + -lboost_program_options \ + -lboost_filesystem \ + -lboost_log -lboost_log_setup \ + -lssl + +CPP_BINS = \ + smerpd$(EXE) + +STATIC_LIB = \ + +STATIC_LIB_OBJS = \ + +C_PORT_OBJS = \ + +OBJS = \ + $(C_PORT_OBJS) \ + $(STATIC_LIB_OBJS) \ + version.o \ + appInstance.o \ + commandLine.o \ + logLevel.o \ + logSyslogFacility.o \ + logger.o \ + configFile.o \ + appConfig.o \ + request.o \ + reply.o \ + server.o \ + connection.o \ + getPassword.o \ + requestHandler.o \ + posixMain.o + +CPP_BINS = \ + smerpd$(EXE) + +-include $(TOPDIR)/makefiles/gmake/sub.mk + +local_all: $(CPP_BINS) + +$(STATIC_LIBS): $(STATIC_LIBS_OBJS) + ar rcs $(STATIC_LIBS) $(STATIC_LIB_OBJS) + +local_clean: + @rm -f $(STATIC_LIBS) + +local_distclean: + +local_install: + $(INSTALL) -d -m 755 $(bindir) + $(INSTALL) -m 644 $(CPP_BINS) $(bindir) diff --git a/tvision/INSTALL.txt b/tvision/INSTALL.txt new file mode 100644 index 0000000..2557896 --- /dev/null +++ b/tvision/INSTALL.txt @@ -0,0 +1,22 @@ + Read this file to know how to install from sources. + + The package have an unified methode to compile for all the available +platforms. But even with it I give separated instructions for each target. + + Here are the files that describes how to compile for each target: + [alphabetically sorted] + +Borland C++ (5.5, 5.6) doc/install/bcc.txt +CygWin doc/install/cygwin.txt +DJGPP (2.02, 2.03) doc/install/djgpp.txt +Linux doc/install/linux.txt +Microsoft Visual C (5.0, 6.0, 7.0) doc/install/msvc.txt +MingWin doc/install/mingwin.txt +Open Watcom (1.3) doc/install/watcom.txt +UNIX (POSIX) systems doc/install/unix.txt + + Important: If you want to contribute to this project you can help me to +keep any of these targets working. You just need to get the CVS changes +periodically compile and tell me if it worked or not. + +$Id: INSTALL.txt,v 2.3 2005/09/20 14:48:37 set Exp $ diff --git a/tvision/Makefile.bcc b/tvision/Makefile.bcc new file mode 100644 index 0000000..04acd6a --- /dev/null +++ b/tvision/Makefile.bcc @@ -0,0 +1,36 @@ +#!/usr/bin/make +# +# Copyright (c) 2003-2005 by Salvador E. Tropea +# Covered by the GPL license. +# +# That's the makefile for Borland C++ compiler. +# Also used by MSVC (nmake) and Open Watcom (wmake). +# I used BC++ 5.5 free command line tools for testing. +# + +!ifdef FOR_NMAKE +MKF_EXT=.nmk +MAKE=nmake +!else ifdef FOR_OW +MKF_EXT=.wat +MAKE=wmake -ms +ExLIB=.dll +!else +MKF_EXT=.bmk +!endif + +# +# Main targets +# +all: makes\librhtv$(ExLIB) $(EXTRA_TARGETS) + +makes\librhtv$(ExLIB): + -cd makes + $(MAKE) MKF_EXT="$(MKF_EXT)" DEBUG="$(DEBUG)" EXTRA_TARGETS="$(EXTRA_TARGETS)" -f librhtv.bmk all + -cd .. + +clean: + -del makes\obj\*.obj + -del makes\*.lib + -del makes\*$(ExLIB) + diff --git a/tvision/Makefile.in b/tvision/Makefile.in new file mode 100644 index 0000000..1d59290 --- /dev/null +++ b/tvision/Makefile.in @@ -0,0 +1,56 @@ +#!/usr/bin/make +# +# Copyright (c) 2003-2004 by Salvador E. Tropea. +# Covered by the GPL license. +# +ifeq ($(prefix),) + prefix=@prefix@ +endif +ifeq ($(INSTALL),) + INSTALL=@install@ +endif +EXE_EXT=@exe_ext@ +libdir=$(prefix)/lib +OS=@OS@ +@maintainer_mode@ +@darwin@ +export + +.PHONY: @targets@ @installers@ install-headers install-config clean \ + intl-dummy examples + +all: @targets@ intl-dummy + +@maintainance_rule@ + +@target_rules@ + +@intl_dummy_rule@ + +examples: + $(MAKE) -C examples + +rhtv-config$(EXE_EXT): rhtv-config.c include/tv/configtv.h + @GCC@ -o rhtv-config$(EXE_EXT) -Iinclude rhtv-config.c + +install-headers: + @install_headers@ + +@install_rules@ + +@intl_dummy_install_rule@ + +install-config: + @install_config@ + +install: @installers@ install-headers install-intl-dummy install-config + +@clean@ + +# +# For compatibility with automake: +# needed to 'make dist' of tiger +# +distdir: clean + @cp -pR * $(distdir) + diff --git a/tvision/Makefile.nmk b/tvision/Makefile.nmk new file mode 100644 index 0000000..f8db22e --- /dev/null +++ b/tvision/Makefile.nmk @@ -0,0 +1,16 @@ +#!/usr/bin/make +# +# Copyright (c) 2003-2004 by Salvador E. Tropea +# Covered by the GPL license. +# +# That's the makefile for MSVC compiler. +# +# This file reuses the Makefile.bcc file but defining FOR_NMAKE variable to +# select Microsoft tools. +# + +FOR_NMAKE=1 +# Uncomment to generate code with debug information. +#DEBUG=1 +!include Makefile.bcc + diff --git a/tvision/Makefile.wat b/tvision/Makefile.wat new file mode 100644 index 0000000..3b94037 --- /dev/null +++ b/tvision/Makefile.wat @@ -0,0 +1,25 @@ +#!/usr/bin/make +# +# Copyright (c) 2005 by Salvador E. Tropea +# Covered by the GPL license. +# +# That's the makefile for MSVC compiler. +# +# This file reuses the Makefile.bcc file but defining FOR_OW variable to +# select Open Watcom tools. +# +# wmake -f Makefile.wat +# + +FOR_OW=1 +# Uncomment to generate code with debug information. +DEBUG=1 +EXTRA_TARGETS=makes\librhtv.lib +!include Makefile.bcc + +# Import library: +makes\librhtv.lib: makes\librhtv$(ExLIB) + -cd makes + wlib -q -n -b librhtv.lib +librhtv.dll + -cd .. + diff --git a/tvision/THANKS b/tvision/THANKS new file mode 100644 index 0000000..d5eefa0 --- /dev/null +++ b/tvision/THANKS @@ -0,0 +1,53 @@ +Excluding Robert and me (SET) the following people contributed valuable things +to the project. +If I omitted somebody please e-mail me! The list is sorted alphabetically. + +Alex Lozano: Solaris beta testing. + +Anatoli Soltan: BC++ and WinNT code. + +Andrey `Onyx' Shevtsov (miniEleph): A lot of help and testing for the FreeBSD +port. + +Andris Pavenis: Many patches and help to support the last releases of gcc. + +Dominique (Anamorphose): RPM packages (v1.1.4) and newer Red Hat 7.2 +packages. + +Ivan Baldo: Debian packager and beta tester. + +Jose Angel Sanchez Caso (JASC): Big endian solutions, the drivers concept +implemented in TV 2.0 and the graphical Win32 driver. + +Laurynas Biveinis: A lot of patches collected from the net, MSS support, +testing and ideas. + +Michel Catudal: RPM packages (v1.1.3) and newer SuSE 8.0 packages. + +Mike Gorchak: QNX6 and QNX4 port. + +Roman Valyushenko: X11 bug reports and fixes, X11 busy cursor and russian +translation of the messages. + +Ronald Landheer: Help with the Cygwin port. + +Sergio Sigala: He maintains a BSD port of TV from where I took some of the +examples. I think Robert based his Linux code on it. + +Tapio Kelloniemi: Information about how to make the library cooperate with +Braille Terminals. + +Vadim Beloborodov: MinGW and Win32 code. + +WintiX: Miscrosoft C compiler help and test. + + +The following users also contributed with small patches, testing and bug +reports: + +Alex Matulich, Anders Blom, Arvin Baccay, Cesar Rabak, Christoph Bauer, +Christopher Nelson, David Nock, David A. Capello, Dean Wakerley, Dim Zegebart, +Dimitar Jekov, Egon Eckert, Jerzy Witkowski, Joel Soete, Luis Pistoia, Matt +Mueller, Nate Eldredge, Norberto Alfredo Bensa, Owen Rudge, Robert Varga, +Sean Proctor, Sergey Krivulja, Tanes Sriviroolchai, Tatu Kilappa, Waldemar +Schultz and Wojciech Warczakowski. diff --git a/tvision/TODO b/tvision/TODO new file mode 100644 index 0000000..1559d76 --- /dev/null +++ b/tvision/TODO @@ -0,0 +1,10 @@ +That's a list of things to do in the project: + +* Fix problems when compiling the library with -DNO_STREAM. Laurynas +Biveinis contributed some fixes. More work is needed. +* Add some mode where graphic modes aren't restored. Restoring graphic modes +is dangerous in machines with buggy Windows video drivers. Reference report: +0001.txt. +* Implement something like TVIntl, it should handle the intl initialization, +hide the gettext stuff and provide a remapping according to the current App +code page. diff --git a/tvision/borland.txt b/tvision/borland.txt new file mode 100644 index 0000000..13e4b9a --- /dev/null +++ b/tvision/borland.txt @@ -0,0 +1,50 @@ +Borland TurboVision 2.0 + +NOTE ON THE CONTENTS OF THIS ARCHIVE: +------------------------------------- +The three enclosed .ZIP files comprise all necessary and +available source and documentation for TurboVision 2.0. + +Note that no path information is stored in these archives. +Typically, the contents of INCLUDE.ZIP are to be placed in +\BCx\INCLUDE\TVISION; the contents of SOURCE.ZIP are to be +placed in \BCx\SOURCE\TVISION. Also note that the source +includes some assembly language (*.ASM) files. Successful +generation of the TurboVision library will require use of +Turbo Assembler to translate these source files into object +files. DOCS.ZIP can be placed anywhere. + + +DISCLAIMER AND LIMITATION OF LIABILITY: +--------------------------------------- +DISCLAIMER AND LIMITATION OF LIABILITY: Borland does not make or +give any representation or warranty with respect to the +usefulness or the efficiency of this software, it being +understood that the degree of success with which equipment, +software, modifications, and other materials can be applied to +data processing is dependent upon many factors, many of which +are not under Borland's control. ACCORDINGLY, THIS SOFTWARE IS +PROVIDED 'AS IS' WITHOUT EXPRESS OR IMPLIED WARRANTIES, +INCLUDING NO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE, OR NONINFRINGEMENT. THIS SOFTWARE IS +PROVIDED GRATUITOUSLY AND, ACCORDINGLY, BORLAND SHALL NOT BE +LIABLE UNDER ANY THEORY FOR ANY DAMAGES SUFFERED BY YOU OR ANY +USER OF THE SOFTWARE. BORLAND WILL NOT SUPPORT THIS SOFTWARE +AND IS UNDER NO OBLIGATION TO ISSUE UPDATES TO THIS SOFTWARE. + +WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, NEITHER +BORLAND NOR ITS SUPPLIERS SHALL BE LIABLE FOR (a) INCIDENTAL, +CONSEQUENTIAL, SPECIAL OR INDIRECT DAMAGES OF ANY SORT, WHETHER +ARISING IN TORT, CONTRACT OR OTHERWISE, EVEN IF BORLAND HAS BEEN +INFORMED OF THE POSSIBILITY OF SUCH DAMAGES, OR (b) FOR ANY +CLAIM BY ANY OTHER PARTY. SOME STATES DO NOT ALLOW THE +EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, +SO THIS LIMITATION AND EXCLUSION MAY NOT APPLY TO YOU. Use, +duplication or disclosure by the Government is subject to +restrictions set forth in subparagraphs (a) through (d) of the +Commercial Computer-Restricted Rights clause at FAR 52.227-19 +when applicable, or in subparagraph (c) (1) (ii) of the Rights +in Technical Data and Computer Software clause at DFARS +252.227-7013, and in similar clauses in the NASA AR Supplement. +Contractor / manufacturer is Borland International, Inc., +100 Borland Way, Scotts Valley, CA 95066. diff --git a/tvision/change.log b/tvision/change.log new file mode 100644 index 0000000..d26d91b --- /dev/null +++ b/tvision/change.log @@ -0,0 +1,3852 @@ +$Log: change.log,v $ +Revision 2.743 2010/01/27 13:17:40 set +* Fixed: [DOS] EOF needs stdio.h. Closes SF # 2940568 reported by fytodent. +. +Revision 2.742 2010/01/27 12:44:36 set +* Fixed: [alconscr.cc screen.h] setCharacter second argument (from Unicode +branch) +* Fixed: [linuxkey.cc] charCode doesn't exist in the trunk (from Unicode +branch). Closes SF #2940576 reported by fytodent. +* Added: [index.html] Some CVS snapshots (old). + +Revision 2.741 2009/11/10 18:18:35 set +* Modified: Krzysztof's e-mail. + +Revision 2.740 2009/08/27 14:22:37 set +* Fixed: [examples/fonts/test.cc] Missing Uses_limits request. +* Added: [examples/Makefile.nmk ] MSVC makefile for the examples, +contributed by Jure Erznoznik. +. +Revision 2.739 2009/08/27 13:14:18 set +** Patches contributed by Jure Erznoznik +* Fixed: [tfilecol.cc] for 64bit size_t (MSVC) +* Modified: [examples/dlgdsn/*.cc] to avoid using gcc's case extensions. +* Added: [compatlayer.h] support for MSVC 2008 boolean datatype. +* Added: [winnt/Makefile.nmk] support new classes + added defines for 64bit +compile + added support for MSVC 2008 + +Revision 2.738 2009/06/26 11:35:31 set +* Fixed: The last change in TVConfigFile::GetString() introduced a bug +(last " not removed). + +Revision 2.737 2009/06/24 14:31:16 set +* Fixed: [Linux] the keyboard driver filled charScan.charCode twice and +didn't fill charCode members of the keyDown event. + +Revision 2.736 2009/06/23 18:00:10 set +* Modified: Version in tv.h. + +Revision 2.735 2009/06/23 17:42:28 set +* Modified: QNX and Debian version to 2.2.0. + +Revision 2.734 2009/06/23 17:15:21 set +* Modified: Version to 2.2.0. + +Revision 2.733 2009/06/23 16:48:25 set +* Added: AlCon driver, this is the conio emulation code on top of Allegro. +From the alcon branch and contributed by Grzegorz Adam Hankiewicz. +* Fixed: TVConfigFile::GetString() leaked memory and returned an +unprocessed string. +* Fixed: Memory leaks in X11 driver. + +Revision 2.732 2009/06/22 15:14:45 set +* Modified: TParamText::setText to take a constant string as first argument +(not modified). + +Revision 2.731 2009/03/17 13:04:09 set +* Modified: [WWW] SF Logo according to the new policy. +* Fixed: [WWW] Some HTML errors. + +Revision 2.730 2009/03/17 12:38:35 set +* Modified: [tlistvie.cc] To avoid ambiguous if/else. +* Modified: [Debian] Package version to 5 for Lenny. +* Fixed: [WWW] Link to CVS source code. +* Modified: [WWW] Script to upload htmls to SF. + +Revision 2.729 2009/02/27 11:32:27 set +* Fixed: [config.pl] sys/io.h detection. The code didn't compile with gcc +4.3.x. +* Modified: [tbutton.cc teditor.cc tmenuvie.cc tpxvalid.cc tscrolle.cc +tstatict.cc tview.cc] To avoid gcc warnings about ambiguous else statements +. +Revision 2.728 2009/02/25 16:25:37 set +* Modified: [newstr.cc tmenuvie.cc] Use of NULL instead of 0. +* Modified: [tfileinp.cc tfilelis.cc tgkey.cc codepage.h gkey.h menuitem.h +screen.h tmenuvie.cc] Use of const char * for some functions/values taking +string constants. +* Fixed: [tpxvalid.cc] TPXPictureValidator passed a const char * to picture +* Modified: [linuxkey.cc xtermkey.cc] Useless typedef keyword. +* Modified: [linuxscr.cc qnx4scr.cc unixscr.cc xtermscr.cc x11src.cc] +execvp takes a char *const and not const char *, so now we allocate copies. +* Modified: [x11src.cc] classHint members are declared a char * and not +const char *. +* Fixed(?): [listbox.h] TListBoxRec should be packed for 64 bits +architectures. +. +Revision 2.727 2009/01/22 14:58:09 set +* Modified: TCalculator::keyChar to be constant. SF #2526590 patch +submitted by Larry Ziegenbein (SF larryzie) + +Revision 2.726 2009/01/06 12:39:22 set +* Added: [doc] Visual Studio 2008 compilation procedure. Contributed by +Harry Sack + +Revision 2.725 2008/08/27 03:51:33 terrible +* Corrected bad format for changelog entry, sorry, has been a long time! :-) + +Revision 2.724 2008/08/27 03:48:59 terrible +* Updated: [Debian] Version to 2.1.0-4 (small correction). + +Revision 2.723 2008/07/10 19:08:01 set +* Modified: [Debian] To also support libgm-dev as a builing package. + +Revision 2.722 2008/07/10 19:07:31 set +* Added: Some equivalences to the Unicode table. +. +Revision 2.721 2008/07/10 18:55:20 set +* Modified: Libraries named to create the library (exclude itself). +. +Revision 2.720 2008/02/27 20:09:25 set +* Fixed: [X11] The cursor became invisible if it was over a character with +background color = foreground color. +. +Revision 2.719 2008/02/27 14:20:28 set +* Modified: [X11] To fully skip request to draw areas with the same +content. Previous code did some work even if nothing was actually drawn. + +Revision 2.718 2008/02/26 14:28:40 set +* Modified: [SSC] Enabled TTextDevice and most of TTerminal stuff when +using SSC. Only otstream isn't supported. + +Revision 2.717 2008/02/26 14:22:41 set +* Modified: The rhtv-config tool to report only the installation directory +for the --include option. + +Revision 2.716 2008/02/26 11:54:08 set +* Fixed: Access violation in TStringCollectionCIntl::freeItem() when +HAVE_INTL_SUPPORT wasn't defined. Closes SF #1891237, reported by Peter +Remmers. + +Revision 2.715 2007/09/03 13:18:44 set +* Fixed: incorrect delete in TPalette::operator=. SF #1786428. Submitted +by Baurzhan Ismagulov - ibr. + +Revision 2.714 2007/07/11 12:00:44 set +* Fixed: [TScreen] The image/pdf viewer mechanism to collect zombie +children when the user manually closes the application helper. + +Revision 2.713 2007/06/19 13:36:51 set +* Added: A new fpstream constructor. The original constructor enforces the +binary flag (to avoid problems with binary data) but also adds the ios::out +flag. This is bad when you open a read-only file. The new constructor +doesn't add any flag (not even binary). From a problem seen on SETEdit and +reported by Witek. + +Revision 2.712 2007/06/04 13:53:31 set +* Fixed: [TScreen] The last patch was wrongly applied and some members +were declared inside TDisplay class. Reported by Witek. + +Revision 2.711 2007/05/31 14:27:33 set +* Added: [TScreen] a mechanism to start external image and pdf viewers. +Currently implemented only by the X11 driver. An example is included in +examples/viewers. + +Revision 2.710 2007/05/29 13:05:16 set +* Updated: [Debian] Packaging to version 2.1.0-4. + +Revision 2.709 2007/05/29 11:24:37 set +* Fixed: [config] the way --include option is processed. From a patch sent +by Witek. + +Revision 2.708 2007/05/18 10:54:54 set +* Fixed: [Config] the ncurses' define_key test. Patch from Witek (Witold +Filipczyk) + +Revision 2.707 2007/05/17 18:07:23 set +* Modified: The gpm mouse wheel support. Now it works better, tested. + +Revision 2.706 2007/05/16 20:19:23 set +* Modified: The way LDFLAGS and libraries are used to link the final +library. Now the libraries goes at the end of the line and not mixed with +RHIDE_LDFLAGS. This is needed to use the --as-needed linker flag. I don't +see the point using it for this library because we carefully chose which +libraries are listed, but could help in the future. This patch is based on +the SF patch #1642841. + +Revision 2.705 2007/05/16 18:32:43 set +* Added: Support for mouse wheel in Linux console. Partially tested, needs +a patched gpm. Patch from Witold Filipczyk witekfl/poczta/onet/pl. + +Revision 2.704 2007/05/16 18:16:12 set +* Fixed: TFileInfoPane::draw() didn't protect a temporal buffer from +overruns. Under some situations it could be overflowed. + +Revision 2.703 2007/05/09 12:55:57 set +* Modified: The default time to sleep when no events are available. It was +10 µs, good for most Linux kernels, but 2.6.21 reduces the granularity and +really sleeps for a small ammount of time. Now we sleep for 10 ms. From a +report and test by Ivan Baldo. + +Revision 2.702 2007/05/08 19:43:52 terrible +* Updated: [Debian] Packaging to version 2.1.0-3, small things. + +Revision 2.701 2007/04/18 15:45:11 set +* Fixed: [Makefile] added -f to the rm command to remove the old symblinks +to avoid messages from rm. +* Fixed: [tresfile.cc] the THeader structure requested packed attibute for +the members of a union instead of the union itself. Reported by gcc 4.1.1. +* Fixed: [tview.cc, view.h] removed unused writeView member and associated +structures. This code wasn't used and did a wrong cast. +* Fixed: [linuxscr.cc] removed request for the first element in the setSel +structure. + +Revision 2.700 2007/01/24 16:44:25 set +* Fixed(?): New Linux kernels seems to omit asm/io.h and we must use +sys/io.h. SF Patch #1642839 (anonymous). + +Revision 2.699 2007/01/16 18:17:14 set +* Fixed: [Win32] The Win32 and WinNT drivers failed to work when a TV a +application was executed from the MinGW console. Now the code checks if +it have a working console before using the Win32 and WinNT drivers. +The idea and bug report was submitted by domatlantida (JASC). Closes +S.F. bug report SF #1611485. + +Revision 2.698 2007/01/16 17:31:39 set +* Fixed: TTerminal::prevLines wrongly checked the pos while going back +reading out of bounds. Patch by dou9st3r (SF user). Closes bug report +SF #1618614. +* Fixed: [config] examples/rhide.env definde RHIDE_LDFLAGS in the same eay +used to dynamically link the library, not really good for executables ;-) +* Fixed: [config] the test for gcc 4.x was executed before detecting gcc. + +Revision 2.697 2006/12/05 15:02:55 set +* Fixed(?): Compilation issue in the Win32 code. The WinGr driver wrongly +declared setCharacter. Bug tracker: SF #1607447. + +Revision 2.696 2006/11/22 15:11:38 set +* Modified: The configuration script to use -Wno-packed when gcc 4.x is +detected (untested). Needed to eliminate a silly warning. + +Revision 2.695 2006/11/13 19:33:55 set +* Modified: ipstream now aborts when trying to load an unknown class. +* Added: Initialization of the rest of the buffer when hiting the end of +file. + +Revision 2.694 2006/11/06 13:11:33 set +* Added: A workaround for Ubuntu's glibc, it looks like an explicit +inclusion of libintl.h is needed. The code is experimental and could break +other gcc 4.x Linux distros. Reported by Donald R. Ziesig +. + +Revision 2.693 2006/08/18 14:42:42 set +* Fixed: When adding a variable to a TVConfigFile and this variable already +existed it could break the tree. + +Revision 2.692 2006/06/07 19:08:37 set +* Fixed: printf in SSC streams code when open returned error. + +Revision 2.691 2006/04/18 12:20:49 set +* Modified: The old workaround for bintextdomain prototype missmatch (dated +december 2002) now gives troubles for gcc 4.0.3. I'm removing it to find if +it is needed for modern gcc versions. I tried 3.3.5 without problems. + +Revision 2.690 2006/04/17 13:12:15 set +* Modified: [MSVC] Disabled warning 4996 for v8.0+. It deprecates the POSIX +names and suggests to use _name. + +Revision 2.689 2006/04/12 16:21:16 set +* Fixed: [MSVC] Some warnings from MSVC 8. From info by Eddie. + +Revision 2.688 2006/04/11 13:24:06 set +* Fixed: TFileCollection::writeItem writes a time_t to disk. This isn't +safe at all. MSVC reports it as an error. As a workaround I casted it to +an unsigned long. It will work for most platforms and won't make old files +invalid. +* Fixed: [MSVC] Debug options used some old flags. +* Modified: [MSVC] stricmp and strnicmp to be _*. From a report by Eddie. + +Revision 2.687 2006/04/05 15:39:57 set +* Added: [MSVC] Information about MSVC 8.0 to the compatlayer header. + +Revision 2.686 2006/03/21 18:56:01 set +* Modified: [MSVC] The /GX command line option is deprecated. Using /EHsc +instead. +* Modified: [MSVC] v8.0 doesn't like strcpy, strncpy, sprintf, etc. Added +option to disabling those warnings. +* Modified: [MSVC] v8.0 seems to be unable to handle open(const char *, +int): +./fileview.cc(145) : error C2668: '_open' : ambiguous call to overloaded function + E:\MVS8\VC\INCLUDE\io.h(328): could be 'int _open(const char *,int,...)' + E:\MVS8\VC\INCLUDE\io.h(254): or 'int _open(const char *,int,int)' + while trying to match the argument list '(const char *, int)' + +Revision 2.685 2006/03/17 14:40:36 set +* Fixed: [Linux] The patch to avoid gcc 4.0.3 problems generated problems +in tvintl.cc. Now I moved the workaround from compatlayer to this source. +This should avoid both problems. + +Revision 2.684 2006/03/17 13:58:55 set +* Fixed: [Linux] Current versions of glibc (i.e. 2.3.2) doesn't provide +the real argv/environ vector, just a copy. The methode to set the title +corrupted the environment. + +Revision 2.683 2006/03/15 17:14:39 set +* Fixed: Indentation and data type in tvedit1.cc patch from domatlantida. + +Revision 2.682 2006/03/15 16:46:03 set +* Fixed: Some potential leaks in the X11 driver. Lamentably valgrind +reports tons of them from inside X11. +* Added: TInputLine::setHide(Boolean val) shortcut. + +Revision 2.681 2006/03/14 17:50:42 set +* Fixed: Problems using current Perl interpreter shipped with MSys (MinGW). +Based on a patch by JASC. + +Revision 2.680 2006/02/10 18:12:30 set +* Added: Workaround for a gdb bug, seen on Debian Sarge. + +Revision 2.679 2006/02/03 15:57:50 set +* Fixed: Last patch to WinGr prevented compilation using gcc (/* inside a +comment). + +Revision 2.678 2006/01/25 22:33:06 terrible +* Updated: [Debian] Packaging to version 2.1.0-2, cosmetic changes. + +Revision 2.677 2006/01/24 17:38:08 set +* Fixed: BTV 1.x calls to setValidator in examples. Patch by Frank Taffelt +frank.taffelt/web/de. + +Revision 2.676 2006/01/18 14:00:26 set +* Added: A methode to make input lines hide their content. +. +Revision 2.675 2005/12/27 14:18:30 set +* Modified: Restored the code to honor the ilValidatorBlocks flag in +TInputLineBase::setState. I don't know why I removed it when I added BTV +2.0 stuff. + +Revision 2.674 2005/12/05 20:24:10 set +* Added: Now the list box in the file dialog uses left and right arrows to +navigate directories. Suggested by Sergio Núñez snunez/esquemas/com. + +Revision 2.673 2005/11/10 19:46:26 set +* Fixed: TParamText::~TParamText new/delete[] missmatch. SF patch #1353152 +(David cz, using valgrind). +. +Revision 2.672 2005/11/10 19:39:58 set +* Modified: TInputLine::setData to support a constant as argument. Closes +SF patch #1353157 by fytodent (David cz). + +Revision 2.671 2005/09/23 15:26:07 set +* Fixed: [OpenWatcom] Some details related to the import lib generation. +Patch from Lothar. Note: wmake is the worst make tool we support. + +Revision 2.670 2005/09/21 15:06:15 set +* Modified: [OpenWatcom] compilation flags. Patch by Lothar. +* Added: [OpenWatcom] Import lib creation. +* Fixed: extrimk was created using the C compiler instead of the C++ one. + +Revision 2.669 2005/09/20 14:48:37 set +* Added: [OpenWatcom] Which version was used. +* Modified: [OpenWatcom] Removed test from makefile. + +Revision 2.668 2005/09/19 14:06:58 set +* Fixed: [OpenWatcom] compilation rules. Patch by Lothar. +* Added: [OpenWatcom] instructions on how to compile. +* Modified: [MSVC] the compilation instructions. After Arnold's success +using the free MSVC tools I think MSVC can use the unified make system as +default. + +Revision 2.667 2005/09/16 19:37:02 set +* Added: [OpenWatcom] More to the makefiles, not yet usable. From info by +Lothar. + +Revision 2.666 2005/09/16 18:56:31 set +* Fixed: [MSVC] the "all" target isn't special for nmake. After arranging +things so the variable gets defined by the time all is used I introduced +a side effect: all isn't the first anymore. So we must explicitly ask for +"all" target. From information sent by Arnold. + +Revision 2.665 2005/09/07 18:16:27 set +* Fixed: [MSVC] nmake doesn't analyze the whole makefile before expanding +variables, in order to create mlink.exe we need to first define +HELPER_TARGET. From info by Arnold. + +Revision 2.664 2005/09/06 20:14:30 set +* Added: First step toward integrating Open Watcom to the unified make +system. From info by Lothar. + +Revision 2.663 2005/09/06 18:17:47 set +* Fixed: Unknown keys triggered status line shortcuts assigned to kbNoKey. +Closes SF Bug #1278751, submited by David (fytodent). + +Revision 2.662 2005/08/24 13:00:22 set +* Added: [WWW] Links to a CVS snapshot (tarball and Sarge). + +Revision 2.661 2005/08/22 20:04:37 set +* Modified: [OpenWatcom] Disabled warning 555. Code by Lothar. +* Added: [Win32 DLL/OpenWatcom] Exported TObject, THWMouse and TMouse. +Patch by Lothar. + +Revision 2.660 2005/08/22 15:27:16 set +* Added: [Compilation] intl clean to the clean target. As suggested by +Ivan. +* Modified: [Debian] Command line for dch, needed for Sarge. + +Revision 2.659 2005/08/19 05:27:14 terrible +* Updated: [Debian] Packaging to version 2.1.0-1. + +Revision 2.658 2005/08/09 11:52:20 set +* Fixed: [SSC] SIGSEGV when closing a stream that failed to open. +* Fixed(?): [MSVC] Include path to find cl/dir.h and winnt/include/tv/con* + +Revision 2.657 2005/08/09 11:45:36 set +* Fixed: Disabled gettext v0.14.4 "feature" that returns the +"Program-Id-..." text when you pass "" to gettext. Previous versions didn't +have this "feature". + +Revision 2.656 2005/08/05 17:10:01 set +* Fixed(?): [MSVC] mlink.exe compilation. The /OUT: option must be passed +to the linker with /link. From a report by Arnold. Untested. +* Fixed(?): [MSVC] The unified make process didn't include dir.h. From a +report by Arnold. Untested. + +Revision 2.655 2005/08/05 13:53:20 set +* Added: Polish translation. Contributed by Eddie. + +Revision 2.654 2005/08/04 20:18:07 set +* Fixed: The TCalendar class in the demo program tested for wrong mouse +coordinates to change the month. Patch by Eddie. + +Revision 2.653 2005/08/04 20:04:47 set +* Modified: [OpenWatcom] the compiler generates a warning when we use +"delete[] (const char *)var" so now I cast all of them to (char *). +Reported by Lothar. + +Revision 2.652 2005/08/04 19:29:06 set +* Added: Some missing export directives for the DLL. Patch by Lothar. +* Fixed: Missing TLookup* members. Patch by Lothar. +* Updated: Spanish translation. + +Revision 2.651 2005/08/04 18:59:08 set +* Updated: Spanish translation. + +Revision 2.650 2005/08/03 18:27:19 set +* Fixed: Another "class TEvent" reference. Reported by Eddie. + +Revision 2.649 2005/08/03 13:27:40 set +* Added: [MSVC] More information about installation. +* Added: [MSVC] Diabled warning 4312. From a report by Eddie. + +Revision 2.648 2005/08/02 18:54:01 set +* Added: TLookupValidator and TStringLookupValidator from Borland's TV 2.0. + +Revision 2.647 2005/08/02 15:39:09 set +* Added: The Borland's TV 2.0 TInputLine functionality: + * TValidator * as last constructor argument. + * TValidator try/unroll code. + * TValidator "transfer" stuff to meassure the size. + * TValidators using the full input instead of the last char. + * Shift+Arrows to select the text (I don't like the way that's + implemented) +* Added: TValidator * argument to inputBox helper. +* Modified: Moved the hotKey function to misc, this function isn't used by +TInputLine. +* Added: A TPXPictureValidator example to the demo. +* Modified: Version to 2.1.0 because the TInputLine and TValidator changes +are an important API change. + +Revision 2.646 2005/08/02 14:49:24 set +* Fixed: [MSVC] Wrong pragma usage. Pointed out by Eddie. + +Revision 2.645 2005/08/02 14:07:29 set +* Modified: [MSVC] Disabled warning 4291 in histlist.cc. The compiler is +wrong. +* Modified: [MSVC] Added support for 64 bits pointers in uipointer and +clarified the warning 4311 issue (also disabled). Both from info sent by +Eddie. + +Revision 2.644 2005/08/01 18:16:07 set +* Modified: [MSVC] Disabled the MSVC "pointer truncation" warning. I can't +see any truncation because I think both are 32 bits unsigned values. I'll +disable it until somebody can explain it. Eddie provided the pragma. + +Revision 2.643 2005/08/01 17:02:53 set +* Fixed: A couple of errors in the last modifications to TFrame. The move +and grow should work only for mouse down. If not they get activated when +we only get the up (i.e. when changing focus). + +Revision 2.642 2005/08/01 16:52:00 set +* Fixed: [MSVC] v7.1 defines read/write and in an incompatible way to our +replacements for old versions. Reported by Eddie. + +Revision 2.641 2005/08/01 16:32:22 set +* Added: More export directives. Patch from Lothar. + +Revision 2.640 2005/08/01 16:11:48 set +* Modified: All casts from void * to an integer to use uipointer. The +problem with MSVC remains, but once we solve what to use as uipointer all +the warnings will go away at once. Reported by Eddie. +* Fixed: [MSVC] Some forward declarations for TEvent used class when +that's an struct. Reported by Eddie. +* Modified: [MSVC] The FA_* definitions in compatlayer and other places to +be coherent. I'm not sure about them but now they are coherent to what +findfirst returns. Reported by Eddie. + +Revision 2.639 2005/08/01 14:55:24 set +* Added: A small macro to help creating input lines with validators. That's +related to S.F. FR #1248650 posted by Eddie. + +Revision 2.638 2005/08/01 14:20:24 set +* Fixed: Wrong names in TPXPictureValidator members (IsValid vs isValid, +etc.) Reported by Eddie. + +Revision 2.637 2005/07/29 13:35:00 set +* Fixed: [MSVC] The __DELTA macro used for TStreamableClass casts a pointer +to an integer type. The code used long which isn't a good choice for that. +Reported by Eddie. + +Revision 2.636 2005/07/29 13:34:48 set +* Added: [gcc] Workaround for a gcc 2.95.2 bug. It looks like inline class +members that have an extra ; at the end of the function body can confuse +gcc (only in particular cases). Reported by Thiago. + +Revision 2.635 2005/07/29 13:34:37 set +* Added: A helper function to TView called putEvent. It fills a TEvent +structure and calls putEvent (the original one). That's a common operation. + +Revision 2.634 2005/07/29 13:34:26 set +* Added: [Cosmetic] Icon animations for the close and zoom icons of TFrame. +Based on code sent by Eddie. It can be disabled. + +Revision 2.633 2005/07/29 13:34:09 set +* Fixed: [MSVC] Ambiguous call to stdio's read. In modern C++ that's an +overloaded function. So now TFileViewer::real_bufsize is of ssize_t type. I +also changed some code to handle size_t return values. Reported by Eddie. + +Revision 2.632 2005/07/27 20:44:50 set +* Modified: [DJGPP?] Added workaround for problems compiling without i18n +support using gcc 2.95.2 19991024 (release). Reported by Thiago. + +Revision 2.631 2005/07/25 14:09:20 set +* Fixed: [Win32] Typo in the names of the two new prototypes for +TWin32Screen. + +Revision 2.630 2005/07/22 20:53:04 set +* Modified: The TValidator API to be compatible with Borland's TV 2.0 API. +This will break some old programs but allow compilation of newer ones. + +Revision 2.629 2005/07/22 18:16:25 set +* Added: TPXPictureValidator, not tested. Closes SF FR #1235527. + +Revision 2.628 2005/07/22 12:53:13 set +* Added: [WWW] CVS snapshot for Sarge (SPARC). + +Revision 2.627 2005/07/19 14:56:57 set +* Fixed: [GCC] Some gcc versions only have "strstream" (not .h). Reported +by Vik while using Fedora Core 4. + +Revision 2.626 2005/07/19 14:55:48 set +* Fixed: [SSC] offset not updated after a block read. + +Revision 2.625 2005/07/14 18:16:28 set +* Added: [SSC] very basic support for strstreambuf class. Needed by RHIDE. + +Revision 2.624 2005/07/12 13:18:24 set +* Fixed: [Win32] The Win32 driver crashed after a window resize. Reported +by Eddie (one_eddie/tenbit/pl). + +Revision 2.623 2005/07/08 20:26:49 set +* Added: [gcc] Code to solve problems related to gcc 3.4.x and 4.0.0. The +solution was provided by Andris, but IMHO that's a workaround for gcc bugs +instead of a solution. + +Revision 2.622 2005/07/08 16:50:37 set +* Modified: [Win32+Watcom] Changes to export classes, needed to create a +DLL. That's a first wave of patches from Lothar, more will come ;-) + +Revision 2.621 2005/07/08 16:43:23 set +* Modified: [Windows XP] Workaround for the cursor shape. Disabled by +default because I never got confirmation. From Andris. +* Modified: [Linux] Enclosed Linux headers with extern "C", seems to be +needed by 2.6.11 headers (new used as a variable *8-P). From a bug report +in Gentoo. +. +Revision 2.620 2005/06/29 14:13:41 set +* Fixed: [Watcom] DIR and dirent are defined in direct.h +. +Revision 2.619 2005/06/21 20:33:08 set +* Modified: Third wave of patches to add support for Open Watcom. Patches +from Lothar. We are almost there ;-) +. +Revision 2.618 2005/06/17 19:54:17 set +* Added: [Config] Options to use the C++ compiler indicated by the CXX +environment variable. +. +Revision 2.617 2005/06/01 15:40:11 set +* Added: A second wave of patches to add support for Open Watcom. All based +on information and examples from Lothar. +. +Revision 2.616 2005/05/19 21:01:11 set +* Note: Watcom effort is being done by: Lothar Behrens (lothar/behrens/ +lollisoft/de) +* Added: [Watcom] uint64 and int64 definitions. +* Modified: [Watcom] changed stream members from pub* to *. + +Revision 2.615 2005/05/18 15:43:06 set +* Added: First step towards Open Watcom support. It just detects Watcom +compiler and defines it almost like BC++. + +Revision 2.614 2005/05/18 13:45:14 set +* Fixed: Extra ) in TInput1Line declaration. Reported by Frank Taffelt +(frank taffelt web de). +* Fixed: [config] Warning issued by gcc 4.0.0 in DetectPointersSize, it +makes the configuration fail when using -Werror. Reported by Andris. + +Revision 2.613 2005/05/12 18:42:08 set +* Added: gcc 4.x detection in compatlayer to use the same tricks used for +gcc 3.4.x. Patch from Andris. +* Fixed: Some classes with virtual members didn't have a virtual +destructor. Reported by gcc 4.0.0. Patch from Andris. + +Revision 2.612 2005/04/25 13:29:21 set +* Updated: Version in readme.txt and QNX package. +* Added: [MSVC] Compatibility with Visual Studio .NET 2005 Express Beta +Edition from Christian Kirches . + * Added: -D_USE_32BIT_TIME_T to flags to keep time_t as 32 bits. + * Added: #undef _CRT_INSECURE_OPEN before including io.h to avoid + warnings about _open. + * Added: #undef YieldProcessor to avoid collisions with a macro defined + in windows.h. + +Revision 2.611 2005/04/21 14:27:32 set +* Added: [configuration] A check for RHIDE tools when the user enables the +maintainer mode. + +Revision 2.610 2005/02/28 13:31:07 set +* Fixed: [Linux] Removed term.h inclusion from linuxdis.cc, that's ncurses +stuff not needed by the current implementation of the Linux driver. +Reported by Thiago. + +Revision 2.609 2005/01/17 15:05:49 set +* Fixed: Compilation problems when using MSS and gcc 3.4.1. Patch by +Michael Vzoroff. + +Revision 2.608 2005/01/11 18:49:54 set +* Fixed: [MinGW] The snprintf implementation is broken. That's obvious +because MinGW uses M$ runtime. Now MinGW target uses the replacement. + +Revision 2.607 2004/12/23 21:21:59 terrible +* [Updated] Debian packaging to version 2.0.4-1, it seems Salvador didn't + run the version update script, so I made changes to Debian packaging + manually; maybe this fixes problems Sergio was having building the package + but I didn't try to compile it so I cross my fingers... :). + +Revision 2.606 2004/12/15 20:33:08 set +* Fixed: Missing changes to cluster.h header in last patch. + +Revision 2.605 2004/12/13 15:49:34 set +* Fixed: [WWW] URL to Sigala's doc. Patch by Thiago. +* Fixed: [config] install was searched in the path without using the "Exe +Extension". I realized it when Thiago reported other problem about install +detection. + +Revision 2.604 2004/12/10 19:39:58 set +* Fixed: When configuring with --no-intl the TCluster class generated a +SIGSEGV in the destructor. Reported by Julian B. Lethbridge. [Also applied +missing patch from Unicode branch]. + +Revision 2.603 2004/12/07 14:48:58 set +* Added: [config] --debug option to select debug switches. + +Revision 2.602 2004/12/06 18:16:40 set +* Fixed(?): XFree86 reports Ctrl+2 without any symbol (only ASCII). +Reported by Sergio Núñez (snunez/esquemas/com). +* Added: Detection of 64 bits pointers and macros to cast pointers into +64 bits values. GCC 3.4.x doesn't allow to cast a pointer into an unsigned +long long if the pointer is 32 bits wide. +* Updated: Web page to reflect the release. +* Modified: Version to 2.0.4 + +--------- CVS tag r_2_0_3DOS and r_2_0_3nuDOS + +Revision 2.601 2004/11/29 16:23:15 set +* Fixed: [DJGPP][Maintainer dependencies] The path to system headers to be +excluded from dependencies must include the gcc 3.x dir. +* Fixed: [DJGPP][RHIDE compilation] RHIDE_LDFLAGS' UNIX settings interfere +with RHIDE on DOS. +* Added: [DJGPP] Warning in the docs about conio gettext and intl gettext +collision. This isn't fixed in current djgpp version even when this issue +is know for years. +* Fixed: [Compilation][Examples][gcc 3.x] Missing string.h in thelp.cc +* Fixed: [Compilation][Examples][gcc 3.x] CLY_OpenModeT to ushort in tvhc.h +* Fixed: [DOS] Missing useFixKbdBuffer in key.h. +* Fixed: [DJGPP][Maintainer dependencies] Dependencies for examples when +they are abolute (even after using gprexp). +* Updated: [Win32] makefiles. + +--------- CVS tag r_2_0_3 and r_2_0_3nu + +Revision 2.600 2004/11/23 00:31:47 terrible +* Updated: Debian packaging to version 2.0.3-3 (no changes really). + +Revision 2.599 2004/11/02 20:06:39 set +* Added: [Compilation][MSVC] Option to compile with debug information. +>From information sent by Grzegorz. +* Fixed: [Compilation][Darwin] libtvfintl.a must be listed "as-is", not +using -l. +* Modified: [Configuration] ar and install detection. Now more robust. + +Revision 2.598 2004/10/29 16:12:37 set +* Fixed: [DOS] The default encoding wasn't CP437. From a report by +jessehardy/126/com, a chinese user of RHIDE using code page 936. + +Revision 2.597 2004/10/29 15:21:30 set +* Fixed: [Compilation][MSVC] Typo in mlink.cc and wrong reference to +../compat/obj in common.nmk. Both patches from Grzegorz. With this the +unified mechanism works. + +Revision 2.596 2004/10/28 20:44:25 set +* Added: [DOCs][MSVC] MSVC 7.1 as supported compiler. Mike verified it and +this version is different than 7.0, enough to mention it. + +Revision 2.595 2004/10/20 13:42:56 set +* Modified: [Compilation][MSVC] HistRec to overload delete making explicit +this operation is invalid. I hope it avoids warnings. Reported by Grzegorz. +* Added: [Compilation][MSVC] A lib wrapper to avoid command line +limitations. Is untested. + +Revision 2.594 2004/10/19 18:16:52 set +* Modified: [Compilation] Removed time stamp from ?mk files. + +Revision 2.593 2004/10/19 18:06:20 set +* Fixed: [Compilation] Missing ../compat path in extrimk.cc tool. Reported +by Grzegorz. + +Revision 2.592 2004/10/19 15:11:04 set +* Fixed: [Linux] The console driver failed to detect the code page used by +the screen font (SFM). I think this was introduced by the 2003/05/21 patch. + +Revision 2.591 2004/10/18 15:00:53 set +* Modified: [Compilation] The dependencies now include a relative path so +makefiles doesn't need to define a "vpath". That's because nmake doesn't +have any equivalent. + +Revision 2.590 2004/10/15 23:41:53 set +* Fixed: [Win32][gcc 3.x] gcc 3.3.3 warning in WinGr code (using char as +array index). + +Revision 2.589 2004/10/15 23:38:24 set +* Fixed: [Win32] The Win32 driver: when the application or configuration +file requested a screen size bigger than 80x25 the code failed to register +the new window size and hence allocated too few bytes for the screenBuffer +generating a SIGSEGV. +* Fixed: [MinGW] New versions (i.e. 3.1.0) defines ssize_t. +* Fixed: [MinGW/BC++/MSVC] The regex code had a mess with the prototypes of +some internal functions. Reported by gcc 3.x. +* Added: [DOCs] More information about MinGW, now the code compiles with +version 3.1.0 using MSYS 1.0.10 and SiePerl 5.6.1. Note that the gdb +included with it is useless for the system I used (Win98SE) but the 6.0 +version is usable (with a lot of limitations :-( + +Revision 2.588 2004/10/14 19:31:55 set +* Modified: [Compilation] The dependencies extractor to put the OBJFILES +definition before its use. It should help nmake. +* Modified: [Compilation][nmake] To avoid generating blink.exe. + +Revision 2.587 2004/10/13 15:53:46 set +* Added: [MSVC] First attempt to add MSVC to the "unified" compilation +mechanism. + +Revision 2.586 2004/10/12 20:28:31 set +* Added: [Install] Support for Solaris' native install tool. That's a +really bad implementation installer. + +Revision 2.585 2004/10/08 21:13:58 set +* Fixed: [Config][Solaris] dynamic lib creation when using native ld. +* Fixed: [Config][Solaris and Darwin] the native snprintf function +violates POSIX, now replaced by internal one. + +Revision 2.584 2004/10/08 15:04:54 set +* Added: Tru64 (OSF1) support. Thanks to HP Test Drive. The system I used +is an HP Tru64 Unix 5.1b running on a DS20E 2@667 MHz (ev67) [2 Alpha CPUs] +It have a very buggy port of GNU tools, but is usable. +* Fixed: [Compilation] Some C libraries (not GNU) declares "struct timeval" +with a "forward" declaration and you must pull sys/time.h. I saw it before +but forgot to apply the patch. +* Added: [DOCs] More information about the UNIX systems where I succesfuly +compiled. + +Revision 2.583 2004/10/05 22:33:23 terrible +* [Debian] Updated to 2.0.3-2 (minor changes mostly cosmetic). + +Revision 2.582 2004/10/05 21:43:21 set +* Fixed(?!): [gcc 3.4.1] For some, unknown, reason the mechanism to "pull" +stream dependencies fails for Mandrake 10.0 (gcc 3.4.1 + glibc 2.3.3 + +binutils 2.14.90.0.7 20031029). So now I'm changing to the mechanism we +used for BC++ when 3.4.1 is detected. + +Revision 2.581 2004/10/05 00:19:29 set +* Added/Fixed: [DOS] The default keyboard code assumed the start and end of +the BIOS circular buffer. Now it reads these values from the BIOS data +area. Egon Eckert contributed a patch for it. But I applied it with major +changes. The most important is that it can be reverted from the config +files. I'm doing it to include this patch in the 2.0.3 release. + +Revision 2.580 2004/10/04 21:33:34 set +* Fixed: [Comnpilation][SuSE] SuSE 9.0 defines TEMP_FAILURE_RETRY using +errno, but errno.h isn't automatically included. So I added a workaround +for this bug. + +Revision 2.579 2004/10/02 21:00:02 set +* Fixed: [Darwin] The file libfintl.a must be generated before the dynamic +lib. My previous try worked because I already installed it during the test. +* Fixed: [FreeBSD] Even when miniEleph said me that I had to install +librhtv.so and librhtv.so.2 the fact is that if I use sonames like in the +other UNIX systems I have to also install librhtv.so.2.0.3. I understand +that's unusual for FreeBSD and also that my versions are wrong but that's +the only way to get a usable setup. + +Revision 2.578 2004/10/01 21:35:27 set +* Added: Support for NetBSD: + * install moves files by default so we need to add -c. + * extra libs must be searched in /usr/pkg/lib. + * getopt_long is supported. +* Added: Support for OpenBSD: + * getopt_long is supported. +* Added: Support for Darwin: + * options to compile sources for dynamic libraries is -fno-common (no + -fPIC). + * options to link a dynamic lib are 100% different. + * static libs must be included during dynamic lib generation. + * dynamic libs names are different (lib.version.dylib). + * ranlib must be run *after* installing a static lib. + * strip --strip-debug => -S. + * ldconfig doesn't exist. + +Revision 2.577 2004/09/30 20:56:16 set +* Fixed: [XTerm] The "get window title" escape sequence was reported to be +exploitable. For this reason new versions of xterm and Eterm doesn't +respond to this request. It made the library wait for the reply. So the +programs didn't continue until the user pressed a key. Now I added a 300 ms +timeout. + +Revision 2.576 2004/09/30 20:55:36 set +* Added: [Config] OpenBSD as known OS. Tested with OpenBSD 3.4. +* Fixed: [XTerm] input problems with *BSD systems. They interpret VMIN in a +very particular way and if that's 0 the input blocks forever. Now the input +code works for Darwin 6.8 (MacOS X 10.2), FreeBSD 4.8, NetBSD 1.6.1 and +NetBSD 1.6.1. Some output problems remains when big chunks of the screen +are updated. + +Revision 2.575 2004/09/30 17:22:48 set +* Updated: [WWW] adding the RC1 +--------- CVS tag r_2_0_3rc1 and r_2_0_3rc1_nu + +Revision 2.574 2004/09/29 02:32:39 terrible +* [Debian] Packaging up to speed with new version 2.0.3-1!!! I have +succesfuly built packages for an old Sid and of course Woody, though I am not +uploading them to the repository since I want to test 'em with SETEdit. I +will try to do them tomorrow if I can escape from paid work ;-). + +Revision 2.573 2004/09/22 21:26:40 set +* Fixed: [RPM] problems when the compress script didn't have execute +attributes. + +Revision 2.572 2004/09/22 19:37:40 set +* Added: [MSVC] Now UNCs are also supported (previously only BC++ code had +it). Arnold helped to enable it using MSVC 6.0. +. +Revision 2.571 2004/09/21 20:55:12 set +* Fixed: [Compilation] Problems with the examples when using +MAINTAINER_MODE. +. +Revision 2.570 2004/09/20 14:47:45 set +* Fixed: [gcc 3.x] Warning in compat/snprintf.c. Reported by Nicola Asuni. + +Revision 2.569 2004/09/20 14:18:34 set +* Added: [Config] A command line option to specify a path for includes. +This path is used for the configuration tests and for the library. +* Added: [Config] The path for X11 headers to the path to compile the +library. This is needed for various UNIX systems so I think the best is to +always include it. We knew it for QNX4 but I found Darwin also needs it. +Linux and Solaris doesn't. + +Revision 2.568 2004/09/17 19:13:47 set +* Fixed: [NetBSD] libintl isn't part of libc. + +Revision 2.567 2004/09/17 19:02:36 set +* Fixed: [MSVC] Missing return value in tdirlist.cc: +ListDirectory( char *path, char *end ). Introduced by last TDirListBox +patches in the MSVC specific section. + +Revision 2.566 2004/09/17 14:50:02 set +* Fixed: [DOS][gcc] gcc 3.4.1 warnings in vgastate.c code. Reported by +Nicola Asuni. + +Revision 2.565 2004/09/17 14:49:19 set +* Fixed: [Examples] [dlgdsn] The getFileName function returned a pointer to +a local buffer. Now it returns a newly allocated string. Reported by Nicola +Asuni. + +Revision 2.564 2004/09/16 21:04:05 set +* Added: [Config] AMD64 and NetBSD detection. Code seems to compile for +both. It doesn't mean they are supported. + +Revision 2.563 2004/08/30 13:13:44 set +* Fixed: [MSVC] MSVC 6.0 also failed to compile the WinGr driver, so we are +just disabling it for MSVC. + +Revision 2.562 2004/08/26 20:23:53 set +* Modified: [MSVC] At least MSVC 6.0 (version 12.00) have a erong +implementation of vsnprintf. As I already had too much problems with this +issue I switching to the compatlayer replacements. Reported by Arnold. + +Revision 2.561 2004/08/24 15:19:17 set +* Added: Horizontal scroll bar to the TDirListBox. +* Added: Visible cursor to the TDirListBox, it shows the state of the +incremental search. It should also help for Braille terminals. + +Revision 2.560 2004/08/24 13:31:27 set +* Fixed: Call to drawView() before updating the topItem member in +TListViewer::focusItem. Patch by Egon Eckert (egon/heaven/industries/cz). + +Revision 2.559 2004/08/23 20:43:53 set +* Added: Sorted directories for the non POSIX platforms in TDirListBox. +* Modified: The TDirListBox code to be easier to maintain. I hope the +changes doesn't break all platforms ;-) +* Added: Incremental search in the TDirListBox. + +Revision 2.558 2004/08/18 20:23:16 set +* Modified: TDirListBox to show the directories alphabetically sorted. + +Revision 2.557 2004/08/17 14:44:10 set +* Fixed: [gcc] Errors in the examples when using 3.4.1. Patch by Andris. + +Revision 2.556 2004/08/12 19:02:09 set +* Added: Compatibility with gcc 3.4 streams. It isn't fully compatible with +3.1-3.3 but defines a special filebuf that can be created from a C stream. +Andris suggested it. +* Fixed: gcc 3.4 seems to enforce a much more strict selection of +overloaded operators when a minimal ambiguity appears. To solve it the +operands must be casted. In this case stream offsets can't be added to long +values, casting the long value to a stream offset solves the problem. + +Revision 2.555 2004/07/29 20:39:29 set +* Added: When you disable a TLabel the linked object gets disabled. After +all what other thing could be expected? +* Added: Disabled TLabels are painted in a different way. Currently using +the "disabled button" color because we don't have much space in the pal. +* Added: TRadioButtons have a new member setEnableMask, with it you can +control the enabled/disabled state of upto 32 TViews without needing to +inherit a new class. + +Revision 2.554 2004/07/03 00:10:39 set +* Fixed: [X11] Some gcc versions can optimize "while (!safeToUnHook);" to +an endless loop. Patch by Andris. + +Revision 2.553 2004/06/28 18:18:18 set +* Fixed: [BC++] lack of QNX4 rule in "old mechanism" makefile. + +Revision 2.552 2004/06/28 17:51:19 set +* Fixed: [BC++] warnings in regex.c because of implicit const char * to +unsigned char * conversion (double error). + +Revision 2.551 2004/06/25 19:30:54 set +* Added: [MSVC] a simple bool/true/false replacement to compatlayer. + +Revision 2.550 2004/06/25 14:17:32 set +* Fixed: [MSVC] the WinGr driver can't be compiled with 4.0 because it uses +too much features only available in newer versions. +* Fixed: [MSVC] the lack of snprintf request in cl/needs.h. +* Both from Arnold Wiegert reports. + +Revision 2.549 2004/06/24 20:47:46 set +* Fixed: [MSVC] Cast to (char *) for alloca return value in ntdirent.c. +* Fixed: K&R 1 prototypes in regex.c. +* Fixed: [MSVC] Lack of ioctl in 4.0 +* Fixed: Forced stddef.h because of size_t use everywhere. +* All the above from Arnold Wiegert, also previous patch. + +Revision 2.548 2004/06/23 20:11:04 set +* Added: [MSVC] Version 4.0 seems to report version 1000 and lacks +snprintf. I also needs new.h instead of new. + +Revision 2.547 2004/06/23 19:40:51 set +* Modified: [MSVC] Use of /Tp instead of /TP in makefiles. It looks +like MSVC 4.0 only supports it. Reported by by Arnold Wiegert. + +Revision 2.546 2004/06/14 14:43:39 set +- From valgrind: +* Fixed: TVIntl::emptySt() new/delete[] missmatch +* Fixed: TFileDialog::valid new[]/delete missmatch +* Added: TVOSClipboard clean-up at exit. + +Revision 2.545 2004/06/14 14:42:42 set +* Fixed: [X11] A race condition in the update thread code. It was possible +that a SIGALRM arrived after destroying the TScreen class and before we +exited killing the program with the signal. Observed using valdrind (which +made the exit really slow ;-) + +Revision 2.544 2004/06/11 21:27:05 set +- From valgrind: +* Fixed: Leaks in TVFontCollection::CreateListOfFonts and +TVConfigFile::FreeList. +* Added: Clean-up to TVCodePage. + +Revision 2.543 2004/06/03 18:47:07 set +* Added: [config] HP-UX detection. Contributed by Dmitry V. Zavyalov +(dzavyalov/artezio/ru). + +Revision 2.542 2004/05/31 14:52:59 set +* Fixed: The F3 shortcut of menu item "File|Open" wasn't explicit in the +TEditorApp. Patch by David D. (ddoubrava/volny/cz) +* Added: [MSVC] Uses_glob to the MSC section of tfilelist.cc. Looks like +it's needed. Patch by David D. (ddoubrava/volny/cz) + +Revision 2.541 2004/05/28 20:53:38 set +* Updated: Library version in the readme.txt and Debian control file. +. +Revision 2.540 2004/05/26 20:42:43 set +* Fixed: [Win32] The size of clipboard returned by Win32 API isn't the size +of the text it contains (>=real size). For this reason we must meassure the +real size before passing it to the application. Reported and solved by +Warren H. Holt. + +Revision 2.539 2004/05/24 15:45:15 set +* Fixed: [Win32] The keypad / key for the WinNT driver. From information +provided by: Warren H. Holt (wHolt/drs-ewns/com) + +Revision 2.538 2004/05/24 14:48:44 set +* Modified: [config] Use of "g++" in favor of "gcc -lstdc++". This is +because newer gcc 3.x compilers can't compile C++ code without doing a +mess when we use the gcc frontend. From a report by Baurjan Ismagulov - ibr + +Revision 2.537 2004/05/12 14:25:15 set +* Fixed: When using TButton callbacks the button called the CB but also +sent the event. It is dangerous if the CB uses a dialog because the event +will be received by this dialog. Now if the CB should generate the event +if needed. +* Added: A user provided data pointer to the callback. So it not only +receives the command number but also a pointer to user defined data. + +Revision 2.536 2004/05/07 20:09:19 set +* Added: A new function called CLY_memcpy to compatlayer.h. This must be +used when we use memcpy and the blocks overlaps but we know the "normal" +implementation will work. Platforms where the copy order isn't OK can +define it to be memmove. A configuration option allows to do it too. +* Fixed: Some calls to memcpy that overlaps are now to CLY_memcpy. From +reports obtained by valgrind. + +Revision 2.535 2004/05/06 19:39:02 set +* Fixed: Use of delete[] for TVBitmapFontSize * objects. Reported by +Oswald using valgrind. +* Fixed: TListViewer::center not initialized. Reported by Oswald using +valgrind. + +Revision 2.534 2004/05/05 20:11:03 set +Modified/Fixed/?: In "File Dialogs": Now as soon as the file list is +selected the focused item is propagated to the other views (input line and +info panel). + +Revision 2.533 2004/04/28 15:39:37 set +* Added: Support for the way that Putty uses to report Home and End keys. +Not tested, from a report by Andras Szabo szaboan/kesz/hu. + +Revision 2.532 2004/04/19 20:41:58 set +* Added: Code needed to test with the AlCon branch. + +Revision 2.531 2004/04/14 15:41:12 set +* Fixed: Oops! the patch from the Unicode branch didn't apply propperly, +now is fixed and the code compiles. + +Revision 2.530 2004/04/14 15:34:01 set +* Modified: When clicking in an object: if it doesn't receive the focus we +no longer pass the the mouse event to this object. I think it doesn't have +any sense. It helps to other objects to avoid losing the focus. +* Modified: The basic "execDialog" function now sets the data before checking +if the dialog is valid. It helps when using validators because they will +indicate the dialog is invalid if the data is empty. +* Added: A mechanism to set options to TInputLine class. The only option +available is one to avoid passing the focus when the validator indicates the +data is invalid. +* Modified: Now dialogs become "inactive" (sfActive=False) after execution. +In this way TView childs can know when the dialog is no longer running. + +Revision 2.529 2004/03/18 18:03:18 set +* Fixed: [BC++] The version to use ISO C++ 1998 stuff seems to be >= 0x560. +From a report by Hartmut Welpmann + +Revision 2.528 2004/03/12 19:25:05 set +* Added: [config] Some stuff to the configure and makefiles to maintain +compatibility with packages that uses "auto tools". Patch by Aurelian +Melinte (LinCS/tiger project). + +Revision 2.527 2004/03/02 19:52:41 set +* Fixed: [Linux] Problems with big-endian terminals using /dev/vcs* +devices. Looks like the vcs format is platform dependent. + +Revision 2.526 2004/01/13 14:30:28 set +* Fixed: [BC++] Missing QNX4 directory. +* Fixed: [BC++] It doesn't have ioctl.h. + +Revision 2.525 2003/12/12 05:17:50 lmike +* Fixed some mouse issues for the QNX6. +* Fixed tvision.qpg file, added proper library dependencies. + +Revision 2.524 2003/12/09 16:04:38 set +* Added: A new argument to the optional TListBox constructor and a new +member to TListView. They allow to create TListBox-es that centers the +focused item when setData is used. Suggested by gradha. + +Revision 2.523 2003/12/04 19:44:59 set +* Fixed: MinGW seems to lack the ioctl.h header. Compatlayer must avoid +to try to include it. + +Revision 2.522 2003/12/03 20:28:08 set +* Fixed: Moved changes to winnt/Makefile.nmk to winnt/msvcmake.in. Reported +by gradha. + +Revision 2.521 2003/12/03 15:09:10 set +* Added: Patch from Mike to cleanly compile using MSVC 7.1 (.NET 2003 +Architect). + +Revision 2.520 2003/12/02 14:51:14 set +* Added: A first try to support the last MSVC compiler from information +provided by Grzegorz, it includes: +1) Adding /EHsc to compilation +2) Looks like this version follows the ISO C++ 1998 standard like gcc 3.x. +3) Default values for arguments of function pointers are no longer +supported. This is bizarre because all gcc versions support it. May be +that's part of ISO C++ 1998, not sure. + +Revision 2.519 2003/11/28 05:23:32 lmike +* [QNX6] Added experimental mouse support in text mode. + +Revision 2.518 2003/11/24 16:32:51 set +* Added: A new configuration option: AltKeysSetting. It controls the how +alt keys are interpreted. From a talk with Frank Liu. + +Revision 2.517 2003/11/24 16:29:58 set +* Modified: Synchronyzed the code for the update thread with my home CVS. + +Revision 2.516 2003/11/18 13:17:14 lmike +* Removed QNX4 ifdefs from the main tv sources, all done via Uses_xxx now. +* Added CLY version of snprintf for the QNX4. +* Added more QNX4 related fixes, including support for the pterm/qnxterm. + +Revision 2.515 2003/11/17 15:58:47 set +* Added: --without-static and --without-dynamic to the configuration. +Suggested by Oswald. +* Fixed: The target to install the dynamic lib didn't create the directory +first. Reported by Oswald. +* Added: The posibility to override the "install" command in makefiles. +Suggested by Oswald. + +Revision 2.514 2003/11/10 15:15:06 set +* Applied: Another batch of patches for QNX4. Sent by Mike. + +Revision 2.513 2003/11/06 19:46:21 set +* Fixed: The Uses_signal stuff in set-logo.cc example needed the inclusion +of the configuration file. Reported by Frank Liu. + +Revision 2.512 2003/11/05 16:41:49 set +* Added: Another batch of patches from Mike to support QNX4. +* Added: Uses_signal to compatlayer. + +Revision 2.511 2003/11/03 19:52:13 set +* Added: First steps toward QNX 4 support. Contributed by Mike Gorchak and +Frank Liu. + +Revision 2.510 2003/11/03 15:56:31 set +* Modified: [X11] The default font to have " and ' of the same size. +Suggested by Oswald. + +Revision 2.509 2003/11/03 15:55:17 set +* Added: A new configuration variable "AvoidMoire". This variable is +checked by TScrollBar and TBackground to avoid using chars that produce +annoying moire effects. Suggeste by Oswald Buddenhagen. + +Revision 2.508 2003/11/03 15:53:57 set +* Modified: The behavior of menu short-cuts look-up. The original code from +Borland was quite bad (never searched in the current menu) so Robert +modified it to always search in the opened menu. But this is not good when +the key is Alt+Key, in this case now the old behavior is used. + +Revision 2.507 2003/10/27 13:19:10 set +* Fixed: A bug in dlgdsn example. Patch by Frank Liu +. + +Revision 2.506 2003/10/14 16:02:13 set +* Added: A flag to TProgram to disable the Alt+N window selection. I need +it so I can make this key combination configurable in SETEdit. + +Revision 2.505 2003/10/14 15:43:11 set +* Added: A new member called reSort() to the sorted collections. It is +useful when the sorting criteria and/or key values are changed on the fly. + +Revision 2.504 2003/10/06 17:01:42 set +* Modified: To avoid remapping ASCII values under 32 for the input code +page. Reported by Alex Lozano. + +Revision 2.503 2003/09/29 16:04:38 set +* Added: Some code to detect KOI-8 FreeBSD terminals and avoid damaging +some cyrillic characters. It must be tested. From a report by Nikolai +Dershak + +Revision 2.502 2003/09/02 13:46:45 set +* Updated: QNX configuration. Patch from Mike. + +Revision 2.501 2003/08/13 20:18:47 set +* Added: Link to the BC++ and pure DOS fix release to the web page. + +Revision 2.500 2003/08/11 14:35:54 set +* Updated: Russian translation. Patch by Roman Valyushenko . + +Revision 2.499 2003/08/11 13:59:05 set +* Modified: [Configuration] to avoid including the compilation directory in +the headers path when --no-libs-here is specified. Pointed out by Ivan. + +Revision 2.498 2003/08/10 19:55:39 terrible +* Updated: Debian packaging to 2.0.2-1 version! + +Revision 2.497 2003/08/06 15:30:30 set +* Fixed: The snprintf replacement wrote to NULL pointers. + +Revision 2.496 2003/08/05 19:33:01 set +* Fixed: [X11] the "mouse" event mask I used was incomplete. This generated +problems when using the update thread because in this case the events are +retired in random order and the mask must be strict. + +Revision 2.495 2003/08/05 19:32:22 set +* Added: [X11] Another approach for the update thread using setitimer and +SIGALRM, seems to be more reliable. + +Revision 2.494 2003/08/05 19:26:24 set +* Added: [X11] a new option for this driver called UseUpdateThread. When +enabled (and support is compiled) the driver uses a second thread to handle +X11 expose events and make the cursor blink. In this way even when the +application blocks the execution the window doesn't become "black" (lack +of redraw). This is only supported for Linux and I'm using glibc's pthread +library. I'm really sad to see how bad it works, I put a long list of +problems I'm facing in the x11src.cc code. I hope all of this is just my +fault because if they are pthread limitations then Linux have a really poor +threads support. I'm looking for pthread replacements. + +Revision 2.493 2003/07/30 19:43:18 set +* Fixed: [BC++] A warning about using unsigned mixed with signed in the +demo example. Solution by ric . + +Revision 2.492 2003/07/30 14:37:36 set +* Fixed: [WinNT driver] Asterisk key not reported. Reported by "Warren H. +Holt" +* Fixed: Alt+ASCII carried the ASCII value.Reported by "Warren H. Holt" + + +Revision 2.491 2003/07/30 14:18:20 set +* Updated the web page to list the new packages. + +Revision 2.490 2003/07/29 13:22:33 set +* Fixed: fileview.cc used destroy instead of CLY_destroy. Looks like some +patch from my home CVS was missing. I also adapted all examples to use +CLY_destroy. Reported by abx@abx.art.pl + +Revision 2.489 2003/07/28 18:05:17 set +* Fixed: The configure script to accept command line optins like: +--cflags="..." without breaking the options. Reported by Ivan. +* Modified: Now the i18n catalogs are named "tvisionVERSION", it makes +easier to have more than one TV installed and remove one without altering +the other. Suggested by Ivan. +* Modified: The OS clipboard code to return translated messages. + +Revision 2.488 2003/07/28 02:53:52 terrible +* Fixed: configset didn't wait for an ENTER because the read command +required an argument. While I was there I did cosmetic changes. +* Fixed: debian/README was mising in ./lista! +* Fixed: clean the .lo files in addition to the .o ones! +* Updated: Debian packaging to the 2.0.2-0.1 version!!! + +Revision 2.487 2003/07/16 14:00:57 set +* Modified: The RPM scripts to support an environment variable to indicate +where to create the RPMs. I needed it when using S.F. Compiler Farm and +Red Hat 7.3 which always failed when using a directory mounted with NFS. + +Revision 2.486 2003/06/30 14:02:28 set +* Added: makes/rhide.env to distro. +* Added: gprexp to the genimk. + +Revision 2.485 2003/06/30 13:04:11 set +* Added: A script to update from CVS using the options I use. A DOS batch +file and a shell script are provided. + +Revision 2.484 2003/06/26 19:15:58 set +* Added: Some clarifications about install process. +* Added: Explanation about how to use the rhtv-config tool. + +Revision 2.483 2003/06/23 14:12:02 set +* Added: now is posible to indicate the installation prefix for the +makefile even after configuring another value. +* Modified: configure script to no longer remove the Makefile. +* Modified: I heavily changed the readme.txt file to reflect current status +I also moved some driver specific text to the doc directory. +* Fixed: the TStaticText class when using the center char \3 needed an +extra length. +* Added: the script to create the RPMs now ensures the other scripts are +executables. +* Added: detailed compilation instructions in individual files for each +target. They are adapted versions of the ones I provide with SETEdit. + +Revision 2.482 2003/06/18 19:58:51 set +* Fixed: [DOS] When pasting from Windows clipboard and it was empty the +routine didn't set the length to 0 returning an aleatory length. +* Fixed: Missing dgettext in international dummy. + +Revision 2.481 2003/06/17 12:48:16 set +* Added: [BC++] A simple makefile to call the main makefile and clean the +package. + +Revision 2.480 2003/06/17 12:45:00 set +* Added: A script to generate the RPMs in an easy way. +* Fixed: A misterious error in the spec file, most probably an accidental +typo. Produced when applying patch. + +Revision 2.479 2003/06/17 12:30:11 set +* Fixed: Extra lines at the end. + +Revision 2.478 2003/06/13 20:49:30 set +* Added: Files and instructions to create RPMs. They are bbcat's .spec +files with some additions and corrections. Things I'm not sure they will +remain: +1) Need of tar.bz2 file. +2) Use of package-version dir. +3) The package have a name different than Debian package. + +Revision 2.477 2003/06/09 18:54:50 set +* Modified: The maintainance rules to maintain examples/*/*.umk because +they are on CVS and not the .imk. + +Revision 2.476 2003/06/05 19:59:22 set +* Fixed: When genimk fails it must delete the partially generated .imk and +.umk to force a new generation after fixing the problems. + +Revision 2.475 2003/06/05 19:55:38 set +* Fixed: Compilation problems with MSVC 7.0. Patch from Mike. Doubt: +vsnprintf, may be the MSVC version should be lower or for all. + +Revision 2.474 2003/06/05 19:49:00 set +* Modified: A couple of C++ header requests that Andris pointed out to be +portable. I'm not sure if they are a side effect of using SSC. + +Revision 2.473 2003/06/05 19:44:25 set +* Fixed: gcc 3.3 compilation problems. Patch from Andris. It solves: +1) Order of base class constructor calls in initialization. +2) gcc no longer supports char as index for arrays. + +Revision 2.472 2003/06/05 19:33:26 set +* Modified: [Win32] Graphic driver to support environment where IDC_ARROW, +IDC_HAND and/or IDC_SIZENWSE aren't defined. + +Revision 2.471 2003/06/02 18:26:44 set +* Fixed: the configuration script generated .env files with lib paths +pointing to the old locations for the libraries. + +Revision 2.470 2003/06/02 15:09:05 set +* Added: Makefiles for BC++, they doesn't have a main makefile yet, but +you can compile the library with it. (cd makes; make -f librhtv.bmk). +* Added: Makefiles for BC++ to most examples. It doesn't mean they work, +just that they compile. A lot behave strangely or crash at exit. Looking +for volunteers to fix the problems. +* Fixed: a lot of portability details in the examples so they can compile +with BC++. + +Revision 2.469 2003/06/02 14:52:38 set +* Added: Even more checks to imk processor. + +Revision 2.468 2003/06/02 14:51:19 set +* Fixed: The compat.gpr project have relative dependencies that confused +genimk.cc. + +Revision 2.467 2003/06/02 14:49:55 set +* Added: Support for more variants of RHIDE .mak files to extrimk.cc. + +Revision 2.466 2003/06/02 14:47:15 set +* Fixed: Missing maintain.mak in distribution list. +* Fixed: Compress scripts list generation. +* Fixed: BC++ and MSVC makefiles generation, now using .imk files. + +Revision 2.465 2003/06/02 14:44:58 set +* Modified: The whole compilation mechanism. Now all is concentrated in the +"makes" directory using the mkf, imk and umk files like I did in setedit +project (check http://setedit.sf.net/ for more info). + +Revision 2.464 2003/05/30 19:38:32 set +* Modified: Removed recode detection from configure script (no longer used) +* Added: --real-prefix and --no-libs-here options for cases where the +lib is installed to a temporal directory and then moved to their final +destinations as when creating the .debs. +* Modified: To avoid debug info by default. +* Updated: readme.txt file. +* Modified: Debian package stuff to include rhtv-config and use the new +configuration switches. Also removed recode as dependency. + +Revision 2.463 2003/05/29 18:36:59 set +* Added: [BC++] Definition of __inline__ as inline in compatlayer.h. This +will avoid command line definitions. + +Revision 2.462 2003/05/29 18:24:24 set +* Modified: Now the global function destroy is called CLY_destroy, new code +should use the function with this name. For compatibility most targets +defines CLY_destroy == destroy. Exception: BC++ 5.6 which have an STL +function called destroy that collides. +* Added: [BC++] Support for BC++ 5.6 strandard C++ library. It doesn't +have filebuf::filebuf(int) (even when the manual clearly states it is +there). But it have filebuf::open(int). It also have a really bizarre +interpretation of the field used for file rights (0777 doesn't create a +file and 0666 creates a hidden file???!!). +* Added: A compatlayer define to avoid defining min/max. Looks like STL +defines them in a way that collides with the current definitions and that +the STL definition is ok for TV. So now targets can define +CLY_DONT_DEFINE_MIN_MAX to 1 and avoid the collisions. It will most +probably help Mike to compile with MSVC 7.0, was needed for BC++ 5.6. +* Added: [BC++] Some code to the example to print the compiler version and +to test the streams. + +Revision 2.461 2003/05/23 16:19:28 set +* Added: Version to the configuration tool for easy detecttion. + +Revision 2.460 2003/05/23 13:18:21 set +* Modified: To create the rhtv-config tool without .exe for UNIX systems. +* Added: Options to know the C and C++ flags used to compile the library +using rhtv-config. + +Revision 2.459 2003/05/22 19:01:25 set +* Fixed: When configuring the BC++ and MSVC makefile from DOS makefile it +failed if it was done under UNIX and the file had \r\n. From a report by +Mike. + +Revision 2.458 2003/05/21 20:57:38 set +* Fixed: Some pointer casts to use long as data type instead of int. This +is needed for 64 bits targets. The demo compile and seems to be functional +for Itanium processors. + +Revision 2.457 2003/05/21 17:42:44 set +* Fixed: [Linux] The debug log mechanism to compile with gcc 3.x. + +Revision 2.456 2003/05/21 14:38:36 set +* Fixed: [Linux] Moved the UTF-8 detection to be done after saving the +screen contents. +* Fixed: [Linux] The mpaColor to support the new "8 colors" mode. The test +program successfully run in an UTF-8 console without /dev/vcs* access. + +Revision 2.455 2003/05/21 12:41:03 set +* Fixed: TVCodePage::CreateCPFromUnicode(...) corrupted the data when +creating the LowRemap part. It was the reason for some random fails while +creating a custom code page for Linux console. +* Fixed: [Linux] I failed to detect when Linux kernel informed that the +Unicode table was bigger than 512, and the code took it as a fail. It made +the code fail for most fonts with 512 glyphs. So it failed for most UTF-8 +consoles. +* Added: [Linux] Now if we detect a font with 512 glyphs and we are using +VCS* mechanism the colors are reduced to 8 and a simple algorithm avoid +that things like "white over grey" become "grey over grey". +* Note: After fixing those two and adding this one I successfully run the +applications using an UTF-8 console and latarcyrheb-sun16.psfu.gz font. The +problems when no VCS* is available remains, but the user have an option to +get things working. + +Revision 2.454 2003/05/20 14:06:29 set +* Fixed(?): When trying to enable DEBUG logs in Linux driver and using +gcc 3.x it wasn't compilable. Not tested. + +Revision 2.453 2003/05/19 18:13:12 set +* Fixed: [Linux] if the console was in UTF-8 mode: +1) The library failed to draw some stuff during the first screen update +(until a character that needs UTF-8 was used). +2) The library didn't restore the UTF-8 probably causing problems to +another applications. +Now this is detected and if in UTF-8 the mode is reverted to single char. +The original state is restored during Suspend and memorized again in Resume + +Revision 2.452 2003/05/19 14:06:39 set +* Added: Some test programs to detect problems with Linux console handling. +I put them in the docs directory. + +Revision 2.451 2003/05/19 13:50:06 set +* Fixed: [Win32] The configure script didn't define the STDINC directories +(in fact I don't know what exactly to put there) and hence it was +imposible to compile rhtv-config.c. + +Revision 2.450 2003/05/19 13:47:58 set +* Modified: rhtv-config to report the same for dynamic and static libs in +systems where we don't support dynamic libs. + +Revision 2.449 2003/05/16 18:44:23 set +* Fixed: Forgot to remove debug print in scripts and to put some code in +djgpp version. + +Revision 2.448 2003/05/16 18:37:00 set +* Added: Workaround for problems when using CVS RHIDE, it generates +absolute paths for items in subprojects that doesn't have a target. I added +a filter to make them relative. + +Revision 2.447 2003/05/16 14:25:45 set +* Fixed: [Solaris] The use of size_t needs explicit inclusion of stdio +header. + +Revision 2.446 2003/05/16 12:39:47 set +* Added: A small tool called "rhtv-config.exe" that can be used to +determine the libraries needed to link with TV (statically and +dynamically), the path for libraries and the path for includes. I'm quite +sure it doesn't work perfectly but I was able to compile the tvedit +example using: gcc -o tvedit.exe `rhtv-config.exe --include` tvedit.cc +`rhtv-config.exe --dir-libs` `rhtv-config.exe --dlibs` +* Modified: To ever include stdc++ as library in the worst case it will be +listed twice. + +Revision 2.445 2003/05/15 18:37:08 set +* Fixed(?): msgfmt (gettext) problems: +1) It didn't reuse ~Alt-X~ Exit and let it commented. A bug. +2) The new version included in Red Hat 8.0 says the commented version is +a duplicate. From my point of view another bug, it can be marked as +information but never as an error. +Gettext is climbing to the top of most buggy tools I use. + +Revision 2.444 2003/05/15 18:14:03 set +* Modified: configset to wait for ENTER instead of sleeping 2 seconds. As +suggested by Ivan. + +Revision 2.443 2003/05/14 19:11:49 set +* Fixed: New classes and operator improperly protected against multiple +inclusion of the same header. + +Revision 2.442 2003/05/14 14:07:23 set +* Added: Three new classes that makes the use of the base classes a little +bit easier: TInput1Line, T1Label and T1StaticText. They are versions that +uses just 1 line and computes the length of the box. I also encapsulated +the i18n cache stuff there. I applied the T1Label to TV code. They are +based on TVTools ideas but implemented in a very different way. One +important detail is that T1Label and T1StaticText are slower than doing +things by hand but they are much easier to use. + +Revision 2.441 2003/05/14 13:53:37 set +* Added: TSItem::append, TMenuItem::append, operator += (TMenuItem& , +TMenuItem&), operator += (TSubMenu& , TSubMenu& ), operator += ( TSubMenu& +, TMenuItem& ), operator += ( TStatusDef& , TStatusDef& ), operator += +( TStatusDef& , TStatusItem& ), operator + ( TSItem& , TSItem& ) and +operator += ( TSItem& , TSItem& ). Most of them based on TVTools code or +inspired and reworked. +* Added: explanation about BSD code in TV and also code from TVTools to the +readme. + +Revision 2.440 2003/05/13 15:06:16 set +* Added: void *getData() member to TInputLine. It return the data member. +That's needed to compile coded adapted to the Unicode branch where the +data member is protected. + +Revision 2.439 2003/05/12 12:49:50 set +* Fixed: The TVIntl recode shouldn't recode values in the ASCII range. Not +at least for the supported code pages. + +Revision 2.438 2003/05/12 12:46:13 set +* Modified: tv.h to generate dependencies more similar to the Unicode +branch. + +Revision 2.437 2003/05/09 13:55:59 set +* Added: A check to determine if the configure script is newer than the +cache. If that's the case the cache is discarded. + +Revision 2.436 2003/05/09 12:25:05 set +* Fixed: I forgot to initialize intlLabel in inputBoxRect. +* Added: A small example for inputBox to the demo example. +* I got a copy of: Borland Turbo Vision (C++) Bug/Enhancement List created +by Marc Stern it contains a lot of bug fixes and +enhancements for TV. Most of them were already in current code and others +didn't apply (compiler dependent or related to obsolete stuff). But I +applied: +* inputBox enhancements: size according to contents and centered buttons. +* TDialog enhancement: support for TDialogs inside TDialogs (palette trick). +* TGroup enhancement: more robust when faulty code selects an unselectable + or hidden item and the group is shutDown(). Marek Bojarski + idea. +* TGroup fix: setCurrent didn't verify if the focus really changed. +* TWindow enhancement: if arrows aren't used by the focused TView and they + reach the TWindow then they behave as Shift/Tab (change focused). Seems to + be useful. +* tvutils.h enhancement: defined min/max for any data type (using + templates). Vincent Van Den Berghe idea. + +Revision 2.435 2003/05/07 19:37:55 set +* Added: [Linux] Now the Ctrl+Tab is mapped to Tab so TV applications can +use it. + +Revision 2.434 2003/05/05 13:28:59 set +* Added: A warning to configset as I did for DOS' batch. + +Revision 2.433 2003/05/05 13:26:35 set +* Added: A warning to configset.bat because people thinks thats "set +configuration" and not "configuration for SET" ;-) +* Added: Now if shell utils aren't installed (I think djgpp is the only +that can lack it) the configuration stops and explains the problem. +* Fixed: [DOS] snprinf and dos/mouse code needed strings.h when using SSC. + +Revision 2.432 2003/04/30 18:18:49 set +* Fixed: When doing incremental searches in sorted list boxes some times +the cursor disapeared. + +Revision 2.431 2003/04/25 19:43:36 set +* Fixed: [X11] Under some situations after a resize the cursor disapear. +Now I added an explicit enable. + +Revision 2.430 2003/04/25 16:41:52 set +* Fixed: The TSortedCollection trapped ENTER in some particular cases. +* Fixed: X11 driver using Unicode translatio even when X11 didn't support +it. + +Revision 2.429 2003/04/22 15:46:04 set +* Fixed: SSC stuff when using gcc 3.x. Tested on Cygwin using gcc 3.2. With +SSC the time was reduced 65%! (about 3 times faster!). Even with it the +compilation time is the double of the time using Linux. + +Revision 2.428 2003/04/22 15:16:03 set +* Added: An optional replacement for C++ streams. This is a very small and +incomplete replacement, but is enough to compile TV and SETEdit. With this +replacement and some changes added the library can be compiled without +using even one standard C++ header. I tested it moving the whole C++ +include directory away. The main idea is to reduce the size for target +using only static libs and also to reduce the compilation time. For gcc +2.95.4 running on Linux I got a 20% reduction of compilation time. +To enable it you can use --with-ssc configuration option, but remmember +that's experimental. + +Revision 2.427 2003/04/21 18:03:14 set +* Added: Some documentation about the new TVIntl API. + +Revision 2.426 2003/04/21 16:56:56 set +* Fixed: Alt-X Exit wasn't marked for translation. +* Added: An i18n example. +* Fixed: Crash when using i18n and not hooking code page callback. +* Added: Now when a translation can't be found in the current domain TV +tries in "tvision" domain. It allows separated catalogs for the application +and the library avoiding duplication. +* Added: Member to initialize i18n providing a directory to search and some +tricks used in RHIDE and SETEdit. + +Revision 2.425 2003/04/21 16:37:19 set +* Fixed(?): Use of \r in i18n messages. This is a really bad limitation. + +Revision 2.424 2003/04/21 16:17:16 set +* Added: Support for the new i18n API to TColorGroup and TColorItem. +* Added: snprintf and fprintf members to TVIntl. They transparentlty +translates and recodes the format string. +* Modified: i18n makefile to stop generating *_iso* files. +* Updated: spanish translations, also fixed a few russian translations, the +obvious ones because of cformat changes ;-) + +Revision 2.423 2003/04/21 16:13:33 set +* Added: Some comments about TV streams in the doc directory. They are +really small but includes an ASCII graphic showing the hierarchy. +* Modified: TEditorApp to use messageBox as a printf instead of using +strstreams. Now it can be done safetly because we use snprintf. + +Revision 2.422 2003/04/21 16:08:02 set +* Fixed: [Cygwin] it have snprintf, no need for replacement. It makes DJGPP +the only one without it, I guess it will be solved in 2.04. + +Revision 2.421 2003/04/21 15:46:31 set +* Fixed: The snprintf replacement (coded by Caolan McNamara +, thanks Caolan!) didn't return the expected value. +According to modern implementations (like GNU one) it must return the +number of characters we should write the buffer if it have enough space and +not the ammount we wrote. I hope my changes are ok ;-) + +Revision 2.420 2003/04/21 15:29:04 set +* Added: Dummy versions of the TVIntl members for systems without gettext. + +Revision 2.419 2003/04/21 14:38:43 set +* Fixed: unused variable. + +Revision 2.418 2003/04/16 20:10:31 set +* Added: adapted the messageBox to the new i18n API. +* Modified: messageBox to use snprintf instead a fixed size buffer. +* Added: a snprinf replacement for systems without it, untested. + +Revision 2.417 2003/04/15 15:30:44 set +* Modified: Files distribution list to reflect new QNX package. + +Revision 2.416 2003/04/15 15:17:44 set +* Fixed: The new intl.h header only worked for C++ code but the +configuration script tests it using C code. Now it also defines things for +C code. Reported by Mike. + +Revision 2.415 2003/04/15 14:42:22 set +* Patches from Mike: +* Added: [QNX] pterm specific functions for more keycombination detect. Now +running TV app under pterm have the same functionality as running under raw +console. +* Fixed: [QNX] russian text inputing, tested on CP866/WIn1251/KOI8-R. +* Added: [QNX] more to QNX.txt ;) will be much more in future. +* Updated: [QNX] package generation data. +* Fixed: Lack of check in xgettext and recode tests and wrong link to dummy +intl lib. + +Revision 2.414 2003/04/10 21:34:40 set +* Fixed: TVCodePage::FillGenericRemap must be ready to be called even +before the code page module is initialized. + +Revision 2.413 2003/04/10 21:26:43 set +* Updated: DOS project. +* Fixed: [DOS] use of _() return value as char *. + +Revision 2.412 2003/04/08 19:07:42 set +* Added: Now added support to TButton and TWindow/TDialog. + +Revision 2.411 2003/04/08 15:19:43 set +* Added: A dummy include/tv/parttree.h file to avoid dependencie problems. + +Revision 2.410 2003/04/08 14:05:45 set +* Added: Support for the new i18n features to TStaticText it affects +TLabel and TParamText(partially). + +Revision 2.409 2003/04/07 13:39:55 set +* Added: Support for the new i18n features to TCluster it affects +TCheckBoxes and TRadioButtons. + +Revision 2.408 2003/04/07 13:39:03 set +* Fixed: The dialog design example to use the new API style. + +Revision 2.407 2003/04/07 13:36:47 set +* Modified: Now TMenu and TStatusLine are "i18n award". It means that when +translations are enabled these classes translates their strings on the fly +using caches to avoid useless searchs. It also supports code page changes +transparently because the cache is invalidated and fresh translations are +retreived. +* Modified: Version to 2.0.2 because that's an important change for +applications as SETEdit and RHIDE. + +Revision 2.406 2003/04/07 13:32:43 set +* Added: A new class TVIntl to handle all the gettext mess. The GNU gettext +library is a mess and a source of problems and limitations. For this reason +I isolated all of this in a class that will also provide clean recoding +of catalogs. + +Revision 2.405 2003/04/03 20:08:26 set +* Modified: The following patch enforces the use of the return value of +gettext (intl library) as a const char *. + +Revision 2.404 2003/04/02 13:35:49 set +* Fixed: [MinGW] The configuration script shown the error messages created +when running non-existent programs appear in the screen generating +confusion. Now the command are executed redirecting stderr. + +Revision 2.403 2003/04/02 13:34:49 set +* Fixed: [BC++] Warning about unused parameter in tgkey.cc. + +Revision 2.402 2003/03/20 20:33:10 set +* Fixed: intl lib configuration for QNX. Patch from Mike. + +Revision 2.401 2003/03/18 16:27:55 set +* Fixed: Some TEditorApp messages include a file name but the +doEditDialogDefault function used an 80 bytes buffer. Reported by Mike. + +Revision 2.400 2003/03/18 16:03:17 set +* Fixed: QNX details, patch from Mike. + +Revision 2.399 2003/02/05 13:43:51 set +* Modified: The default TMouse::resume behavior to restore the buttonsCount +member. It allows calling suspend/resume when using drivers that doesn't +implement it. This is needed for legacy applications as reported by Andris. + +Revision 2.398 2003/02/05 12:27:19 set +* Fixed: [DOS] The Windows clipboard paste requested plain text instead of +OEM text. This skipped the code page translation. Reported by Thiago. + +Revision 2.397 2003/02/02 01:09:33 terrible +* Updated: Debian packaging to version 2.0.1-1 "Columbia". + +----------------------------- 2.0.1 Release ------------------------------ + +Revision 2.396 2003/01/24 12:37:58 set +* Fixed: [X11] Some times when resizing a window we get an expose event for +the new size before the application gets the resize notification. It can +fool the redrawing mechanism. As the application will redraw the screen +soon there is no point in executing the expose event, so these events are +ignored until the TApplication receives the notification. Reported by +Andris, it wasn't easy to reproduce. + +Revision 2.395 2003/01/16 20:15:58 set +* Fixed(?): Bug in the TEditor class. It looks like the condition that +paints the empty part of the lines was wrong and didn't paint lines longer +than half the width. Reported by Frederic BARBAISE +. + +Revision 2.394 2003/01/10 13:21:14 set +* Fixed: Cyrillic examples had wrong key assigned to Exit (typo). Roman +found it. + +Revision 2.393 2003/01/08 13:45:40 set +* Modified: Small optimization in TMenuView::findItem to avoid searching +for ch==0. Proposed by Roman. + +Revision 2.392 2003/01/08 12:49:30 set +* Fixed: [UNIX] In some cases the headers are included even when a driver +isn't supported just to keep the propper dependencies. Some of the UNIX +headers uses sig_atomic_t defined in signal.h, now included. Reported by +Roman and Dejan Lekic (dejan). It needs more testing. + +Revision 2.391 2003/01/07 13:16:26 set +* Updated: Russian translation. From Roman. +* Fixed: tvedit3.cc had two messages almost identical, now merged. Pointed +out by Roman. + +--------------------------- 2.0.1 Release Candidate 2 ---------------------- + +Revision 2.390 2002/12/27 12:42:13 set +* Added: Workaround for problems with SuSE when including libintl.h +(__THROW interferes with default prototypes). Reported by Grzegorz. + +Revision 2.389 2002/12/19 17:29:43 set +* Updated: Russian translations. Contributed by Roman Valyushenko + +* Updated: List of changes in 2.0.1. +* Fixed: Wrong links in web page. Reported by Michel Catudal +. + +Revision 2.388 2002/12/17 14:23:26 set +* Fixed: [X11] I used Xutf8LookupString without realizing that's an +XFree86 4.0.2+ extension. Added conditionals for it (untested). + +--------------------------- 2.0.1 Release Candidate 1 ---------------------- + +Revision 2.387 2002/12/16 13:30:05 set +* Fixed: Extra .mak file in files list. + +Revision 2.386 2002/12/14 22:57:31 terrible +* Updated: Debian packaging to version 2.0.1-0.2. + +Revision 2.385 2002/12/13 18:11:40 set +* Added: A new example: A Borland's Help file browser. It can display TC++ +and BC++ help files. Contributed by Jan Van Buggenhout + +Revision 2.384 2002/12/12 19:02:57 set +* Modified: [DOS] Removed the old greek keyboard hack, the generic approach +should work for all drivers. + +Revision 2.383 2002/12/12 19:01:39 set +* Added: A generalized mechanism to interpret Alt+Non-ASCII. So now in a +greek keyboard Alt+Chi is converted to Alt+X and in a russian keyboard +Alt+Che is also converted to Alt+X ... may be some day Alt+SA will be Alt+X +in a japanese keyboard ;-), but that will need much more work. + +Revision 2.382 2002/12/11 12:41:07 set +* Modified: I generalized the TGKey::defaultSetCodePage, it now supports +russian and greek keyboards for various code pages. This code allows +accessing to menues even when the user is in the "alternate mode" (i.e. +Alt+A <-> Alt+Alpha). + +Revision 2.381 2002/12/10 19:47:53 set +* Modified: THelpFile::getTopic to be virtual as suggested by Chipzz +. + +Revision 2.380 2002/12/10 18:10:43 set +* Modified: Allocated separated internal codes for cyrillic and greek +letters that are identical to latin ones. This wastes memory but simplifies +some stuff. +* Added: [X11] Russian and Greek keyboards seems to work ok (my keyboard +now is US+Japanese+Russian+Greek ;-). You just need to select the propper +code page. + +Revision 2.379 2002/12/10 14:15:46 set +* Fixed: [X11] The new code to handle input code page (return value). +* Fixed: [X11] I relaxed the filter too much in the last patch ;-) + +Revision 2.378 2002/12/09 18:21:32 set +* Modified: [X11] The filter that avoids reporting ASCII values for +ALT+key. It was too strict making fail the KOI8R mode, so now Alt+A and +Alt+EF (cyrillic) are a valid shortcuts for a menu with A or EF. + +Revision 2.377 2002/12/09 17:49:21 set +* Modified: [X11] To read the keyboard using Unicode. So now the driver +uses a conversion from Unicode to the current input code page. With this +I got an almost working "russian keyboard". The problem is in my +oversimplification used for the fonts where cyrillic characters with the +same shape as latin characters are expressed as latin characters ... + +Revision 2.376 2002/12/09 14:45:34 set +* Added: [Linux] A configuration variable to indicate the console fails to +implement the cursor shape escape sequences. It seems to happend with some +frame buffers, as reported by Martijn. The variable is called +BrokenCursorShape. + +Revision 2.375 2002/12/09 13:14:00 set +* Modified: [Win32] unistd requested unconditionally, is needed for all the +Win32 targets. + +Revision 2.374 2002/12/09 13:10:26 set +* Fixed: MinGW doesn't define its version using gcc itself, so we must +include at least _mingw.h. This is an error in MinGW. + +Revision 2.373 2002/12/09 13:04:55 set +* Fixed: [DOS] The greek mode stuff. It must be moved but right now is +better to let it work like this until I have some greek tester ;-) +* Tested with gcc 3.2.1 OK + +Revision 2.372 2002/12/09 13:03:29 set +* Fixed: [DOS] Typos in untested code. Also reverted some keyboard +variables just to compile the code, they should go away. + +Revision 2.371 2002/12/06 19:49:12 set +* Fixed: [Win32] lack of unistd due to the new use of dup2. Patch by Igor +Gnip. +* Fixed: The examples/Makefile to clean in sub-sub directories. Patch by +Igor Gnip. + +Revision 2.370 2002/12/06 16:12:12 set +* Fixed: [Win32] typo in WinGr driver. + +Revision 2.369 2002/12/04 21:18:22 terrible +* Updated: Debian packaging to 2.0.1-0.1. + +Revision 2.368 2002/12/03 12:30:20 set +* Added: A way to indicate we want to load secondary fonts at start-up. +They must be provided by the font callback as the primary. I added code to +X11, Linux and DOS drivers for it. The last is untested. +* Fixed: The Linux driver failed when resquesting to just load the +secondary font. + +Revision 2.367 2002/12/03 12:29:34 set +* Added: TListView now does PageUp/Down with the mouse wheel. +* Added: Text selected in TInputLines is copied to the selection clipboard. + +Revision 2.366 2002/12/03 12:28:29 set +* Modified: The GetKbdMapping behavior. Now it must be called for each +setting individually and can be redefined by each driver. + +Revision 2.365 2002/11/29 12:49:07 set +* Modified: Moved CLY_Beep to TScreen::Beep. It allows drivers that needs +access to low level stuff to define it properly. X11 is a clear case, you +must have access to the display. + +Revision 2.364 2002/11/28 20:49:55 set +* Fixed: [X11] The driver reported the wrong kind of flags for key +modifiers in the event structure. + +Revision 2.363 2002/11/28 18:42:26 set +* Fixed: The files list said intl/dtou.pl instead of intl/utod.pl. + +Revision 2.362 2002/11/28 17:53:40 set +* Fixed: [X11] Squash! finally killed the f*cking bug. It was the mother of +race conditions. The strange thing is how useless was efence to detect it. +The problem was that for a small portion of time the TProgram::buffer +pointer was out-of sync with TScreen::screenBuffer. It was between the +realloc (note it could reuse the memory and add more randomness) and the +momment where TProgram detected the resize. A draw to the TProgram space +confused the buffer and tried to use it corrupting memory. Now the X11 +driver just signals the window changed and wait until TProgram asks for +it before changing anything. + +Revision 2.361 2002/11/27 20:52:32 set +* Fixed: [X11] When the window manager forces the window size during +initialization a race appears between the path to reach the point where +TProgram asks for the new window size and other draw routines that asks +for the current screen width/height. This is fixed and may be needed by +other drivers. But the driver still crash if the WM forces the size. I +don't know why but the crash is inside X lib. Efence doesn't show any kind +of memory corruption. Looks like a missuse of the Xlib API. + +Revision 2.360 2002/11/27 17:24:28 set +* Added: Now the TScreen::System member can take 3 optional arguments. They +are used to redirect the stdin, stdout and stderr file handles of the child +process. This is achieved using dup2 after spawning the child. If the value +is -1 the handles are shared as before. Tested only for Linux. +* Added: Testing code to the Linux driver to try using a separated file +handle for output. This approach is cleaner but lamentably something is +wrong and I must disable the buffering losing performance (5 times slower). +For this reason it isn't used. + +Revision 2.359 2002/11/27 13:14:24 set +* Added: Now the ~ at the beggining of a file name is expanded in a similar +way used by UNIX shells. CLY_IsRelativePath() returns 0 and _fixpath() (it +is used by CLY_fexpand()) expands it. Win32 (unless Cygwin) is an +exception. If the ~ is followed by anything but a dir separator or the end +of the name it isn't expanded (~Name pass unmodified). If the HOME +environment variable isn't defined it isn't expanded. Martijn suggested +expanding ~. + +Revision 2.358 2002/11/26 12:53:29 set +* Changed version to 2.0.1 to make a maintainance release during the next +weeks. +* Modified: [WWW] version and history. + +Revision 2.357 2002/11/26 12:52:50 set +* Added: The new X11 cyrillic example to the readme and the makefile. + +Revision 2.356 2002/11/25 15:06:47 set +* Added: The creation and installation of es.mo and ru.mo files from +spanish and russian translations. + +Revision 2.355 2002/11/25 15:03:12 set +* Added: TGKey now have a member to set the code page for the translation +tables. +* Added: TVCodePage calls TGKey::SetCodePage. +* Fixed: TMenuView didn't use the TVCodePage toupper/lower system. +* Modified: Moved KOI8r tables from Linux driver to TGKey, so they can be +shared with X11 driver. +* Added: An example showing how to force cyrillics for X11 applications, it +also works for Linux console and should work for DOS. + +Revision 2.354 2002/11/25 14:59:02 set +* Fixed: In systems using ACMs with unknown Unicodes the translation table +got 0xFFFF and when using it some memory corruption could appear. Reported +and investigated by Martijn Versteegh. + +Revision 2.353 2002/11/05 14:49:33 set +* Added: [WWW] a link to Sigala's documentation and a comment about the +documentation for the new classes. + +Revision 2.352 2002/11/05 13:27:36 set +* Modified: [Win32] [WinGr driver] Console release in constructor. Patch by +Pawel Piecuch . +* Fixed: [Win32] [WinGr driver] Control characters passed with ASCII +attached. Patch by Pawel Piecuch . + +Revision 2.351 2002/11/05 13:12:26 set +* Fixed: The Linux driver initialization could use a NULL pointer to delete +a requested font. + +Revision 2.350 2002/11/05 13:00:33 set +* Added: Support for DBCS systems at compile level in codepage.cc code. +More adjusts could be needed. Related to SF FR #633611 by Kirby Zhou +(kirbyzhou). + +Revision 2.349 2002/10/15 19:57:41 set +* Added: Roman to contributors lists. + +Revision 2.348 2002/10/15 19:53:26 set +Added: Russian translation for the messages. Contributed by Roman +Valyushenko. + +Revision 2.347 2002/10/08 20:40:23 set +* Added: [WWW] Now the .zip file is also available from Simtel network. + +Revision 2.346 2002/10/07 20:02:37 set +* Modified: Release details in the web pages. + +----------------------------- 2.0.0 Release ------------------------------ + +Revision 2.345 2002/10/07 15:19:01 set +* Fixed: [Win32] X11 library path. + +Revision 2.344 2002/10/04 00:57:50 terrible +* Updated: Debian packaging to version 2.0.0-1. + +Revision 2.343 2002/09/30 20:08:35 set +* Updated: The list of strings to translate and the spanish translation. + +Revision 2.342 2002/09/30 20:06:48 set +* Fixed: SDG modules must use "Comments" and not "Description". +* Added: More documentation. That's far from complete, even when the +objetive is to document only new stuff. But is an start. + +Revision 2.341 2002/09/27 13:46:39 set +* Modified: [X11] The methode used to make the cursor blink. Using sigalarm +the sleep funtion stops working, according to GNU library docs it shouldn't +happen, but in most libc implementations could. So now what I do is just +check the current time. I think that's slower, but safer. + +Revision 2.340 2002/09/25 20:29:01 set +* Modified: The readme file to be more clear about what is supported and +what to read. +* Removed: All MSVC files found in win32 directory. They are outdated and +now replaced by the nmake files found in winnt directory. +* Added: More clarifications to the winnt/readme.txt file. It had wrong +information about how to proceed when using MSVC. + +Revision 2.339 2002/09/25 19:39:04 set +* Fixed: [MSVC] Now gdi32.lib is also needed (for the WinGr driver). +Reported by Sergey Krivulja + +Revision 2.338 2002/09/23 16:02:03 set +* Added: Daily snapshot to the web site. + +Revision 2.337 2002/09/23 15:56:37 set +3 Patches and/ot Reports from Igor Gnip : +* Fixed: Removed unused variable in classes/tfilelis.cc. +* Fixed: Changed NAME_MAX by PATH_MAX in examples/tvhc/tvhc.cc, it is +defined for all targets. +* Fixed: Changed the use of sleep in examples/msgcls/testdyn.cpp to use the +CLY_YieldProcessor function. + +Revision 2.336 2002/09/23 14:11:35 set +* Fixed: Disabled TButtons with default flag ignored the disable state. +Patch from Hartmut Welpmann , originally done by +Marc Stern. + +Revision 2.335 2002/09/23 12:41:24 set +* Added: More documentation to the codepage.cc file. +* Added: A SETEdit project and SDG configuration to generate some +documentation in HTML format. It is just oriented to the new stuff added +and isn't complete. + +Revision 2.334 2002/09/23 12:37:24 set +* Added: Win32 and WinGr documentation. +* Modified: X11 docs, added the fact that X11 driver can be used for Win32. + +Revision 2.333 2002/09/23 12:34:24 set +* Added: DOS driver, code pages and configuration file documentation. +* Modified: Added most structure to all the other docs. +* Modified: [DOS] Made PollMouse=1 and SaveVGAState=0 the defaults. I think +this gives more chances to get things working in the first try. If the user +wants to get better support s/he can read the docs. + +Revision 2.332 2002/09/23 12:32:28 set +* Fixed: [X11] The 27 to 31 ASCII range wasn't mapped to any key, they are +used for ^{ ^\ ^} ?? ^/. + +Revision 2.331 2002/09/23 12:31:54 set +* Added: A mechanism to set the name of the configuration file from the +user application side. It allows to have special configuration files for +particular applications. + +Revision 2.330 2002/09/23 12:31:09 set +* Added: [Linux] more details about why the 512 chars system used by Linux +isn't the same that TV needs. From a talk with Tapio. + +Revision 2.329 2002/09/19 18:06:38 set +* Fixed: static const class members looks like a logic construction and g++ +understands it, but it seems to be a non-standard thing and MSVC doesn't +undertsand it. I changed it by the "anonymous enum" trick. From a report by +WintiX. + +Revision 2.328 2002/09/18 20:01:28 set +* Added: [Linux] driver documentation, this is a tricky driver and needs a +lot of explanations. Isn't revised, it means it can contain all kind of +stupid information ;-) + +Revision 2.327 2002/09/18 12:28:29 set +* Fixed: [DOS] I restored the screen after releasing the memory used to +hold the old content :-P it generated random artifacts in upper left corner +of the screen at exit. +* Added: [DOS] Two configuration options: SaveVGAState, it can be used to +disable the VGA state save/restore mechanism. When disabled the support for +restoring graphic modes is limited, but the simple text modes aren't +affected. And another option called VGABIOSState disabling it (but not the +other) the save/restore mechanism uses an internal routine I coded. This +routine uses the VGA registers for it. This needs a 100% VGA compatible +board or a Win32 driver that fully emulates a VGA board when running in +Win32 environments. + +Revision 2.326 2002/09/17 13:00:29 set +* Fixed: [MinGW] Some perl interpreter returns paths with back slashes and +MSYS tools doesn't tolerate mixed slashes. + +Revision 2.325 2002/09/16 20:51:38 set +* Added: [Cygwin] The X11 libraries seems to be linked statically and I +don't know how to do it dynamically. It pulls various X libraries like +Xt, SM and ICE. As a workaround I added them to the list of libraries. The +demo compiles for Win32 using X11 driver!! + +Revision 2.324 2002/09/16 19:18:40 set +* Modified: eliminated the direct use of alloca in C++ code. Now the code +calls AllocLocalStr giving more chances to hide the implementation. +* Modified: [MinGW] when version is >=2 I define alloca as __builtin_alloc. +Looks like MinGW people didn't define alloca in headers, even when that's +a builtin gcc "function". It isn't tested by I tried to strictly enclose it +using __MINGW32_MAJOR_VERSION>=2. From a report by Igor Gnip +. + +Revision 2.323 2002/09/16 15:55:20 set +* Added: A new configuration option "DontMoveHiddenCursor". It disables the +Braille Terminal helper in favor of speed. + +Revision 2.322 2002/09/16 15:34:18 set +* Modified: The cursor behavior to help "Braille Terminals". Now the cursor +is moved even when it isn't visible. This is complemented with this patch +from Tapio. + +Revision 2.321 2002/09/16 14:48:53 set +* Fixed: Our TV includes TFileViewer in the library so I also fixed the +delta bug there. + +Revision 2.320 2002/09/16 14:39:40 set +* Fixed: The file viewer of the demo program didn't initialize the delta +member generating aleatory memory corruptions. Seen on Cygwin and MinGW. + +Revision 2.319 2002/09/16 14:34:39 set +* Modified: [WinGr] priority to be the second option until the driver is +finished. + +Revision 2.318 2002/09/16 14:33:35 set +* Fixed: [CygWin/MinGW] Both of them needs libgdi32 for the new WinGr +driver. + +Revision 2.317 2002/09/16 14:31:58 set +* Removed: The .mak files named in "lista" they are added by the +compression script. + +Revision 2.316 2002/09/16 14:31:19 set +* Fixed: [X11] When resizing the font I informed to the WM about the new +cell size but I forgot to inform about the new minimal size. At least +Enlightenment took it in a very funny way: computed the minimal size + the +delta multiplied by the new cell size. It generated a negotiation between +the application and the WM to converge in a wrong size. +* Added: [X11] Information about the base size. At least E uses it to +inform the window size in cells. If we don't set it the size reported is +the current size minus the minimal size (40x5 for 80x25). +* Added: More documentation to the X11 driver doc. + +Revision 2.315 2002/09/16 14:30:33 set +* Added: [XTerm] A new configuration option called "UseShellScreen". It +could help if someday we compile an RHIDE with TV 2.0.0 and want to use it +running on a XTerm/Eterm. +* Added: XTerm driver documentation and corrected some Eterm details. + +Revision 2.314 2002/09/16 14:29:41 set +* Added: [XTerm] Support for "application mode" keys (4 arrows, home and +end). Also modified the Xterm.res script to use them. These keys works ok +for bash (readline) and mc (slang?). +* Added: [XTerm] A correct color palette to the Xterm.res script the one +used by xterm in my system doesn't match VGA BIOS. + +Revision 2.313 2002/09/16 14:28:55 set +* Added: Eterm driver information to "doc" directory. +* Modified: The Eterm theme and moved to an independent directory. Is quite +functional. +* Fixed: [Eterm] The SetWindowTitle() methode is not the same as used by +XTerm. +* Fixed: [Eterm] GetCurrentFontName() doesn't work on Eterm, must return +error. If I don't do it Eterm thinks I want to set a font called "?". + +Revision 2.312 2002/09/16 14:26:33 set +* Added: Experimental support for X11 under Win32. I just enabled the code +for Cygwin, isn't tested. + +Revision 2.311 2002/09/16 14:25:07 set +* Modified: [UNIX] now the priority for linking the examples is: (1) +installed libraries, (2) compiled dynamic and (3) compiled static. It +implies the user must install the libraries if s/he had an old version +installed. But this is the standard procedure. The advantage is smaller +examples and at the same time you can test small changes without linking +the examples again and again, even without installing using LD_LIBRARY_PATH +* Removed: redundant argument of the configure script. +* Modified: the help of the conf. script, now is easier to find what you +want. +* Added: a configuration option to install the dynamic libraries without +running strip. +* Fixed: [Linux] the driver always *must* detect the code pages to use them +as defaults, it can't be skiped. + +Revision 2.310 2002/09/13 18:55:58 set +* Modified: [X11] Now the busy indicator shape is just XC_watch by default, +using a configuration variable you can select Roman's cursor. Suggested by +Ivan to allow better integration with the desktop. + +Revision 2.309 2002/09/13 17:04:17 set +* Fixed: X11 detection mechanism. It failed for Darwin. +* Fixed: other small configuration detail seen on Darwin. + +Revision 2.308 2002/09/13 12:26:29 set +* Modified: [DOS] The mouse handler un/hook methode. I got nasty GPFs with +the old code. I also disabled some code in TVApplication that shouldn't +be there. Some problems still there. + +Revision 2.307 2002/09/13 12:25:02 set +* Fixed: The dummy international library used "gcc" inconditionally. Now is +configured. +* Added: Support for ranlib separated of ar. Darwin seems to have a POSIX +ar that doesn't support -s, untested. +* Added: -Wno-long-double option when Darwin is detected. +* Added: Defaults to the AlphaTable, toLowerTable and toUpperTable tables. +In this way they can be used before initialization when we just need ASCII +information. + +Revision 2.306 2002/09/12 21:08:56 set +* Fixed: XTerm driver needs UNIX mouse code, changed conditionals. + +Revision 2.305 2002/09/12 21:03:42 set +* Fixed: XTerm driver included an uneeded ncurses header. + +Revision 2.304 2002/09/12 21:00:03 set +* Modified: The UNIX driver headers to be excluded if ncurses isn't +available. + +Revision 2.303 2002/09/12 20:51:22 set +* Modified: The configuration and code to make the UNIX driver optional. + +Revision 2.302 2002/09/12 19:34:15 set +* Added: Spanish translations for most of the TV messages. + +Revision 2.301 2002/09/12 18:10:32 set +* Added: A correct "default code page" mechanism to DOS, Linux, QNX, UNIX, +Win32, WinNT, X11 and XTerm. WinGr needs more things and this isn't +currently appliable. + +Revision 2.300 2002/09/12 01:13:13 terrible +* Fixed: [X11] Release X11 resources on driver destruction. +* Updated: Debian packaging to version 2.0.0-0.5. + +Revision 2.299 2002/09/11 18:50:26 set +* Added: __ppc__ as a PPC identifier + +Revision 2.298 2002/09/11 18:25:17 set +* Added: Darwin to the list of known OSs, is just to test. +* Verified compilation and functionality for: ++ Debian GNU/Linux 3.0 Alpha EV67 (Tsunami Catamaran) COMPAQ AlphaServer +DS20E 666 MHz. ++ Debian GNU/Linux 3.0 PPC 604ev5 (MachV) CHRP IBM,7043-150. ++ Debian GNU/Linux 3.0 SPARC Ultra60 TI UltraSparc II (BlackBird) Spitfire ++ Solaris SunOS 5.8 Sun E220R. +All using xterm+ssh started with the script found in examples/xterm. + +Revision 2.297 2002/09/11 16:46:24 terrible +* Fixed: XOpenDisplay should receive NULL instead of "". + +Revision 2.296 2002/09/11 16:20:13 set +* Fixed: TCommandSet handles 32 bits values but defined them as "unsigned +long", they are 64 bits in Alpha machines. + +Revision 2.295 2002/09/11 15:04:59 set +* Fixed: [Linux] TDisplayLinux::GetCursorShapeMDA undefined for non x86 +platforms. + +Revision 2.294 2002/09/11 12:54:54 set +* Added: isLower, isUpper and isAlNum to TVCodePage. + +Revision 2.293 2002/09/10 20:36:52 set +* Fixed: The colors dialog used TEvent´s infoByte field, but it was loaded +from an unsigned value. This is OK for little endian, but in big endian +machines doesn´t work. I removed all the infoByte code and replaced it by +infoLong usage loading with long values. + +Revision 2.292 2002/09/10 20:14:21 set +* Added: Support for endian differences in font files. Now the fonts can +be generated using little or big endian machines, the loading routines +detects it and does the needed conversions. Tested on Solaris (in fact I´m +using the fonts with SETEdit to write it, the editor is running on an Ultra +60 machine and the output is in mine Linux box :-) + +Revision 2.291 2002/09/09 13:31:35 set +* Fixed: The wheel increment wasn't setup for scroll bars loaded from disk. +Currently they are just setup with the default value to avoid breaking the +compatibility with all programs. + +Revision 2.290 2002/09/06 18:26:15 set +* Added: Mouse wheel support to TScroller. + +Revision 2.289 2002/09/06 17:56:16 set +* Fixed: TFileList used an ole methode to determine if the shift key was +pressed. Reported by Ivan. + +Revision 2.288 2002/09/06 14:22:13 set +* Added: Workaround for broken KOI8-R systems (looks that's the most common +case) where the SFM and ACM doesn't use Unicode, or uses Unicode mixed with +KOI8. Also added the test data. + +Revision 2.287 2002/09/06 00:08:13 terrible +* Updated: Debian packaging to version 2.0.0-0.4. +* Note: it seems that the library is binary compatible with the 0.3 version, +interesting! + +Revision 2.286 2002/09/04 20:25:23 set +* Modified: The messageBox now temporally disables the "busy indicator". +* Fixed: [X11] The busy indicator didn't flush the X commands. + +Revision 2.285 2002/09/04 15:30:22 set +* Fixed: TInputLine must let pass kbEnter and kbTab no matters what ASCII +they contain. Currently when the input code page doesn't match the +application code page Enter and Tab can contain ASCII values over 32. +* Fixed: [Linux] OS code pages are detected not only when App and Scr +aren't forced, this is computed when any of them is missing. + +Revision 2.284 2002/09/04 13:11:34 set +* Added: Insert with middle button to the TinputLine class. It works for +any OS supporting an auxiliar clipboard. Currently that's only for X11. To +achieve it I added a new member called insertChar and another called +makeVisible. They reuse the keyboard char input code. + +Revision 2.283 2002/09/03 13:44:24 set +* Fixed: TVConfigFile::AddString added integers, I found it when the editor +failed to set the palette as a string ;-) + +Revision 2.282 2002/09/02 13:52:37 set +* Fixed: Various code page and font details to avoid problems in case of +fails. +* Fixed: [X11] the default font shouldn't be replaced by the ones from the +application and they must be freed. + +Revision 2.281 2002/09/02 13:51:48 set +* Added: [DOS] BIOSKey configuration option. + +Revision 2.280 2002/09/02 13:50:46 set +* Fixed: [WinGr] When I patched the code to avoid the unsigned use as +signed in setCharacters I didn't noticed JASC was using it to force a +redraw. So now I replaced the hiden trick using an explicit variable. + +Revision 2.279 2002/08/29 20:45:44 set +* Fixed: [Win32] wingrdis needed stdlib to compile using MinGW. I noticed +I must add gdi32 library, but is 1 AM and I'm really tired. It only +compiles the BC++ 5.5 and MinGW executables crash. + +Revision 2.278 2002/08/29 20:44:42 set +* Fixed: [Win32] various warnings and errors reported by BC++ 5.5 in the +new driver. One of them was a real error (use of an unsigned value as +signed). I didn't test functionallity, just compilation. + +Revision 2.277 2002/08/29 20:43:34 set +* Added: The new WinGr driver to the DOS, Win32 BC++ and Win32 MSVC +makefiles. +* Fixed: A couple of compilation details under DOS. + +Revision 2.276 2002/08/29 20:40:20 set +* Added: showBusyState member to TScreen. That's a way to show the user +some kind of feadback when the application is busy. Currently only the +X11 driver implements it showing a different mouse cursor. The idea and +the X11 code was contributed by Roman Valyushenko. +* Added: example on how to use it and also window title and code page +examples to the progress bar example. + +Revision 2.275 2002/08/29 20:39:00 set +* Added: Thanks to JASC for the new driver. +* Added: The new files to the distribution. +* Added: [Linux] More debug information to the code page autodetection. It +is currently broken and I don't know if it will work, looks like Linux +kernel doesn't offer the needed information (broken by design). +* Modified: The cyrillic test to bypass the autodetection. + +Revision 2.274 2002/08/29 20:36:23 set +* Added: JASC code to the Linux make process. Also modified the code a +little bit to generate the propper dependencies when compiled under other +platforms. + +Revision 2.273 2002/08/28 13:50:45 domatlantida +* Added: WinGr driver. It isn't integrated to the make process yet. The +author is JASC (domatlantida). But this check-in is being done by set using +domatlantida user until JASC solves your CVS setup problems. + +Revision 2.272 2002/08/27 17:20:09 set +* Added: [X11] An option to avoid adjusts in the window size when the WM +doesn't follow our hints. Roman Valyushenko discovered problems using KDE +3.1 alpha, it sends sizes that aren't fontW/fontH multiples and when we +resize the window KDE gets confused. This option can be used to disable +this behavior. + +Revision 2.271 2002/08/26 15:35:24 set +* Modified: Moved a code page struct definition that was in the code to the +header. It workarounds a bug in Borland's debugger reported by Pawel +Wypustek . + +Revision 2.270 2002/08/26 13:36:41 set +* Added: A callback to TDisplay. Is called when the driver was detected but +not yet initialized. I need it to set some defaults in SETEdit without +wasting time doing it for all the possible drivers. +* Added: A TDisplay member that return information about known DOS modes. +* Added: [DOS] ExtProgVideoMode and VideoMode configuration variables. *Not +tested*. + +Revision 2.269 2002/08/26 13:35:58 set +* Added: atReplace to the TNSCollection class. +* Added: "Add" facilities to the TVMainConfigFile class. +* Added: TDisplay::getDefaultPalette() to find what's the default palette. + +Revision 2.268 2002/08/26 13:35:29 set +* Added: The test code I use for Linux/Console cyrillic support. + +Revision 2.267 2002/08/23 14:46:34 set +* Added: [X11] min. size hints. KDE and E 0.16.5 supports it. Patch by +Roman Valyushenko . +* Fixed: [X11] mouse coordinates from X can be negative, we use unsigneds +and hence they appear like huge positives. Patch from Roman Valyushenko. +* Added: [X11] the cursor disapears when the window lose the focus. It can +be disabled using the HideCursorWhenNoFocus configuration variable. Patch +from Roman with some modifications for the configuration from me. + +Revision 2.266 2002/08/23 12:30:55 set +* Fixed: [XTerm] an extra declaration for UserStartPallete, how this got +there? Reported by Roman Valyushenko + +Revision 2.265 2002/08/22 18:30:45 set +* Modified: [Linux] The last patch to report the ASCII only if that's >= +128. I think that's necesary to understand Alt+cyrillic. + +Revision 2.264 2002/08/22 18:29:44 set +* Fixed: Write pass 1 error in configfile.cc. Detected with efence while +using SETEdit. +* Added: Configfile members to search strings to match the integer +facilities. +* Added: DOS, Linux, X11 and XTerm/Eterm drivers now supports setting a +default palette in the tvrc file. The Eterm is really slow and flickers +when we set the palette :-(. DOS is untested. +* Fixed: [Linux] keys reported as Alt+key from ESC+key now doesn't have +an associated ASCII. + +Revision 2.263 2002/08/21 12:50:59 set +* Fixed: [Win32] unsigned/signed comparisson. Patch by Igor. + +Revision 2.262 2002/08/20 19:49:28 set +* Fixed: [Win32] The call to _sleep is deprecated according to Igor, so I +replaced it by CLY_YieldProcessor, it calls to Sleep (Win32 API). From a +report by Igor Gnip + +Revision 2.261 2002/08/20 14:18:40 set +* Added: Code page configuration to the DOS, Linux, QNX, UNIX, Win32, +WinNT, X11 and XTerm drivers using the tvrc. +* Added: The priority concept to the TVConfigFile class, it allows setting +variables with more or less priority than the ones loaded from disk. +* Modified: Now is possible to create a TVConfigFile class before TProgInit +is called and put some default values there before the tvrc is loaded. + +Revision 2.260 2002/08/16 13:06:13 set +* Fixed: DOS, WinNT and Win32 drivers, last changes were incomplete. + +Revision 2.259 2002/08/16 12:58:55 set +* Modified: [MSVC] the way I define close, open, etc. replacements. The +inline keyword only works for C++ and I must use __inline. I also moved +the definitions after io.h to have the _* prototypes. From errors sent by +WintiX. + +Revision 2.258 2002/08/14 12:55:29 set +* Fixed: genraw example created a TVCodePage object without specifying the +input code page. Reported by Igor Gnip + +Revision 2.257 2002/08/13 13:49:47 set +* Fixed: I forgot to include the videomode example in the distribution list + +Revision 2.256 2002/08/13 13:37:48 set +* Fixed: The TDrawBuffer patch tested in the wrong order generating more +problems than the avoided =-P + +Revision 2.255 2002/08/13 13:37:06 set +* Fixed: TVFontCollection didn't initialize fontName and fileName if the +font wasn't loaded generating a SIGSEGV when destroying the object. +* Fixed: A read past 1 in TDrawBuffer for TFrames. I added code to +TDrawBuffer to check for the EOS instead of fixing TFrame. Detected with +efence, a read past one is hardly dangerous in real life. +* Fixed: [Linux] the driver failed to copy the Linux font when only setting +the secondary font. +* Fixed: [MSVC] the _read, _write, etc. macro replacements expanded for +members called read, write and close generating problems. I replaced them +using inline functions. I hope it solves some compilation problems reported +by WintiX. + +Revision 2.254 2002/08/12 17:52:52 set +* Fixed: Example target for helpdemo is helpdemo and not test. Patch by +Igor Gnip + +Revision 2.253 2002/08/12 17:47:12 set +* Fixed: [MinGW] GNU install doesn't support mixed \ and /. Patch by Igor +Gnip +* Fixed: [MinGW] some examples uses usleep and it isn't provided by MinGW. +Added a macro to compatlayer.h. Igor Gnip + +Revision 2.252 2002/08/12 16:25:04 set +* Added: [DOS] Support for the setCtrModeRes member. It searchs the closest +mode available. I also tested VESA modes successfuly. + +Revision 2.251 2002/08/12 16:07:09 set +* Added: X11, Linux and DOS drivers now tests if the font callback is +installed. In this case these drivers tries to use an application font +before start drawing. Untested. +* Added: FontWidth and FontHeight configuration variables. Supported by +X11 and XTerm drivers. XTerm tries to use a fixed font from a list of +known XFree86 fixed fonts. X11 tries to get a font from the callback or +use 8x16/10x20 internal fonts. + +Revision 2.250 2002/08/12 16:05:49 set +* Added: 2 new configuration variables: ScreenWidth and ScreenHeight. I +added support for it to the X11, XTerm, DOS, Win32 and WinNT drivers, but +only tested the first 2. +* Modified: Now if a variable search in a driver section fails a new search +in the "global" TV section is done. It allows creating default values for +all drivers. + +Revision 2.249 2002/08/12 16:04:31 set +* Added: A TScreen methode to find the short name of the current driver. + +Revision 2.248 2002/08/12 16:03:41 set +* Added: Input code page. It can be used to translate the codes from the +keyboard to the application code page. +* Modified: All drivers to set the input code page. Win32 drivers now use +both values GetConsoleOutputCP() and GetConsoleCP(). + +Revision 2.247 2002/08/12 16:02:27 set +* Added: Yet another flag to TScreen: noUserScreen(). It returns True if +the user screen doesn't exists. You can't invoke a shell in this case. +* Added: A new command cmCallShell. It should be used for the menu option +that invokes a shell. It is disabled if noUserScreen() is True. +* Modified: tvedit, videomode, demo and font examples to use the new +command. +* Fixed: [XTerm] the resume restore the window size wrongly (width and +height exchanged). +* Added: [X11] The new flag. Currently that's the only driver having it. + +Revision 2.246 2002/08/12 16:00:19 set +* Fixed: [Cygwin] The CLY_GetShellName() function to return the content of +SHELL environment variable as in UNIX. Found using the "videomode" example +while testing with Cygwin, now the "Shell" option works ok. + +Revision 2.245 2002/08/12 15:58:18 set +* Fixed: [Win32] Configuration script didn't create compat/rhide.env. +* Fixed: [Win32] Not all the screen was updated after a window resize. +Found using the "videomode" example with a binary compiled with MinGW. + +Revision 2.244 2002/08/12 15:56:51 set +* Added: An example showing how to set the screen/window size using video +modes and resolutions. +* Added: A new TScreen flag to know if the driver supports video mode +change. +* Fixed: [DOS] The extended video modes needs mode recalculate, so now the +set font function when we specify Force also force a mode recalculate. + +Revision 2.243 2002/08/12 15:53:29 set +* Fixed: The names of CP 1254 and 1257 from Win32 API. +* Fixed: [Win32/WinNT] Use of True/False instead of TRUE/FALSE (cosmetic). +* Added: [Win32/WinNT] Support for code pages. But not all the code pages +are supported by TV. +* Fixed: [Win32/WinNT] Cursor problems related to the new code. +* Added: [Win32/WinNT] More comments about problems I found. Also added the +list of code pages that Win32 API reference says we can find and which are +supported by TV. + +Revision 2.242 2002/08/12 15:49:19 set +* Fixed: [Win32/WinNT] The mouse didn't resume. (Missing mouse after +returning from a shell) +* Fixed: Useless code in fontcoll.cc, reported by BC++. +* Modified: [Win32/WinNT] I rewrote the whole suspend/resume stuff. Now I +use a separated screen buffer for the application. It makes the screen/ +cursor much more easy. Pro: this mechanism is really good and is a good +thing in the Windows API. Contra: I'm facing some bizarre problems with +Windows screen updates, most probably is partially my fault, but it exposes +some Windows bug. +* Added: [Win32/WinNT] Debug helpers to the TSscreen* classes. Lamentably +the free Turbo Debugger can't even load the debug information of TV +applications (not enough memory). Is amazing that a debugger that can debug +Windows applications have such a huge limitation. +* Modified: [Win32/WinNT] To check for successful initialization. According +to Win32 API references some trivial operation can fail and must be tested. +* Added: [Win32] Code to avoid ^Break. I copied Anatoli's code found in +WinNT driver. +* Added: [Win32/WinNT] Windows resize! now you can specify a 90x30 video +mode and the window will try to resize to it (or the closest size available) +Lamentably in Win32 you don't have control over the font used by a console +application :-( +* Fixed: [Win32/WinNT] The initialization of the drivers didn't indicate +the application wasn't suspended. It produced problems when +suspending/resuming to a shell. +* Added: [Win32/WinNT] Example on how to change the video mode to tvex.cc. + +Revision 2.241 2002/08/12 15:44:08 set +* Fixed: Extra stdio include in TProgram, used for debug. +* Fixed: The fonts example to remove debug tests. + +Revision 2.240 2002/08/12 15:42:33 set +* Added: A new member to TDisplay: setCrtModeRes. It allows setting the +video mode specifying the resolution instead of a magic mode number. +Also added the TScreen::setVideoModeRes counterpart. +* Added: The default setCrtMode member now translates the DOS modes into +a width and height and calls to setCrtModeRes. In this way X11 and XTerm +video drivers can adjust the window size to the spected size. +* Modified: When we detect an asynchronous mode change the TProgram class +sets the video mode to the current one. This generates conflicts so now it +sets the mode to 0xFFFF and it means reset the variables but don't change +the mode. +* Added: A member to TProgram to access the new TDisplay functionality. +* Added: [DOS] Support for 80x50x8x8 mode as defined in Borland TV 2.0 +(mode 0x100). But isn't recommended. +* Added: [XTerm] Support to the new TDisplay member. The window size is +adjusted to the desired size. I also added font size adjust, it looks for +the closest XFree86 font and selects it. XFree86 4.1.0 have 13 fixed fonts. +Also added font size and window size suspend/resume. Eterm 0.9.2 doesn't +implement the mechanism to find the current font so the size isn't +restored. +* Added: [X11] Support to the new TDisplay member. It calls the font call +back to get a new font if the size of the font is changed in the call. +* Added: Symbolic names to all the DOS text modes. +* Modified: The font test program to use the symbolic names and added a +couple of examples that sets a video mode using the number and a +resolution. + +Revision 2.239 2002/08/12 15:40:18 set +* Fixed: TVFontCollection::EnlargeOne to avoid SIGSEGVs (only detected with +efence). I also changed the strategy to repeat the last line. +* Modified: The sizes of the fonts in the list to offer to the user now +uses a special collection to keep the list well sorted (first by width and +then by height). +* Modified: [X11] The minimum width and height of fonts reported by the +driver. Now that's 5x7, I did it because now I have an SFT with such a +fonts. They are too small to be usable, but could be used to "minimize" +an application or maybe to use in a device like a palmtop, how knows? + +Revision 2.238 2002/08/12 15:39:02 set +* Added: Some documentation about the SFT format in fontcoll.cc. + +Revision 2.237 2002/08/12 15:38:10 set +* Added: Some preliminary support for SFT files containing just a range +of the supported symbols. + +Revision 2.236 2002/08/12 15:37:11 set +* Fixed: The font request call back naturally should use GetFont(), it +returns a newly allocated memory block so is better to do all dynamic. It +means DOS driver must free the requested font. + +Revision 2.235 2002/07/30 17:44:19 terrible +* Updated: Debian packaging to 2.0.0-0.3. +* Modified: my email changed from lubaldo to ibaldo. +* Broked: everything, this is a sabotage!, SET is on vacations!!! + +Revision 2.234 2002/07/25 17:24:23 set +* Fixed: [DOS] The 90x34 and 94x34 video modes uses 14 lines fonts but +didn't set it into the BIOS DATA AREA, for this reason some BIOSes didn't +show the cursor. + +Revision 2.233 2002/07/24 19:57:02 set +* Modified: Part of the font settings API, now you can set both fonts in +one call. Modified for X11, Linux and DOS. Tested for X11 and Linux. +* Fixed: [X11] various bugs with the cursor that appears when: a) you +change the font size and b) you use 2 fonts. +* Added: A message to the font example to explain a fail to set a secondary +font that have a size that doesn't match the primary font. + +Revision 2.232 2002/07/23 12:27:50 set +* Fixed: Lack of Uses_limits in fontcol.cc. + +Revision 2.231 2002/07/23 12:27:14 set +* Fixed: getopt changes were incomplete. + +Revision 2.230 2002/07/22 20:40:53 set +* Added: [MSVC] some code to solve link problems. + +Revision 2.229 2002/07/22 19:35:06 set +* Updated: fontcoll.cc dependencies. + +Revision 2.228 2002/07/22 19:34:17 set +* Added: New methods to TListBox that allows setting a new list without +destroying the one currently used. +* Updated: MSVC and BC++ makefiles. + +Revision 2.227 2002/07/22 19:33:25 set +* Added: Mechanisms to list the available fonts from a directory and create +dialogs with it (collection and list box for the structure). +* Modified: TSortedListBox::getKey to be protected and not private. No +special reason but I think that's better. + +Revision 2.226 2002/07/22 19:32:26 set +* Modified: [Linux] code 30 to be the "enter" symbol and not V/T. +* Fixed: [Linux] ISO-1 code page to differentiate 160 from 32. This isn't +important nor used but I think that's better. +* Modified: Clarified the error that Linux code pages contain about the +double frames. I confirmed that's an error. +* Added: Support for font width to .SFT format. +* Added: Support fot width>8 in TVFontCollection. +* Modified: [X11] Removed the 12x24 font and put a nice 10x20 font I +created using the 10x20.pcf included in XFree86 plus some modifications. +This font is simple but quite nice. +* Added: [X11] A Font10x20 configuration option to select the new font. +* Added: [X11] Support for setfont with widths greater than 8. Is +incomplete and untested. +* Added: Support for width>8 to the genraw.cc example. Also added optional +code to generate headers intead of raw fonts (used for the X11 driver ;-) + +Revision 2.225 2002/07/22 19:18:40 set +* Modified: The Uses_getopt now defines CLY_* names, so you must use +CLY_getopt, etc. It avoids all kind of coliisions. QNX is an example. Looks +like they have a getopt function but not getopt_long and our definition +collides. Reported by Mike. + +Revision 2.224 2002/07/19 20:01:14 set +* Added: [X11] Support for fonts with width > 8 pixels. For testing +purposes I added a 12x24 font. The code can be compiled to use it. + +Revision 2.223 2002/07/19 14:02:28 set +* Updated: DOS project. +* Fixed: Compilation of dosscr.cc, I forgot one debug macro. + +Revision 2.222 2002/07/17 17:14:49 set +* Added: TVFontCollection class. It handles 8xN bitmap fonts. Also added +an example. + +Revision 2.221 2002/07/17 12:27:19 set +* Added: Options to compile the DOS+WinOldAp clipboard routines with a lot +of verbosity. It looks like the code is failing in Win2K and I need to +test it. + +Revision 2.220 2002/07/16 19:22:00 set +* Added: Default code page concept. +* Fixed:(?) Remapping problem when the "similar" was outside the ASCII +range. +* Fixed: IndexToID was wrongly implemented. +* Added: TButtonRef, a button that just uses a reference to the "title". +* Modified: TScrollbars, they are now less configurable but doesn't fail +when remapping the screen. + +Revision 2.219 2002/07/15 15:16:40 set +* Modified: The TVCodePage semantics. Now is more clear. I hope it doesn't +break the code ;-). + +Revision 2.218 2002/07/15 15:13:38 set +* Added: A mechanism to allow applications to provide a new font when the +one currently in use doesn't match a new video mode. + +Revision 2.217 2002/07/15 15:09:47 set +* Modified: Removed the TFont class. Now this functionallity is in TScreen. +May be I'll add more things to make it as flexible as this class. +* Added: [DOS] Font restore on suspend and resume. Also after a change in +video mode. +* Added: Shell example to the font's example, it is good for testing the +fonts suspend/resume behavior. Also added a video mode change when +compiling for DOS. Also good for testing. + +Revision 2.216 2002/07/11 19:11:35 set +* Fixed: [MSVC] more compatlayer issues, added pclose and pipe, commented +utime macro, etc. From SETEdit compilation errors sent by WintiX. + +Revision 2.215 2002/07/10 19:23:11 set +* Added: [FreeBSD] Code to solve the "last line problem". It was suggested +by Mike and should be tested by miniEleph. + +Revision 2.214 2002/07/08 15:41:08 set +* Added: [MSVC] A lot of translations to MSVC library names. Most of the +POSIX low level stuff (open, close, etc.) exists in MSVC but the names are +changed to _*, may be Microsoft thinks that POSIX is polluting the ANSI +namespace ;-). From output sent by WintiX. + +Revision 2.213 2002/07/05 20:28:18 set +* Added: [MSVC] More compatlayer entries for __inline__, utime and opendir. + +Revision 2.212 2002/07/05 13:08:46 set +* Fixed: GetCodePage, currently it have some complexity that may be is +better to remove. +* Modified: TDesktop to remap background character after a code page +change. Not sure if that's the best. +* Added: [DOS] partial font support. I copied the code I had in TFont and +adapted it. More things must be adjusted, TFont removed and add some font +restore at exit/suspend. The example works. + +Revision 2.211 2002/07/04 20:09:59 set +* Modified: [BC++/MSVC] these compilers doesn't use the configuration +mechanism instead a custom configtv.h is used. I unified it for both +compilers. + +Revision 2.210 2002/07/04 19:10:04 set +* Removed: [DOS] old reference code for code page support. + +Revision 2.209 2002/07/04 19:09:16 set +* Added: [DOS] Code page detection and setting. +* Modified: [DOS] The clipboard code to be easier to understand. + +Revision 2.208 2002/07/03 15:51:00 set +* Added: Information about which Win32 compilers are supported to the web +page. +* Added: WintiX to the list of contributors. + +Revision 2.207 2002/07/03 15:40:54 set +* Modified: [MSVC] tvex.exe to tvex targetname as suggested by WintiX. + +Revision 2.206 2002/07/03 15:39:44 set +* Modified: [Win32/WinNT] to detect how many buttons have the mouse. +Lamentably it isn't reliable at all. My mouse generate mouse events when +the middle button is pressed, but Windows insists that's a 2 buttons mouse. +I also strange that IE supports the wheel, the help viewer don't and the +wheel doesn't generate mouse events ... really strange. May be Win98 SE is +tool old to support mouse wheels properly. + +Revision 2.205 2002/07/03 15:38:47 set +* Added: [DOS] PollMouse option to the tvrc to force mouse polling. + +Revision 2.204 2002/07/02 20:51:50 set +* Fixed: [X11] Button 4 and 5 support. Now SETEdit supports mouse wheel ;-) + +Revision 2.203 2002/07/02 19:16:38 set +* Added: [MSVC] A rule to create a demo application to the makefile. WintiX +generated a demo application successfuly! + +Revision 2.202 2002/07/02 19:06:16 set +* Fixed: [Linux] Disabled code in dual.cc, this file must be removed. + +Revision 2.201 2002/07/02 18:14:18 set +* Fixed: dual.cc referenced dual_display that now is temporally inside +TDisplay. + +Revision 2.200 2002/07/02 14:36:05 set +* Fixed: [MSVC] a couple of warnings. From cl output sent by WintiX. + +Revision 2.199 2002/07/02 13:32:20 set +* Added: [Linux] Font restore on suspend and set again on resume. Also +handled console switch. +* Added: [Linux] A configuration variable to enable the secondary font use. +By default is disabled because Linux switchs to 8 colors. + +Revision 2.198 2002/07/01 19:08:31 set +* Modified: Linux project and makefile and DOS files so DJGPP and Linux +projects are more similar. Second step towards an unification. + +Revision 2.197 2002/07/01 15:58:20 set +* Updated: [QNX] package file. From Mike. +* Added: [QNX] small doc about the limitations. From Mike. + +Revision 2.196 2002/07/01 15:43:22 set +* Updated: [MSVC] Makefile to include all the drivers directory. Problems +reported by WintiX. + +Revision 2.195 2002/07/01 15:33:40 set +* Added: A new example that shows how to use help context values and the +status line. Ported by Mike. + +Revision 2.194 2002/07/01 14:26:11 set +* Fixed: [X11] cursor artifacts intoduced in last patches. + +Revision 2.193 2002/07/01 13:02:47 set +* Added: Font set/restore mechanism to TScreen. +* Added: [X11] Full fonts support. +* Added: [Linux] Partial fonts support, more things needs to be solved. +* Added: A fonts test/demo example. +* Added: GetCodePages call to memorize the current code pages in use. +* Fixed: [X11] Initialization to allocate classHint, no fixed size, and to +do it before indicating success. + +Revision 2.192 2002/07/01 12:57:39 set +* Fixed: [X11] clipboard code. + +Revision 2.191 2002/07/01 12:53:39 set +* Fixed: More error reporting details in all clipboard implementations. +* Updated: [DJGPP+Win32] Project and makefiles. + +Revision 2.190 2002/07/01 12:49:03 set +Revision 2.189 2002/06/29 20:11:05 set +* Added: [Win32] Clipboard class. +* Updated: [BC++] Makefile to include all the drivers. +* Fixed: [DOS] Clipboard error reporting. + +Revision 2.189 2002/07/01 12:38:11 set +* Added: [DOS] Windows clipboard routines. +* Modified: The TVOSClipboard class to report the name of the error in case +of fails and the size of the paste buffer. +* Modified: All the drivers to generate dependencies when compiled for +another platforms and protected the headers against use in other platforms. +* Modified: [DJGPP] The project to also include UNIX drivers. That's an +important step towards a project unification. + +Revision 2.188 2002/06/28 20:21:46 set +* Fixed: [MSVC] More details, only 2 or 3 files needs adjustments to get +the code compiled. Errors from WintiX. + +Revision 2.187 2002/06/28 20:06:30 set +* Added: A new class called TVOSClipboard it gives access to the OS +clipboard/s in a neutral way. +* Added: [X11] code to use the XA_CLIPBOARD and XA_PRIMARY copy/paste +mechanism through the new class. The first is clipboard 0 (recommended) and +the second is the auxiliar mechanism that users should use with the middle +mouse button. +* Added: An example application that shows how to use the new class. + +Revision 2.186 2002/06/28 12:38:31 set +* Added: A new capability flag to the drivers. It informs if a screen saver +have any sense for this driver. Ivan remmembered it, a screen saver doesn't +have any sense when we are working inside a window ;-) + +Revision 2.185 2002/06/27 20:52:22 set +* Added: [X11] Explanation about WM/Desktop key conflicts to the mini doc. + +Revision 2.184 2002/06/27 20:36:58 set +* Added: A doc directory and a file explaining implementation details of +the X11 driver. + +Revision 2.183 2002/06/27 20:09:50 set +* Modified: [X11] At least in my XFree86 (Debian GNU/Linux Potato) the Ctrl ++Space combination maps to a keycode 0x20 but none translated symbol. As a +workaround I added a test for this. I also found that shift tab was mapped +to something called ISO_left_tab but nothing was reported to the +application. For this I modified X11 configuration files. +* Removed gkey.gpr, it no longer works. + +Revision 2.182 2002/06/27 18:41:45 set +* Fixed: [MSVC] ssize_t isn't defined by standard headers. I also unified +the mechanism to request it because BC++ and MinGW doesn't define it as +MSVC and each one used a different mechanism. +* Fixed: [MSVC] The C flags to include the -I../include. Both fixes from +the output of MSVC sent by WintiX. + +Revision 2.181 2002/06/27 18:24:26 set +* Fixed: [MSVC] C code compile rule, patch from WintiX. + +Revision 2.180 2002/06/26 16:55:17 set +* Updated: The Win32 headers, some how S.F. CVS got unsynchronized. +* Fixed: getopt and getline to compile with MSVC from output errors +provided by WintiX. +* Updated: Makefiles. CVS users will need to reconfigure. + +Revision 2.179 2002/06/26 16:52:15 set +* Fixed: [MSVC] which header is needed for access function. +* Fixed: [MSVC] rules to compile .c files and use of rm. Reported by WintiX + +Revision 2.178 2002/06/26 15:17:11 set +* Fixed: [Linux] When the VCS access wasn't available the routine that +restores the screen content put 0x0 attributes in spaces after the text. +They become invisible and what's worst the cursor is also invisible when +positioned over such a character. Now the buffer is properly filled with +the default color (7). + +Revision 2.177 2002/06/25 12:17:16 set +* Fixed: The Help Compiler to compile with gcc 3.x, also fixed some bugs. + +Revision 2.176 2002/06/25 12:15:01 set +* Added: [Linux] driver options to disable: keyboard patching (PatchKeys), +VCS use (UseVCS) and MDA use (UseMDA). + +Revision 2.175 2002/06/24 19:39:04 set +* Modified: [QNX] When linking the dynamic library -lncursesS should be +used, explained by Mike. + +Revision 2.174 2002/06/24 19:31:00 set +* Added: [QNX] Package description contributed by Mike. + +Revision 2.173 2002/06/24 15:17:42 set +* Fixed: A typedef struct v.s. struct issue reported by gcc 3.1. Reported +by Ortwin.Gasper@t-online.de. + +Revision 2.172 2002/06/24 15:10:44 set +* Fixed: dlgdsn example to compile with gcc 3.1. Patch from Andris. + +Revision 2.171 2002/06/24 15:04:07 set +* Modified: Removed linuxso/Makefile and linuxso/compat.mak, they are +created by Perl scripts and UNIX targets should have Perl anyways. + +Revision 2.170 2002/06/24 15:02:54 set +* Fixed: [BC++] details to cleanly compile with BC++ 5.5. + +Revision 2.169 2002/06/24 15:01:35 set +* Modified: [DJGPP] to use /dev/env/DJDIR/etc as directory for +configuration. + +Revision 2.168 2002/06/24 15:00:29 set +* Fixed: A couple of errors in new classes exposed when compiling for +djgpp. + +Revision 2.167 2002/06/24 14:59:25 set +* Added: "Priority" variable to the configuration section of each driver. +So now you can change the importance of each driver. The section names of +the drivers are DOS, Linux, QNX, UNIX, Win32, WinNT, X11 and XTerm. + +Revision 2.166 2002/06/24 14:56:18 set +* Added: A new class to manage a configuration file. Right now only one +setting is accepted in this file: ShowCursorEver. See TVConfigFile in +configfile.cc and TProgInit::config. + +Revision 2.165 2002/06/20 20:13:59 set +* Fixed: CLY_GetDefaultFileAttr(CLY_mode_t *mode) for UNIX, it didn't set +writemask making new files to look like R.O. + +Revision 2.164 2002/06/20 20:12:38 set +* Added: A new flag to TScreen to indicate is the driver really supports +setCursorShape or just can hide/show the cursor. + +Revision 2.163 2002/06/19 19:51:00 set +* Fixed: [X11] The "show cursor ever" flag didn't work OK. + +Revision 2.162 2002/06/19 19:30:38 set +* Fixed: Small issue about cursor positioning in TDesktop. Now is cleaner. + +Revision 2.161 2002/06/19 18:43:35 set +* Modified: [WWW] The QNX port is now finished, added as available target. + +Revision 2.160 2002/06/19 17:10:12 set +* Added: [Linux] support for russian keyboards when the encoding is KOI8. +Alexey Godin gave me the information about the layout. I tested it using +the koi8-r fonts and ru1 keyboard map in my system + a translation of the +"File" menu and worked. + +Revision 2.159 2002/06/18 20:50:37 set +* Added: TScroller and TScrollBar now cooperates with Braille Terminals. +From suggestions by Tapio. + +Revision 2.158 2002/06/18 20:28:23 set +* Added: [Linux] A comment about LANG variable. Sent by Alexey Godin. + +Revision 2.157 2002/06/18 16:41:24 set +* Modified: [QNX] New batch of patches for the QNX console from Mike. This +driver is now finished according to Mike. + +Revision 2.156 2002/06/18 14:51:16 set +* Added: Code to remap characters on the fly. I rewrote the code in TView +that sends the data to screen so it can remap characters before doing it. +* Modified: As I was rewrinting the code in TView I changed it to avoid +calling setCharacter which is much less efficient than setCharacters. Now +I copy the text to a buffer and then I change the shadow attribute there. +* Added: Euro sign support. +* Added: Four latin 2 variants used in Linux. +* Added: Now when you set the code page you can specify two code pages. One +maps the font and the other the text handled by the user. This seems to be +stupid but is needed to support Linux mechanism which works this way. If +these code pages are different the code uses the on the fly remap. +* Added: TVCodePage members to create a code page from an unicode array and +to add it to the list of supported code pages. +* Added: [Linux] Detection of the ACM. The user *must* use the correct ACM +unless ISO 8859-1 is used or the ACM is trivial. + +Revision 2.155 2002/06/12 20:51:18 set +* Added: Functions to map unicode into the internal code and more +functionality to the code page debug stuff. With this I discovered that +Potato not only have iso-latin1 damaged fonts but also latin2 damaged. + +Revision 2.154 2002/06/12 18:28:12 set +* Modified: [Linux] GetCursorPos so if it gets a wrong escape sequence +doesn't crash. From a report by Tapio. + +Revision 2.153 2002/06/12 18:01:27 set +* Fixed: [Linux] the Resume member ever used the generic GetCursorPos +instead of the driver selected version. + +Revision 2.152 2002/06/12 17:41:07 set +* Added: Code to the TVDemo examples that shows how to use the TVCodePage +class. It remaps the system menu label and the calendar arrows. + +Revision 2.151 2002/06/12 16:59:28 set +* Fixed: The THWMouse class called GetEvent if the mouse wasn't present. +This was the source of problems when switching consoles under Linux. + +Revision 2.150 2002/06/12 16:46:38 set +* Modified: [X11] the driver now uses ISO-8859-1 fonts instead of PC437. + +Revision 2.149 2002/06/12 15:40:03 set +* Added: [Linux] Code page detection to the driver. It needs console +IOCTLs. If we can't use them the driver tries to guess using the LANG +environment variable. +* Added: Symbolic names for all the supported code pages. + +Revision 2.148 2002/06/12 12:34:12 set +* Added: A first step towards Linux console code page detection. Curently +the code only works for full console access and differentiates between +lat1, lat1u and koi8-r code pages. + +Revision 2.147 2002/06/11 19:10:32 set +* Fixed: [XTerm] Window title set/get details. + +Revision 2.146 2002/06/11 16:15:07 set +* Fixed: [UNIX] ln error when overwriting the libtvfdummy.a link. + +Revision 2.145 2002/06/11 16:05:07 set +* Fixed: [Solaris+XTerm] The termios MIN and TIME values have a default +that isn't really good for interactive applications. Now I set to 0 both. +With this I succesfully run the editor remotely with mouse and shift/ctrl/ +alt+key support. + +Revision 2.144 2002/06/11 15:09:25 set +* Fixed: Missing \n after the tvfintl copy in generated makefile. Affected +UNIX targets. + +Revision 2.143 2002/06/11 14:56:57 set +* Fixed: [XTerm] The suspend member needed a flush, without it calling a +shell didn't restore the shell screen. + +Revision 2.142 2002/06/11 14:34:29 set +* Fixed: TEventQueue::resume() didn't indicate it was resumed if mouse +initialization failed. +* Fixed: [Linux] Suspend used the input before keyboard was resumed. Now +the file handle used for input is ever in non-block mode. This isn't stdin +so I think I can do it. From a report by Tapio. +* Fixed: [Linux] The driver assumed that Gpm_close set gpm_fd to -1, is not +true for GPM 1.17.8. +* Fixed: [Linux] The mouse driver didn't set Suspend correctly. + +Revision 2.141 2002/06/11 12:15:07 set +* Added: [XTerm] Alt+numbers to the Xterm example script. +* Fixed: The screen.h doesn't have any relation with the original header +from Borland, put it clear. +* Fixed: [XTerm] the palette mechanism, now works and is faster. +* Modified: [XTerm] the new XTerm uses ugly colors, forced PC BIOS colors +because they are the colors used by Linux console, Eterm, X11 driver, DOS +and Win32 versions. +* Added: [XTerm] now the button shadows and color samples (reverse space) +are closer to the original shapes. + +Revision 2.140 2002/06/10 20:59:42 set +* Added: TVCodePage class. That's the first version of the codepage +remapping routines. +* Added: More key bindings to the Xterm.res example. They help with some +xterm versions. +* Modified: [XTerm] the driver to use a separated file handle for input. +It solves interferences like in the Linux driver. +* Added: [XTerm] Now the driver starts with ISO-8859-1 mapping so the +frames and similar stuff aren't ugly anymore. +* Added: A broadcast message cmUpdateCodePage to indicate a code page +change. + +Revision 2.139 2002/06/10 13:24:06 set +* Fixed: tvfintl must be used for the examples if no intl was found. +* Fixed: We no longer need to patch vpath_src in .maks for Win32. +* Modified: Now a copy of libtvfintl.a is put in the same directory where +the librhtv.* is created, it helps applications like setedit that can use +Turbo Vision even if not installed. +* Fixed: [Win32] cursor driver issues. +* Fixed: [WinNT] lack of stdlib include. +* Fixed: [MinGW] it doesn't define ssize_t. +* Modified: win32/readme.txt, I teste the library with MinGW 1.1+MSys 1.0.7 +and SiePerl, it works and I explain how to use it. + +Revision 2.138 2002/06/07 19:11:25 set +* Modified: [UNIX] the configuration to test if the X11 include directory +is really needed. It looks like gcc 3.1 gives a warning if this is manually +specified. Is a test because I don't have gcc 3.1 for Linux. Reported by +Andris. + +Revision 2.137 2002/06/07 18:13:40 set +* Modified: [X11] Now after a draw the cursor becomes visible inmediatly. +This is slower but increases the cursor visibility. Ivan reported problems. + +Revision 2.136 2002/06/07 15:46:21 set +* Added: A first attempt to create a MSVC compatible makefile. WintiX + sent me the file and I added it to the configuration +mechanism. In this way the list of object files is extracted from the +RHIDE's .mak. + +Revision 2.135 2002/06/07 15:37:15 set +* Fixed: [MSVC] Compatlayer getcwd request, from info by WintiX. + +Revision 2.134 2002/06/07 14:34:17 set +* Fixed: xtmouse.h lack of new line at the end of file. Patch by Andris. +* Test: Looks like some glibc 2.2.5 includes libintl.h without explicit +request. It generates some conflicts. Here I include a possible workaround. +Reported by Andris. + +Revision 2.133 2002/06/07 02:15:07 terrible +* Updated: Debian packaging with small changes. + +Revision 2.132 2002/06/06 19:32:05 set +* Fixed: The gcc 3.1 standard C++ streams doesn't define a public methode +to open a stream from a C stream/file handle. It wasn't this way in 3.0 and +3.1 pre-releases (which were supposed to be ISO C++ compliant). To overcome +this problem I wrote a wrapper for std::filebuf. That's ultra compiler +version specific and I don't know how many time will be supported. This +idea was suggested by Andris. The modifications are small, but implied some +work to understand how stdc++ works. BTW: stdc++ itself needs a similar +trick for cout/cin associated with stdout/stdin ... + +Revision 2.131 2002/06/05 20:24:51 set +* Fixed: The tutorial number 16 didn't initialize the data for one of the +input line examples producing random garbage. Reported by Mike. + +Revision 2.130 2002/06/05 20:16:48 set +* Added: [QNX] New patch from Mike to enhance the keyboard handling. +* Fixed: TInputLine used an archaic ^Y hardcoded symbol instead of kbCtY. +Patch by Mike. + +Revision 2.129 2002/06/05 15:28:38 set +* Fixed: [X11] Now when the WM sends a DELETE_WINDOW message (usually +because the user used the close button) the TV application gets a cmQuit +event. + +Revision 2.128 2002/06/05 14:26:45 set +* Added: Thanks to JASC in the X11 code, I think he deserves it. + +Revision 2.127 2002/06/05 14:17:50 set +* Fixed: [X11] the driver didn't map ^a-^z, reported by Ivan. + +Revision 2.126 2002/06/05 14:16:40 set +* Updated: Distribution files list to include update and THANKS. + +Revision 2.125 2002/06/04 19:39:41 set +* Modified: Now the configuration determines the directories where extra +libraries could be located and adds it to the list of directories. + +Revision 2.124 2002/06/04 18:34:40 set +* Fixed: Another *.* pattern, reported by Tapio. + +Revision 2.123 2002/06/04 18:31:10 set +* Fixed: [Linux] Now I use a separated file handle for the stdin. The +explanation is in the code and is complex. Fixes random fails on cursor +position restore at exit. + +Revision 2.122 2002/06/04 18:28:58 set +* Fixed: When no window was in the desktop and a dialog was executed it +left the cursor in the last used position. Now TDesktop detects it and +if the cursor will remain visible is moved to the last line in the screen. + +Revision 2.121 2002/06/04 16:01:59 set +* Fixed: demo file for QNX. When I moved includes to Uses_* forgot to +include the config header. Reported by Mike. + +Revision 2.120 2002/06/04 15:45:22 set +* Updated: The list of files to convert when using the UNIX tarball. + +Revision 2.119 2002/06/04 15:44:07 set +* Modified: Now specialCharacters is part of the TView class and not just +a variable. While we don't use namespaces I think we should try to avoid +defining things outside classes if not necesary. + +Revision 2.118 2002/06/04 14:51:45 set +* Added: THANKS file with the list of contributors, also updated the www +site. + +Revision 2.117 2002/06/04 13:21:54 set +* Modified: Added comments and removed dead code on the last changes. + +Revision 2.116 2002/06/03 20:56:23 set +* Added: Now TDeskTop moves the cursor to the bottom of the screen when +an object lost the focus and we are in the "Braille friendly" mode. Until +now the changes are good according to Tapio. + +Revision 2.115 2002/06/03 19:42:24 set +* Fixed: [Linux] The Resume member needed a fflush before calling a child +process (a shell for example). + +Revision 2.114 2002/06/03 19:02:43 set +* Added: Uses_chdir request to compatlayer (needed for MSVC where the name +is _chdir). +* Fixed: Absent Uses_getcwd action for MSVC (direct.h _getcwd). + +Revision 2.113 2002/06/03 16:34:03 set +* Updated/Added: Win32 makefiles. + +Revision 2.112 2002/06/03 16:30:52 set +* Fixed: Some MSVC issues from feedback sent by WintiX + +Revision 2.111 2002/06/03 16:29:18 set +* Fixed: TMenuBar::getItemRect, the return value was commented by Anatoli, +but not all compilers (read MSVC) are cleaver enough to realize this code +is never used. I re-enabled the code but it could interfere with another +compiler. We'll see. + +Revision 2.110 2002/06/03 16:26:04 set +* Fixed: The code that helps Win32 ports in the configuration script. It +touched files of the current target, was outdated and have case sensitive +file systems bugs. + +Revision 2.109 2002/06/03 15:20:34 set +* Modified: [QNX] A new patch from Mike for the keyboard tables. +* Added/Fixed: Some small details in the demo code. Patches from Mike, but +applied in a different way. + +Revision 2.108 2002/06/03 13:44:48 set +* Added: [Win32] The "WinNT" driver. Now this is available and I also +adapted things so the "Win32" driver is also available. It means that both: +the code from Anatoli and Vadim can be used for BC++, Cygwin and MinGW. +It looks like Anatoli's code is much faster and less complex. Currently +the WinNT driver have more priority for BC++ and less for Cygwin/MinGW. + +Revision 2.107 2002/06/03 13:18:38 set +* Fixed: [DOS] Typo in cursor shape code (let it enabled all the time). +* Fixed: [DOS] Palette must be restored each time a mode is set. + +Revision 2.106 2002/06/03 13:14:36 set +* Added: Palette support to the DOS driver. +* Modified: The low level setDisPaletteColors to return the number of +succesfuly set colors. + +Revision 2.105 2002/06/03 12:55:41 set +* Modified: The X11 palette routines to include the redraw. Tested with +SETEdit. + +Revision 2.104 2002/06/03 12:54:20 set +* Added: An option to never hide the cursor to TDisplay. The most important +effect of this variable is how it affects high level classes. When this +option is enabled some classes sets the cursor as visible and moves the +hardware cursor. But the low level stuff is needed to debug it. +* Added: Code to be "Braille friendly" to TMenuBox, TMenuBar and TButton. +* Added: Example code to the demo program, also added code to restore the +window title at exit. + +Revision 2.103 2002/06/03 12:50:09 set +* Fixed: MinGW doesn't define ssize_t. Reported by Thiago. + +Revision 2.102 2002/06/03 12:49:11 set +* Added: [Win32] According to Thiago newer versions of MinGW have their own +uname command that reports MINGW32_. Added to the +conflib.pl. + +Revision 2.101 2002/05/30 18:57:15 set +* Fixed: [FreeBSD] when calling ldconfig we must specify to merge the data +of the directory we installed the library. Suggested by miniEleph. + +Revision 2.100 2002/05/30 18:29:26 set +* Fixed: Wilcard used by TVEdit *.* -> * +* Fixed: Shell call used in TVEdit, now is system neutral. Both pointed out +by Tapio. + +Revision 2.99 2002/05/30 17:47:25 set +* Fixed: The column where the cursor is positioned to help Braille +Terminals. Lamentably we must add a mechanism to unhide the cursor because +in Linux if the cursor isn't visible the position isn't actually changed. +From information that Tapio Kelloniemi sent me. + +Revision 2.98 2002/05/30 17:42:32 set +* Fixed: Lack of string header. Reported by Tapio Kelloniemi + + +Revision 2.97 2002/05/30 17:26:56 set +* Added: X11 Palette code, completly untested. The Linux driver code seems +to work. + +Revision 2.96 2002/05/29 20:29:32 set +* Added: [UNIX] XTerm and Eterm palette support, is untested! + +Revision 2.95 2002/05/29 17:56:02 set +* Fixed: [UNIX] TFileEditor was trying to convert UNIX files into DOS +format ;-) and what is worst using a temporal file with random rights. Now +the TVEdit example works on Linux. + +Revision 2.94 2002/05/29 16:08:14 set +* Modified: TMenuBox to move the cursor to the selected menuitem. That's +an experiment to see if Braille Terminals gets benefited. Tapio Kelloniemi + pointed out this. + +Revision 2.93 2002/05/29 15:28:20 set +* Fixed: [FreeBSD] According to miniEleph ldconfig gets mad if we install +librhtv.so., now for this target I install librhtv.so. + +Revision 2.92 2002/05/29 13:03:32 set +* Fixed: TVHC project didn't exclude system headers. +* Updated: [DOS] project and makefile. +* Fixed: tvdemo3.cc included help.h directly. + +Revision 2.91 2002/05/28 19:28:32 set +* Fixed: [www] The link to Sigala's port and the supported platforms. + +Revision 2.90 2002/05/28 18:32:49 set +* [QNX] Applied patches from Mike: +- Added more recognized keys. +- Fixed some bugs in key code translation. +- Fixed uninitialized suspend variable and esc key delay. + +Revision 2.89 2002/05/28 18:20:42 set +* Added: THelpFile/THelpWindow/THelpViewer and friends to the library. +Originally from Sigala's port and was only in the demo. +* Added: Turbo Vision Help Compiler. Adapted by Mike. I did some changes +to the code. + +Revision 2.88 2002/05/28 15:53:32 set +* Fixed: [DOS] The config.pl file used djgpp/makefile and the file is in +fact named djgpp/Makefile. This isn't a problem for DOS/Windows, but is +a problem when using UNIX to copy the file. Pointed out by Mike. + +Revision 2.87 2002/05/28 15:46:34 set +* Updated: The TV site and included a copy in the CVS/distribution. + +Revision 2.86 2002/05/28 12:48:30 set +* Added: The first approach for the Palette handling. The user can access +a couple of TScreen members (get/setPaletteColors) that works using a +couple of members defined by each driver (get/setDisPaletteColors) and some +buffers (ActualPalette, OriginalPalette and PC_BIOSPalette). Added the +capability bits needed to know what's implemented. I implemented it in the +Linux driver, lamentably Linux lack a mechanism to know the current colors. +I explain more in linuxdis.cc. + +Revision 2.85 2002/05/27 17:46:18 set +* Added: QNX update from Mike: +I'm almost done the screen related stuff (only minor bugs remain), 25% done +keyboard stuff (only functional keys and cursor keys seems to be work) and +no mouse support at all. + +Revision 2.84 2002/05/27 14:05:27 set +* Added: Mouse support to the XTerm driver and put in the list of drivers. +Also fixed a lot of details in this driver. This new XTerm driver restores +the screen, supports shift/ctrl/alt+special keys and interactive mouse. +* Added: An example on how to start an old xterm (from X 3.x) to get all +the keys. +* Added: An example theme fro Eterm 0.9.x to get all the key combinations. +It configures Eterm as xterm from X 4.x. + +Revision 2.83 2002/05/27 12:26:30 set +* Fixed: [UNIX] The makemak.pl script created a link to a no longer +existant linux/gkeyli.cc file. Pointed out by Mike. + +Revision 2.82 2002/05/24 20:13:29 set +* Added: The first test classes for the XTerm driver. They aren't tested +yet but I think they will work much better than the ncurses version. + +Revision 2.81 2002/05/20 15:56:55 set +* Fixed: UNIX and X11 drivers didn't set uid and gid to the effective +values after initialization. This is used for Linux console driver, but +must be done for all. +* Modified: [X11] no default title is used, it was "Test". + +Revision 2.80 2002/05/20 15:27:29 set +* Added: QNX files to RHIDE project and hence Makefile. + +Revision 2.79 2002/05/20 15:23:57 set +* Added: QNX skeleton files from Mike. I changed the code a little bit to +generate the most important dependencies even when using Linux's RHIDE. + +Revision 2.78 2002/05/20 15:08:43 set +* Modified: Now the Linux code is in a separated driver. The old code is +now the UNIX driver. +The new driver is only for Linux console and doesn't apply for Xterm. This +driver doesn't need ncurses and have the following new features: + * If the app. is in a real console (ttyN) but doesn't have VCS access + the text of the screen is saved/restored using the Linux ioctls for select + and paste with the mouse. + * The colors and attributes of the console are saved/restored. + * get/setWindowTitle can affect what ps reports if the user helps the + library providing pointers to argv and environ. + +Revision 2.77 2002/05/17 18:54:31 set +* Added: More configuration patches for QNX from Mike. Complements the +special flags for dynamic libs patch and workarounds a library search +issue of QNX 6.2 beta 3. + +Revision 2.76 2002/05/17 18:33:20 set +* Modified: RHIDE project to include QNX sources from Mike. + +Revision 2.75 2002/05/16 21:21:12 set +* Modified: [Linux] Added Scroll-Lock to the patch list, it freezies the +application and some people thinks it hanged. To make it worst some idiots +put the S-L key very close to Home just to insert a stupid key to make +the machine sleep and hence is quite easy to press S-L instead of Home. So +now TV remaps S-L to Home. From a report by David A. Capello +. + +Revision 2.74 2002/05/16 21:04:53 set +* Fixed: [X11] The code failed to track key-up events when other +application had the focus becoming out of sync. Now I added code to sync +the states. Works for XFree86 and Solaris. + +Revision 2.73 2002/05/16 18:54:15 set +* Added: A batch of patches from Mike for QNX. + * Configuration for libstdc++ + * strings.h inclusion. + * Class: member(value) -> Class { member=value; for some cases reported + by the compiler as problematic. + * Fixed: exclusion of X11 driver initialization if no X detected. + * time.h for puzzle.h demo. + +Revision 2.72 2002/05/16 18:19:30 set +* Added: QNX needs -shared to create a module for a dynamic library. +Pointed out by Mike. + +Revision 2.71 2002/05/15 20:43:48 set +* Added: The first patches to configure under QNX, they just add QNX +detection but more will be added. Patches by Mike Gorchak + +Revision 2.69 2002/05/15 19:06:14 set +* Fixed: Default CFLAGS for FreeBSD used -L/usr/local/include. Reported by +miniEleph (Andrew 'Onyx' Shevtsov). + +Revision 2.68 2002/05/15 01:51:44 terrible +* Modified: Updates to Debian packaging. +* Fixed: reordered external library linking for dynamic library (I think +thats the correct order). +* Fixed: add -lX11 to the linking of the dynamic library if building with +X11 support (creates needed dependency between the rhtvision library and +X11 library, and allows compilation of rhtvision programs without needing +to specify -lX11). + +Revision 2.67 2002/05/14 20:52:31 set +* Added: [X11] get/set window title. + +Revision 2.66 2002/05/14 20:17:30 set +* Modified: Now x11 headers are in the include/tv/x11 directory. Reported +by miniEleph. + +Revision 2.65 2002/05/13 19:30:22 set +* Modified: The intl/dummy/Makefile didn't define CC and GNU make used cc. + +Revision 2.64 2002/05/13 15:26:49 set +* Fixed: X11 cursor, again. + +Revision 2.63 2002/05/13 13:25:18 set +* Modified: [Win32] Reenabled code by Vadim that is supposed to compress +the mouse queue. Needs more investigation. + +Revision 2.62 2002/05/13 13:14:30 set +* Fixed: Win32 makefile now needs vpath for the DOS files (now separated). +* Updated: The files distribution list. +* Fixed: [Win32] Many typos and missing references in the Win32 code so now +it compiles. +* Added: [Win32] the console state and cursor position/shape is restored. +* Fixed: [Win32] the screen content is now restored, Vadim specified a +wrong rectangle. +* Updated: [Win32] the readme. +* I tested all with Cygwin and seems to quite functional. + +Revision 2.61 2002/05/13 13:03:35 set +* Modified: [UNIX] Now the FHS detection is more strict, the existance of +share/doc is not enough, share/man and shared/info must exist. +* Fixed: [UNIX] The FHS detection looks in $prefix and not in /usr. + +Revision 2.60 2002/05/10 18:52:23 set +* Fixed: [UNIX] makemak.pl assumed perl is installed in /usr/bin/perl, it +doesn't have to be true. Now the makefile uses: "perl makemak.pl". + +Revision 2.59 2002/05/10 18:46:33 set +* Fixed: [Solaris] getopt.c didn't include some needed headers. + +Revision 2.58 2002/05/10 17:34:44 set +* Modified: [X11] Cursor initialization. +* Fixed: [X11 Solaris] XmbLookupString doesn't support NULL for status. + +Revision 2.57 2002/05/10 15:21:13 set +* Modified: [X11 Solaris] It looks like Solaris 7 (at least the one I have +access) have a broken ITIMER_REAL. + +Revision 2.56 2002/05/10 14:17:27 set +* Modified: [X11] to use sigaction, seems that signal behaves different in +Solaris. + +Revision 2.55 2002/05/08 12:31:57 set +* Fixed: [UNIX] The .gpr include directory was hardcoded instead of using +TVSRC. From a report by miniEleph. + +Revision 2.54 2002/05/07 19:06:26 set +* Modified: [X11] Now only the changed text is updated. In the test case +it produced a 290% increase in speed. + +Revision 2.53 2002/05/07 16:54:08 set +* Added: [FreeBSD] getopt_long request in compatlayer. Reported by +miniEleph. + +Revision 2.52 2002/05/06 15:04:15 set +* Added: X11R6 include directory to the configuration script. It looks like +this directory isn't automagically included in FreeBSD. Also added options +to configure it -x-include and -x-lib. Reported by miniEleph +. + +Revision 2.51 2002/05/06 13:38:59 set +* Added: The first step for the Win32 driver. All is supposed to be there +but I didn't even try to compile. + +Revision 2.50 2002/05/06 13:32:17 set +* Modified: A lot of DOS code. Now you can get an usable demo application +for DOS. Screen, mouse and keyboard seems to be usable. + +Revision 2.49 2002/05/03 16:56:22 set +* Fixed: Invisible cursor in the Linux driver. + +Revision 2.48 2002/05/02 19:38:14 set +* Fixed: Window resize for X11. I didn't notify it to TProgram and the +window normalization was done before reallocating the screenBuffer. + +Revision 2.47 2002/05/02 19:37:15 set +* Fixed: TDisplay::defaultGetWindowTitle(void) returned a static string, +not newly allocated. +* Fixed: TScreenX11 cursor was using one extra memory location. Detected +with efence. + +Revision 2.46 2002/04/30 18:43:04 set +* Fixed: rhide.env files are now included by .mak files and the old syntax +to include another .env files isn't valid for make. Using "include" works +for both. +* Added: .mak files for the examples to the CVS. + +Revision 2.45 2002/04/30 18:13:10 set +* Fixed: When running in a generic color terminal (using 8 colors) no color +remapping was applied. As a result the colors were messed. +* Added: Some minor support for "screen" terminal. Both from reports by +"Tatu Kilappa" . + +Revision 2.44 2002/04/29 20:17:49 set +* Fixed: dual.cc shouldn't be in the makefiles. +* Fixed: TEditor used getshiftstate. + +Revision 2.43 2002/04/29 19:19:01 set +* Added: compat.mak to CVS so people without RHIDE can compile. +* Fixed: linuxso/makemak.pl needs to create a link to rhide.env for RHIDE +1.4.9 and newer. + +Revision 2.42 2002/04/22 18:26:55 set +* Fixed: The file collection didn't support duplicates, but when it was +configured to be no case sensitive in an OS that is case sensitive some +names could look like duplicates and be omitted. Reported by David A. +Capello . + +Revision 2.41 2002/04/22 18:11:04 set +* Fixed: The configuration script configured the examples for Win32 in all +platforms. +* Added: Some copyrights to the new base classes. +* Added: Code to debug cursor problems. +* Fixed: Cursor under X11. The target still buggy but is the most finished. + +Revision 2.40 2002/02/21 01:07:39 set +* Fixed: Some details to allow compiling under Linux. The code now +compiles. + +Revision 2.39 2002/02/20 01:31:25 set +* Fixed: gcc 3.x problems with GetStrStream() macro. Reported and solution +by Andris. + +Revision 2.38 2002/02/03 19:45:40 set +* Modified: Moved mouse.cc code to tevent.cc. It contains mouseInt() which +was reworked. +* Added: a new THWMouse member called drawCounter, used when the mouse is +drawn asynchronically by an interrupt. It can be accessed using TMouse +members: resetDrawCounter() and getDrawCounter(). Only needed by TView to +know if the mouse was updated while drawing to screen. +* Modified: Draw mouse to return 1 if the draw was necesary. +* Modified: TView to be more clean in the code that finds mouse position and +determines asynchronic draws. +* Modidied: Now the BIOS/direct mode for DOS driver is set using +SetKbdMapping. Two special values determines it: dosUseBIOS and dosUseDirect. +It allows for special actions (pointers redirection) and a portable mechanism +(you can use code that is valid for other drivers, not useful but valid). +* Added: Mouse and Keyboard headers for DOS are almost finished. + +Revision 2.37 2002/02/02 15:20:08 set +* Modified: Now OS specific headers are in separated directories. Example: +tv/linuxscr.h is now tv/linux/screen.h. + +Revision 2.36 2002/01/27 17:05:10 set +* Merged Ivan patches for Debian 1.1.4-1 package. + +Revision 2.35 2002/01/03 02:14:41 set +* Fixed: Need to create win32/rhide.env for Cygwin/MinGW targets. Needed for +RHIDE 1.4.9. + +Revision 2.34 2002/01/03 01:28:38 set +* Fixed: getline code for BC++ 5.5 target. [lack of ssize_t] + +Revision 2.33 2002/01/02 00:15:43 set +* Fixed: The configuration forced tvfintl for Linux. +* Fixed: RHIDE 1.4.9 includes rhide.env in generated makefiles so the new +makefile used for Linux needs a link to it in linuxso directory. + +Revision 2.32 2002/01/02 00:53:16 set +* Added: GNU getline replacement to compatlayer. + +Revision 2.31 2002/01/01 01:28:23 set +* Added: Code to avoid collisions between the last changes in tv/intl.h and +djgpp's conio. Note that gettext instructs users on how to change libc to +avoid such a collision. + +Revision 2.30 2001/12/31 21:59:23 set +* Modified: Now if gettext isn't detected the configuration uses the fake +internationalization dummy. It can be disabled with --no-intl. Why? it allows +people to install gettext *after* compiling TV, they just need to change the +linker options and all works. Pointed out by Laurynas. +* Added: --force-dummy option. It forces the use of tvfintl even if gettext +is installed. That's useful when most of your TV applications won't use intl +library. I use it for the editor that I compile using their own gettext under +DOS, in this way I avoid using iconv. +* Added: Documentation about it. +*** IMPORTANT *** I don't include libintl.h anymore and assume the +prototypes. This helps with the dummy and I doubt it will collide. If some +day it collides the configuration could indicate how to solve it. + +Revision 2.29 2001/12/30 23:34:07 set +* Fixed: A couple of new[]/delete style missmatches while debugging setedit +with MSS 1.2.1. + +Revision 2.28 2001/12/30 18:35:46 set +* Fixed: Compatlayer undefined FA_DIREC even in cases that didn't redefine +it. + +Revision 2.27 2001/12/30 18:33:33 set +* Added: Support for MSS 1.2.1 and fixed missing delete [] in demo. Patches +by Laurynas. +* Added: Configuration options to use MSS and documentation in the readme. +* Fixed: Various missing delete [] in the classes. + +Revision 2.26 2001/12/30 16:15:10 set +* Fixed: I wrongly changed the code used for the BC++ 5.5 target to yield +the processor to use the MinGW version. It made applications eat 100% of +the CPU. + +Revision 2.25 2001/12/18 02:34:11 set +* Added: Fine grained protection against multiple inclutions in compatlayer +header. + +Revision 2.24 2001/12/17 00:20:32 set +* Added: A new URL to the Borland's FAQ that says TV is Public Domain. This +is supported by all the TeamB people I contacted. + +Revision 2.23 2001/12/11 00:59:59 set +* Added: TDisplayDOS is almost finished. +* Added: Started to work on DOS mouse driver. + +Revision 2.22 2001/12/11 00:26:45 set +* Added: Some adjusts to compatlayer for Cygwin target. Needed to compile the +editor. Patch from Robert. + +Revision 2.21 2001/12/06 01:17:15 set +* Fixed: Some errors in listvi example. It used constant strings for input +lines (read only on UNIX and of limited size a disaster). Also fixed the size +of the columns and input line to be nicer. Reported by Wojciech Warczakowski +(Wowar) . + +Revision 2.20 2001/11/29 23:08:41 set +* Modified: Solaris have nl_langinfo so we don't need to use the +replacement. I didn't check if this correction works. + +Revision 2.19 2001/11/28 23:41:26 set +* Added: getopt when Solaris is detected. + +Revision 2.18 2001/11/25 19:07:33 set +* Added: TEditorApp dependency (TApplication) to the tv.h. + +Revision 2.17 2001/11/25 18:46:44 set +* Modified: compatlayer.h should be included just once as tv.h, but this +isn't the case for all the applications and enforces a policy that doesn't +have to be the same used by other projects. For this reason I removed the +protection and any collision will be solved for the particular case instead +of protecting the whole file. After a talk with Andris. + +Revision 2.16 2001/11/25 16:12:00 set +* Added: Some support for linux-* terminals. Patch provided by "Dimitar +Jekov" + +Revision 2.15 2001/11/25 15:44:29 set +* Fixed: Desklogo examples to work with anything different than 80x25 and a +lack of a redraw in tv_logo. Reported by Cesar Rabak . + +Revision 2.14 2001/11/25 14:59:58 set +* Changed: classes/WinNT to winnt, it avoids some problems. +* Compiled all the stuff to verify that I incorporated all the needed code, +it changed makefiles and other stuff. +* Merged Ivan patched for debian package 1.1.3-3, but they are outdated for +this new 2.0.0 branch. +* Added include/tv/drivers.h, it defines prototypes for all the drivers +entry points. +* Added classes/tgkey.cc, it replaces gkey.cc but is the abstract driver +base containing common code for all the platforms. + +Revision 2.13 2001/11/25 00:41:41 set +* Added: Definitions for middle mouse button and also buttons 4 and 5. + +Revision 2.12 2001/11/25 00:39:38 set +* Changed: call to new API name in demo example (to set window title). + +Revision 2.11 2001/11/25 00:34:04 set +* Modified: TView because now the functions to set the shape of the cursor +are compatible with BTV 2.0 and not BTV 1.03. Also a change in an extended +member. The names of extended members changed to keep API coherence and +avoid pointer collisions. + +Revision 2.10 2001/11/25 00:31:40 set +* Modified: TProgram because I changed the names of some members in TScreen +(all extensions not found in BTV) and to avoid using the magic "dual" +variable. That's temporally part of TDisplay but just to compile, it must +be solved in another way not yet fully defined. + +Revision 2.9 2001/11/25 00:29:02 set +* Modified: TEventQueue::resume to avoid calling magic Linux functions, now +TGKey have a suspend/resume for it. + +Revision 2.8 2001/11/25 00:26:56 set +* Modified: TColorDialog to avoid using the old getBlinkState function, now +part of the TScreen class. + +Revision 2.7 2001/11/25 00:12:12 set +* Added the headers for the Linux and X11 drivers. +* Changed the screen.h, event.h and gkey.h headers to declare the new class +structure. + +Revision 2.6 2001/11/25 00:04:03 set +* Changed classes/tdisplay.cc, classes/tscreen.cc and classes/thwmouse.cc +by the new class structure. This is a complete rework of the classes but +maintaining backward compatibility. + +Revision 2.5 2001/11/24 23:56:50 set +* Moved gkey.cc, classes/tdisplay.cc, classes/thwmouse.cc and +classes/tscreen.cc to the DOS driver because they have the DOS code. They +will be changed to follow the new class structure. + +Revision 2.4 2001/11/24 23:43:28 set +* Added: A new driver for X11, it is quite functional and complete. + +Revision 2.3 2001/11/24 23:40:10 set +* Merged: New code for the Linux terminals. It's currently only one driver +(the mouse is the only exception) and should be split in three, but is +adapted to the new class style. + +Revision 2.2 2001/11/24 23:21:19 set +* Changed version to 2.0.0 because big changes are about to be merged. + +Revision 2.1 2001/11/24 23:18:11 set +* Added: X library detection to the configuration. + +Revision 2.0 2001/11/24 23:12:33 set +* New change.log file created. diff --git a/tvision/change1.log b/tvision/change1.log new file mode 100644 index 0000000..6d54b4f --- /dev/null +++ b/tvision/change1.log @@ -0,0 +1,1621 @@ +This is the log file for versions of the 1.x series + +Tagged as tv1_1_3b2 and branched tv1_1_3b2_patches +Revision 1.242 2001/11/06 23:31:08 set +* Fixed: A typo in compatlayer.h, it defined sdtio instead of stdio ;-). +Reported by "Jerzy Witkowski" . + +Revision 1.241 2001/10/31 01:00:56 set +* Added: --no-fhs to the configuration. Patch provided by +jimmy@ncp.infonet.bg. + +Revision 1.240 2001/10/25 00:32:12 set +* Fixed: The gkey.cc program assumed that Linux is the only UNIX ;-) I +noticed it while trying to test the keyboard routines running Solaris. + +Revision 1.239 2001/10/23 00:57:43 set +* Fixed: Some compilation problems when using the last CVS snapshot of gcc +3.1. All in the examples and related to specify std namespace as the +default namespace. Patches provided by Andris Pavenis, just converted to +the little macro I use to hide namespace stuff. + +Revision 1.238 2001/10/22 23:35:05 set +* Added: linuxso/Makefile and linuxso/compat.mak to the distribution list. +They are needed in some cases. + +Revision 1.237 2001/10/20 01:02:51 set +* Merged Debian packaging patches from Ivan: + * Now compiles with -D_REENTRANT as Debian Policy mandates. + * Now runs ./configure before make clean (reported by Salvador). + * Don't eliminate the ldconfig invocation of the upstream Makefile, + it seems that upstream has corrected its Makefile now (done after + Salvador reported that it didn't work on all systems, because I was + overwriting the Makefile while I was reading it, specially on + multiprocesor systems). + * Added include/tv/configtv.h to files_to_backup. +* Fixed: The configuration script modified RHIDE Makefiles in the wrong way +when the original RHIDE variable used more than one line. +* Modified: Ivan added more log info to the Linux mouse. + +Revision 1.236 2001/10/18 00:35:42 set +* Merged patches for Debian stuff from Ivan. + +Revision 1.235 2001/10/18 00:10:06 set +* Fixed: I forgot to update the linux/Makefile file from the project file. +It prevented the code to compile for FreeBSD. + +Revision 1.234 2001/10/17 23:52:54 set +* Fixed: [Linux] DECIMAL_POINT is GNU specific and not the right value to +use like the glibc info says. The value RADIXCHAR is indicated like this: +"The name `RADIXCHAR' is a deprecated alias still used in Unix98." so I +used DECIMAL_POINT. But the same idiots moved DECIMAL_POINT to _GNU_SOURCE +section because it *isn't* standard (glibc 2.2.x). So now I use RADIXCHAR. +Now I wonder what idiot wrote "The Elegant and Fast Way X/Open's +`nl_langinfo'." when this is poorly supported and have such a details. + +Revision 1.233 2001/10/17 23:28:18 set +* Fixed: Not all of the configured values were transfered to the makefile. +They were correctly put in the *.env files but not in the makefile. It +included the GNU ar name. +* Fixed: The compat layer makefile wasn't configured. + +Revision 1.232 2001/10/17 22:38:51 set +* Fixed: [UNIX] Unconditional request for definekey() + +Revision 1.231 2001/10/17 22:35:55 set +* Fixed: Now clean target also deletes the configure.cache. + +Revision 1.230 2001/10/17 22:32:57 set +* Fixed: Now "make clean" really cleans the example objects and executables. +* Added: A makefile for the examples, mostly to make the clean but can be +used to generate all the examples. +* Added: An examples target to the makefile. +* Added: Now the configure script says if the configuration header was +replaced or not. + +Revision 1.229 2001/10/17 21:52:58 set +* Added: A #undef gettext in intl.h for DOS. I hope it solve collisions with +conio.h that are popping again (with old gettext versions). + +Revision 1.228 2001/10/17 00:28:12 set +* Modified: The Win32 port uses a case sensitive glob to match wildcards in +directories but Win32 isn't really case sensitive (is HPFS case sensitive?). +Owen Rudge reported problems because *.txt and *.TXT +doesn't match the same files. So I disabled the case sensitive comparisson. + +Revision 1.227 2001/10/17 00:00:29 set +* Added: to the readme notes about some success compiling for Linux+HPPA+gcc +3.0 reported by Joël Soete . [ISO-1] + +Revision 1.226 2001/10/16 23:53:18 set +* Fixed: A couple of formating errors in the ASCII table and Calendar of the +demo example. Patch from Waldemar Schultz + +Revision 1.225 2001/10/13 23:53:49 set +* Fixed: The clean target didn't ignore errors from the examples/clean +script. + +Revision 1.224 2001/10/13 23:30:24 set +* Added: International dummy library to the Makefile. Suggested by +Laurynas. +* Merged: Changes for the Debian stuff from Ivan. + +Revision 1.223 2001/10/13 22:50:05 set +* Removed autoconf example because it doesn't work anymore. Laurynas is +working on a new version. + +Revision 1.222 2001/10/13 21:40:20 set +* Fixed: The BC++ 5.5 makefile lacked a rule to make C++ components of +compatlayer (currently just a file). Patch by Owen Rudge . +. +Revision 1.221 2001/10/12 02:54:44 set +----------------------------------------------------------------------------- +v1.1.3 release. Switching to stable. + +Revision 1.220 2001/10/10 14:56:15 set +* Fixed: The TRangeValidator was supposed to support hexa numbers but +didn't accept A-Fa-f. Also changed the complex and slow scanfs to +strtol/stroul. Reported and solutions suggested by Andris. +* Added: An example of TRangeValidator to the Tutorial number 16. I used it +to test the changes ;-). I also added an example of the messageBoxes that +uses printf style parameters. + +Revision 1.219 2001/10/08 23:36:18 set +* Fixed: [gcc 3.x] fpstream(int fd) was creating a text mode stream and not +binary. + +Revision 1.218 2001/10/07 23:30:00 set +* Fixed: Damn! BC++ 5.5 implementation of ifstream::getline differs from gcc +v2.x and v3.x. So now I created a compatlayer macro: IfStreamGetLine(object, +buffer, size). For gcc it expands to object.getline(buffer,size) but for bcc +is expanded to a function call that makes get for the line and then removes +the EOL. Now the demo and tutorials seems to work for the three compilers. + +Revision 1.217 2001/10/07 22:21:16 set +* Fixed: The demo to work with gcc 3.x streams. Andris suggested the fix +according to the following information: C++ standard draft at +ftp://research.att.com/dist/c++std/WP/ says about get in (27.6.1.3): If the +function inserts no characters, it calls setstate(failbit), which may throw +ios_base::failure (27.4.5.3). It looks like it makes get to stop reading and +the best is to use getline. In the gcc 2.x iostream info file says: "If +DELIM was present in the input, it remains available as if unread; to +discard it instead, see `iostream::getline'." + +Revision 1.216 2001/10/07 22:05:20 set +* Added: A nl_langinfo replacement to compatlayer library, it just +implements part of the functionallity. BTW according to glibc people using +localeconv is for lames ... it looks like djgpp, MinGW, CygWin, BC++, etc. +users are lames ... + +Revision 1.215 2001/10/07 20:27:32 set +* Fixed: I forgot to install the cl/*.h files! +* Added: A mechanism to create the .deb packages without root priviledges. +I used information from Ivan. The easiest way is running +debina/builpackage. + +Revision 1.214 2001/10/07 19:44:03 set +* Merged patches from Ivan for the Debian package, they avoid deleting +default configuration files. + +Revision 1.213 2001/10/06 18:19:12 set +* Added: Support for localized decimal point in the pocket calculator. The +user types the '.' key but the calculator displays the right decimal point +symbol. Without it the calculator fails to work for locales that uses +another decimal point (like mine). + +Revision 1.212 2001/09/30 21:03:31 set +* Fixed: Now the scripts generate Debian versions with -0.1 as suggested by +Ivan. +* Fixed: debian/control.in had extra \n at the end that were passed to +debian/control every time. + +Revision 1.211 2001/09/29 02:11:10 set +* Modified: I made the library compile with gcc 3.0.1. This new version of +gcc implments the ISO C++ 1998 standard and hence changes a lot of things +about the C++ streams. I got some help from Andris Pavenis and Christoph +Bauer. Andris already compiled the library using some quick and dirty patches +and Christoph suggested good solutions for some of the problems. +* Fixed: New standards enforce the use of an EOL at the last line of code. +* Fixed: New standards deprecates multi-line strings, they are very +convenient for inline assembler. That's a really bad thing. +* Added: A good amount of macros to compatlayer to reduce the impact of the +new streams semantics. +* Modified: Now fpbase::filebuf buf; is a pointer (is a private member). +* Added: fpstream::filelength() because now is invalid to ask for the file +descriptor of a stream. +* Modified: The asm(register) modifier now doesn't work as with gcc<3. +* Fixed: A huge amount of errors in the dialog editor that gcc 3 now +detects (like bizarre casts or returning pointers to local variables). +. +Revision 1.210 2001/09/26 00:08:09 set +* Modified: [DOS] Now the useBIOS variable is the default for the keyboard +routines. According to reports of various users it looks like some new +BIOSes are handling the keyboard buffer in a not standard way. Until we +don't find what exactly is going on I decided to use the BIOS routines by +default (which fixes the problems). An example of report was from +Jcbk455@aol.com, he reported ASCII 7 inserted every 13 keystrokes. I +consulted in the lists and nobody was against it, Robert was in favor. + +Revision 1.209 2001/09/25 23:18:41 set +* Modified: [UNIX] Now if the user is the superuser (uid 0 is ok?) the +library uses the owner mask to report R.O. status. This is not quite true, +the root can write on it but if the volume is R.O. I think that's the best +clue we have. + +Revision 1.208 2001/09/25 23:08:01 set +* Added: [Linux] Support for /dev/vc/NN devices in the keyboard routines. +Thanks to Andris, he have a system that uses it. + +Revision 1.207 2001/09/25 02:17:04 set +* Fixed: Problems in TEditor class when handling UNIX files. +* Fixed: A bug introduced by JASC while adapting teditorf.cc to work for +big endian platforms. It rendered TEditor buffers as only spaces ;-) +Reported by Owen Rudge . +* Fixed: Tons of warnings, some of them bugs that made impossible to +compile the Dialog Design program. +* Fixed: One of the desklogo examples was supposed to show the use of ^Z +signal handling but forgot to include signal.h (generated obvious errors). +* Fixed: Removed header dependencies from all examples, now they depend +only on headers included with #include "". I did it because patchenv.pl +can't handle multiple directories and I think that isn't really necesary. +In this way I'll never let pass system dependent dependencies. + +Revision 1.206 2001/09/23 20:05:12 set +* Modified: Moved all the macros to define if we need \r\n or \n from +setedit to the compatlayer library. + +Revision 1.205 2001/09/23 19:08:27 set +* Modified: [Linux][Xterm] Now if the library detects xterm puts the keypad +in the normal mode (looks like ncurses put it in a special mode) it makes +the keypad usable. I'm sick of these silly ncurses+terminfo stuff. + +Revision 1.204 2001/09/22 02:16:56 set +* Modified: [UNIX] The behavior of file attribute functions of compat +layer, now the IsReadOnly tries to be a little more cleaver looking for the +file group and the groups where the user is. + +Revision 1.203 2001/09/21 02:30:20 set +* Fixed: New standards seems to enforce a \n at the end of all sources. At +least gcc 3.0 says that. I added it to all the tests in the configuration +scripts. +* Fixed: [DOS] GCC 3.0 doesn't compile C++ code using the C compiler. The +configure script can detect it, but as it only happened with very old gcc +versions the scripts were looking for gxx and currently the C++ compiler is +inoked using gpp. +* Added: More MSS details (from last change). +* Added: More packed details (from last change). +* Added: no_mss.h and yes_mss.h to the distribution list. +* Fixed: glob.c had text after a #endif, gcc 3.0 detects it. +* Fixed: isrelpath.c didn't end with \n, gcc 3.0 detects it. +Note: Sergey Krivulja reported it also for gcc 2.96. + +Revision 1.202 2001/09/21 01:20:43 set +* Added: Now the library is `MSS aware'. Laurynas sent me some patches for +it and I adapted them. MSS is a memory debugger. +* Modified: Uniformized the use of __attribute__((packed)) [Laurynas +patches] and added to the compatlayer. +* Modified: Now the uint* and uchar, uint, ulong, etc. types are part of +compatlayer. I saw a collision with types defined but GNU libc (only for C +sources where you can't define the same type twice :-(. Currently is solved +case by case but I think it could be solved computing what headers are +requested. It looks like for some ancient reason sys/types.h defines it. +This action changed all name files. +* Modified: The Boolean type is now also part of compatlayer. + +Revision 1.201 2001/09/20 22:26:53 set +* Fixed: The keyboard internal structure wasn't "endian aware". Wow! now +the mouse, shadows and keyboard seems to work for PPC and SPARC. + +Revision 1.200 2001/09/20 01:11:37 set +* Modified: Now the configuration script doesn't need pwd, if it fail uses +cd command. +* Added: Creation of examples/rhide.env for the Win32 target. +* Added: Now the config.pl updates the win32 Makefile so MinGW users without +all the needed tools have a chance to compile. +* Modified: Now the configuration detects more details and defines +preprocessor variables acording to it. The definitions are also less +confusing. Now they are OS, OSf (subtype of OS), Comp (Compiler), Compf +(subtype of compiler) and CPU. With it I removed almost all magic __*__ tests +that are usually tricky and not so clear. +* Added: Cygwin target, with the help of Ronald Landheer +. +* Added: Better prefix detection for MinGW. +* Fixed: The version.txt file messed things if ended with \n, now is ok. +* Added: A definition to compatlayer to identify systems where drive letters +have any sense (CLY_HaveDriveLetters). +* Added: More use of compatlayer Uses_* mechanism. +* Added: Uses_abort to compatlayer (MSVC have it process.h). +* Added: More code to solve the endian problems with the shadows. +* Added: Code to solve the endian problem with the mouse attribute. +* Modified: win32/trans.cc, win32/console.cc and win32/gkey.cc now are just +one file. It helps to maintain uniform the list of files. +* Modified: the win32/readme.txt to reflect the changes. + +Revision 1.199 2001/09/16 20:05:39 set +* Updated: Distribution readme and debian/changelog. +* Fixed: debian/control had extra new line characters. +* Fixed: Now the scripts of distribution updates debian/changelog with my +name and stating it was a script. Sugested by Ivan. +* Added: .exe files to the list of excluded in Linux source distribution. + +Revision 1.198 2001/09/16 18:09:00 set +* Added: Code to solve the endian problem in shadows. Must be tested. + +Revision 1.197 2001/09/16 17:52:53 set +* Added: Updated information about supported platforms to readme.in. +* Added: A clean target to the makefile. It only deletes the objects and +libraries. + +Revision 1.196 2001/09/16 16:52:07 set +* Added: Architecture detection to the configure. It defines TVCPU_$(Arch). +* Added: GNU make detection to the configure. It supports gmake as name. +* Added: GNU ar detection to the configure. It supports gar as name. +* Fixed: In systems different than Linux and DOS RHIDE makefiles doesn't +include -lstdc++ (RHIDE_TYPED_LIBS_$(RHIDE_OS).cc is not defined). So now +the configuration puts them as RHIDE_OS_LIBS. Seen on FreeBSD and Solaris. +* Added: Support for ncurses installed as -lcurses (I saw it in Solaris). +* Added: Now CFLAGS and CXXFLAGS can be passed to the configuration in the +command line (must use the perl script directly, no the shell script!). It +made the configset script usable with any UNIX shell (/bin/sh isn't bash in +a lot of UNIX systems). +* Fixed: When detecting if define_key is available in ncurses the version +isn't enough. Seen on Solaris. +* Fixed: Warning about configure.cache not exits in configset. +* Fixed: When detecting gpm in systems lacking it the config script said +"too old" instead of "non existent". It was a side effect. +* Added: SunOS to the list of systems supported by the configuration. It +doesn't mean the library is working there. +* Modified: References to __i386__ by TVCPU_x86. +* Fixed: When creating the dynamic library the list of libraries was listed +twice. + +Revision 1.195 2001/09/16 12:44:19 set +* Fixed: [Linux] Now is included only when needed +(i386+Linux). After fixing it the code compiled for Linux: Alpha, PPC +(RS/6000) and SPARC (Ultra60 w/2 CPUs) and FreeBSD+x86. Some big endian +details must be solved but the demo works for all the platforms. Some +configuration details must also be solved. + +Revision 1.194 2001/09/09 22:10:48 set +* Fixed: [BC++/Win32] Some unused variable warnings. It looks like BC++ 5.5 +needs something like if (unused) unused=0; to understand we don't want it. +* Fixed: [BC++/Win32] Some comparisson between signed and unsigned. +* Added: Now both compress scripts (djgpp and linux) updates the BC++ 5.5 +makefile. +* Modified: intl.h to define HAVE_INTL_SUPPORT as 1 like in the +configuration file or gcc will get mad. +. +Revision 1.193 2001/09/09 19:58:18 set +* Modified: version to 1.1.1. +* Added: Comments about the modification of the cursor behavior. + +Revision 1.192 2001/09/08 20:16:14 set +* Added: itoa to the compatlayer. This function is fast for converting +integers into strings and seems to be suitable for calling from an async +point (like a signal). I used djgpp implementation. +* Fixed: when TDesktop was locked nothing but the cursor was updated. Now +the cursor isn't updated. I hope it doesn't break anything, I think I did +it in a clean way. In the past while the editor was loading a big list of +texts the desktop remained locked but you could see the cursor jumping all +around the screen as the TCEditors were inserted/selected in the desktop. +Now the cursor remains still until unlock calls resetCursor(). + +Revision 1.191 2001/09/08 18:02:01 set +* Modified: [Linux] Now the TV_system function creates a new session for +the child process it implies two important things: 1) The child is a leader +of a group so calling kill(-pid_child... kills all the processes in their +group. 2) The child doesn't have controlling terminal so it can't read/ +write to the parent console. I think that's good. The output is usually +redirected so no problem there, but I must investigate what happends if the +process reads (just error or a signal?). + +Revision 1.190 2001/09/05 20:10:44 set +* Added: [Linux] Now I also patch the ^[ key to just return [ (not ESC). +This enables a needed key for setedit. +* Fixed: [Linux] gkey.cc to compile with the current library. + +Revision 1.189 2001/09/05 18:40:29 set +* Fixed: Some problems in the TSortedCollection incremental search. The +backspace wasn't working (at least on Linux), the `.' didn't show the jump +to the extension correctly, files with more than one . weren't supported, +etc. I hope it now works better. + +Revision 1.188 2001/09/04 19:23:48 set +* Fixed: [Win32+BC++] bug when only one key modifier (Shift, Control, Alt) +was detected. Patch from Anatoli Soltan + +Revision 1.187 2001/09/04 18:32:14 set +* Added: inline TMenuItem& operator + ( TMenuItem& s, TMenuItem& i ). +It makes the creation of nested menues more readable. Sugested by Dean +Wakerley . + +Revision 1.186 2001/09/04 18:05:42 set +* Fixed: It was impossible to use CFLAGS options that contained +option=value because it confused patchenv.pl failing to configure the +makefiles. Reported by Norberto Alfredo Bensa + +Revision 1.185 2001/09/04 03:46:22 set +* Added: The TColorSelector mark wasn't available to remap to other code +page (fixed code 8). Now is TColorSelector::mark. + +Revision 1.184 2001/09/03 23:11:23 set +* Added: Options for the TFileCollection to sort .* files after the rest. +* Added: Options for the TFileCollection that affects TFileList so some +files aren't listed: *~, *.bkp and .*. I also reindented and cleaned some +code in tfilelis.cc. + +Revision 1.183 2001/09/03 20:20:28 set +* Added: Now any TCluster (radio buttons, check boxes, etc.) that have a +state sfDisabled is painted with a different color. I mapped it to color +0x3E (previously reserved) and by default is dark gray over cyan. + +Revision 1.182 2001/09/01 22:37:28 set +* Added: A new parameter for TV_System: pid_t *pidChild=0 if this parameter +is passed and the OS supports it and we implemented it (read: only for +Linux right now ;-) system creates a child process and calls exec with the +provided command. As a result the command starts to run in background. The +pidChild pointer is filled with the pid of the child. Right now all is too +POSIX and I hope I will be able to generalize it for other systems. + +Revision 1.181 2001/08/31 19:36:56 set +* Modified: Now if the terminal have fixed encoding the scroll bars uses +the original chars. That's because we can't trust in any redefined value. + +Revision 1.180 2001/08/31 19:34:58 set +* Added: A function to know if the terminal have a fixed encoding and we +shouln't offer to the user recoding options. Boolean codePageVariable() + +Revision 1.179 2001/08/31 01:13:44 set +* Modified: I cleaned the writeBlock() function of tscreen.cc. It became a +mess. I removed the C_, C__ and C___ macros and the __SAVECURSOR_OK option. +Also removed some redundant checks and reindented the code. +* Fixed: Now writeBlock() is Endian safe. I got reports from David Nock + who was working in a Linux PPC. I used code ideas from +the version that José Angel Sánchez Caso (JASC) sent +me but I couldn't find time to merge. +* Added: Two functions to compat layer library to get the high and low +nibble of 16 bits values (according to the endianess of the platform). +* Fixed: Some times after a suspend/resume of the keyboard ttyname failed +to return the name of the terminal (who knows why?). Now if the name was +already known and the new calls fails the old information is used. It was +part of an Andris patch that I applied but not enabled because I have +doubts about a line that now I left commented. + +Revision 1.178 2001/08/30 20:58:23 set +* Modified: [Linux] A lot of low level details in the TScreen class: +* Added: An internal variable TerminalType to hold the type of terminal, it +can be: +VCSA_TERMINAL The Linux console with access to /dev/vcsa*. +LINUX_TERMINAL The Linux console without access to /dev/vcsa* +GENER_TERMINAL A generic terminal. +* Modified: Now LINUX_TERMINAL sets the terminal to use G1 charset and sets +the G1 charset to the screen font (user defined). It means that now TV +applications that doesn't have access to /dev/vcsa* have access to all +symbols anyways. I had to do some tricks to get some control characters +printed. I used the UTF-8 mode that Linux have (unicode). So now the fonts +loaded by the user will be used (I can see my accents correctly). +* Fixed: The 127 and 128+27 codes are control characters and shouldn't be +printed. It deformed the "ASCII" window. +* Fixed: After suspend/resume the calls to endwin/doupdate messed up the +selected charset. I think that's a bug in ncurses. It was noted when you +suspended to a shell and resumed (frames damaged). Now the library ensures +the right charset is selected after doupdate(). +* Modified: Now RestoreScreen() (called by suspend) clears the screen if +the user screen can't be restored. That's good for calling a shell and is +less confusing than just do nothing. +* Modified: Now when using GENER_TERMINAL only the frames are remapped from +PC437 letting some ISO Latin 1 accents alive. That's not perfect but is +better than previous behavior. I have ideas about how to enhance it. + +Revision 1.177 2001/08/30 20:42:19 set +* Added: Now the install target is separated in three parts: +install-headers, install-static and install-dynamic. The install target +means the three, but you can just install the dynamic library. It helped me +a lot while testing things with the editor. + +Revision 1.176 2001/08/29 23:27:07 set +* Fixed: An error in the config.pl that put libintl.a for Linux target. + +Revision 1.175 2001/08/29 22:49:01 set +* Added: A function to get the name of the shell to the compat layer +library. + +Revision 1.174 2001/08/28 20:57:50 set +* Modified: Disable the sched_yield() method in yieldpro.c. I don't know if +it's working, I guess so, but top says the applications uses 99% of the +CPU. I guess that's because I only running this application (all the rest +are sleepping) and hence Linux doesn't have anyone to yield the CPU and +returns inmediatly. That's OK, but I'm sure users will complain because it +gives the impression that we eat all the CPU. + +Revision 1.173 2001/08/28 16:22:48 set +* Added: A dummy libintl.a library. This is provided for people that have +configured the library with international support but want to create one or +more executables without it. I created it after some mails from Laurynas +Biveinis . +* Added: An explanation of it to the readme.txt file and also some +explanation about the impact of libiconv.a. +. +Revision 1.172 2001/08/28 14:26:32 set +* Added: Support for gettext 0.10.37 and newer that needs libiconv. I tested +it with 0.10.39 and libiconv 1.7. The detection was enhanced and the examples +are configured to use -liconv if needed. Thanks to Laurynas for ideas and +some Perl patches. +. +Revision 1.171 2001/08/27 19:57:56 set +* Modified: Now the yieldproc.c module uses the POSIX sched_yield function +if available. It must be tested to see if that's good. Sugested by +Robert Varga . +. +Revision 1.170 2001/08/17 00:15:44 set +* Modified: The debian files. Mainly to reflect the new dependencies and +warn users about doubts in Borland's license. From Ivan Baldo. +* Fixed: [Linux] The dynamic library didn't recompile the compat library +with -fPIC. Report and ideas by Ivan Baldo. + +Revision 1.169 2001/08/16 02:51:32 set +* Fixed: The bug mentioned in the last check in. Now when looking for the +parent's console we stop if any parent isn't attached to a terminal. It +works for my X because none of the X terminals I have are attached to a +terminal, but we must see if that's enough. + +Revision 1.168 2001/08/16 01:55:48 set +* Fixed: The terminal attributes saved in startcurses were not restored in +stopcurses (but in the destructor) making assymetric the calls. Patch by +Robert. +* Modified: Now sys/perm.h is used and asm/io.h doesn't need to be +protected from sys/io.h. Robert hint. +* Added: Now if the library isn't in a virtual console the library tries +harder to find out if this is situation is because the parent spawned the +program in a terminal like a pts/x. If this is the case the library finds +what terminal owns the parent and uses it. This is very nice to bypass +programs like Midnight Commander, but have a serious drawback that I must +fix in the next minutes: X is also bypassed ;-). Patch from Robert. +* Fixed: ticks.h used NULL without including stdio.h. Patch from Robert. +* Fixed: Warning about unused variable in gkeyli.cc when HAVE_KEYSYMS was +not enabled. Patch from Robert. + +Revision 1.167 2001/08/15 23:58:19 set +* Added: The .mak files to the Linux distribution. +Released as beta. + +Revision 1.166 2001/08/14 15:20:47 set +* Added: Makefiles for all the examples. They are created/updated when the +package is created and updated by the configure script to be adapted to the +target system. Documented. +* Fixed: Various compilation errors in the examples. +. +Revision 1.165 2001/08/13 23:31:28 set +* Added: The Dialog Editor to the distribution and mentioned in the readme. +* Added: A .po file containing all the messages that can be internationalized +in Turbo Vision. +. +Revision 1.164 2001/08/12 20:56:34 set +* Added: A check in TCluster::draw to avoid buffer overflows. I don't know if +it is really needed but a user asked for it and is better to double check +this nasty details. Sent by Warlei Alves. +* Added: A Dialog Editor created by Warlei Alves, he can't follow this +project so now it will be part of the examples directory. +. +Revision 1.163 2001/08/12 19:41:05 set +* Fixed: A problem only found in RHIDE. Programs should never call +TScreen::resume() directly but TApplication::resume() instead. RHIDE abuses +of some Turbo Vision internals and hence needs to call TScreen::resume(). The +problem is that TProgam::buffer is tied to TScreen::screenBuffer and if you +call TScreen::resume() and it reallocates TScreen::screenBuffer then +TProgam::buffer gets unsynchronized and TProgram writes to deallocated data. +Andris sent me a patch to make it happend only in almost impossible cases, +but it could theoretically happend anyways. So I added a new TProgram member +called syncScreenBuffer(). If a program abuses TV calling TScreen::resume() +directly, then it should call TProgram::syncScreenBuffer() inmediatly. +. +Revision 1.162 2001/08/12 16:47:42 set +* Merged patches from Andris addressing compile issues related to gcc v2.97 +and newer releases: +1) Internal string functions must be declared (#include ). +2) Is no longer valid to directly cast a pointer to a integer smaller than +it, two casts are needed. +3) Friend classes must be explicitly named as classes. +. +Revision 1.161 2001/08/05 00:27:56 set +* Fixed: Problems with the detection of input/output functions provided by +libc 2.1.3. + +Revision 1.160 2000/12/09 21:17:06 set +* Applied changes from Anatoli to the WinNT port. They enhances the +configuration process and fixes some problems and typos. Read-only temporals +was fixed. +* Reverted the if ( !key ) return False; added to TNSSortedCollection::search +because it generated a nasty bug in the editor. +* Updated the winnt/readme.txt to reflect the current steps. +* Added a TODO file. +. +Revision 1.159 2000/09/24 14:53:46 set +* Added: Endianess detection to the configure mechanism. It defines +TV_BIG_ENDIAN for big endian machines. +* Modified: Solved collisions between gettext and conio.h. +* Added: New members to ipstream and opstream, they are intended to write +architecture independent values to disk. This started with a patch from +Jose Angel Sanchez Caso (JASC). +* Added: Names for platform independent types in ttypes.h. Currently they are +defined correctly only for x86 (gcc, MSVC and Borland). +* Fixed: Unconditional inclusion of gpm in UNIX, this is not good. +* Added: Big endian support in teditorf.cc by JASC. +* Fixed: __linux__ conditionals made generic UNIX. +* Merged some fixes to compile with -DNO_STREAM from Laurynas Biveinis +, more work is needed to complete it. + +Revision 1.158 2000/08/10 23:58:26 root (set) +* Fixed: The glibc 2.1.3 outb check to be done by configure script. Hey! +these guys have 2 errors: (1) they should provide a way to avoid collisions +with kernel headers (they are older) and (2) They doesn't have the ".3" info, +just 2 and 1 (MINOR), that's quite stupid. +. +Revision 1.157 2000/08/09 23:25:26 root (set) +* Fixed: Now glibc 2.1.3 defines outb/inb so they get defined twice (glibc+ +kernel headers). I added a test to avoid including the kernel headers if they +were defined. But I must check it because I don't have 2.1.3 at home. +* Added: Now the compatibility layer saves the UID/GID when asking for the +files attributes. Under DOS/Win32 this is avoided. + +Revision 1.156 2000/06/06 00:28:30 root (set) +* Added: A warning message to the configure script if gpm can't be found under +Linux. + +Revision 1.155 2000/06/06 00:12:55 root (set) +* Fixed: [Linux] the dynamic library unconditionally requested libgpm even +when the configure detected it wasn't installed. + +Revision 1.154 2000/06/04 18:40:39 set +* Updated: The list of files and DOS files. +. +Revision 1.153 2000/05/23 01:43:23 set +* Added: Now the configuration process generates the BC++ makefile. Even when +people using BC++ won't use it I can use it to update the makefile. +* Fixed: conflib.pl declared local variables wrongly. +* Added: A function to conflib.pl to collect project items from a .mak. +* Added: fileview.cc to the BC++ port. +. +Revision 1.152 2000/05/22 23:52:32 set +* Modified: Now the configtv.h isn't generated if the new one is identical. +It avoids a masive recompile after configuring. +. +Revision 1.151 2000/05/20 20:02:21 set +* Modified: The generated make file to use PHONY and force a real check of +all the dependencies even if the library is already generated. +* Added: Now the win32/Makefile file is generated from the djgpp's file +during the configuration process. For this I modified the djgpp/vga* files to +produce no code if they are compiled without djgpp. +* Added: a thanks section to the main readme. +* Added: some details in the readme, specially about RMS doubts and what I'm +doing about it. Also to make clear the win32 and winnt targets are there and +both works for win32. +* Fixed: a NO_STREAMABLE instead of NO_STREAM in tparamte.cc. Reported by +Egon Eckert . +* Merged changes from Anatoli Soltan. Now the BC++ code runs under Windows +95 too! +* Fixed: Some warnings emitted by gcc 2.95.2 with the examples/demo code. +* Added: getcwd to the compatlayer library. + +Revision 1.150 2000/05/16 02:08:05 set +* Added: A new constructor for TListBox and TSortedListBox that accepts two +scroll bars. I don't know why original TV lacks it when TListViewer have it +(base class). +* Modified: The behavior of the TListViewer class, now when you press the +left or right key and the viewer have and horizontal scroll bar and there is +just one column the handleEvent calls to the scroll bar handleEvent instead +of just return. I think that's very sensitive. +. +Revision 1.149 2000/05/13 16:02:39 set +* Fixed: Yet another call to delete without []. Pointed out by Laurynas. +. +Revision 1.148 2000/05/12 23:13:05 root (set) +* Fixed: Some details in the compat layer library to compile under Linux +(first compilation issues ;-) + +Revision 1.147 2000/05/12 02:28:35 set +* Incorporated the WinNT port (using BC++ 5.5) from Anatoli Soltan +. +* Separated most OS sensitive stuff to a sub-library called "Compat Layer". +This will break some code, specially RHIDE, so I'm changing the middle +version. This new library allows clean support of DOS/djgpp, Linux/gcc, +Win32/MingW32 and WinNT/BC++ without too much conditionals. +. +Revision 1.146 2000/04/29 17:09:42 set +* Added: Mixer stuff. +. +Revision 1.145 2000/04/20 19:56:54 root (set) +* Fixed: Some details in linux/tscreen.cc to try to compile it under other +UNIX flavors. I disabled all the x86 specific code for other flavors (is i386 +and OS specific) and also changed some stuff that seems to be defined only +by ncurses and not BSD's curses. + +Revision 1.144 2000/04/20 19:18:52 set +* Modified: Some #ifdef __linux__ by TVOS_UNIX to test it under other +flavors. +. +Revision 1.143 2000/04/13 01:07:02 set +* Fixed: [DOS] Now when BIOS is selected the keyboard is polled really using +BIOS. Previous code used djgpp's kbhit() and it doesn't really call BIOS. +* Modified: Now the canScroll member of TInputLine is just protected and not +private. +. +Revision 1.142 2000/04/13 00:41:17 root (set) +* Updated: The Linux .gpr for the new headers structure (tv/...). +* Fixed: Tab key problems when using the Eterm trick. +* Fixed: Some warnings reported by gcc 2.7.2.3. + +Revision 1.141 2000/04/12 23:36:37 set +* Added: A "non-inline" version of the functions defined in the djgpp's +vgaregs.h file. They are needed to compile the DOS version without +optimization. The problem was reported by Laurynas. +. +Revision 1.140 2000/04/12 23:13:48 set +* Added: An example of autoconf/automake macro for the library. Contributed +by Laurynas. +. +Revision 1.139 2000/02/27 18:30:20 set +* Added: A callback to the TButton class. Now you don't need to create a new +class just because a dialog have a non-standard button. +. +Revision 1.138 2000/02/27 15:06:18 set +* Added: 32 bits versions of TRadioButtons and TCheckBoxes. They have the +same name but just appends "32". These objects only override dataSize() to +return 4. They are much better because: (1) You can have 32 items (not just +16) and (2) structures doesn't need to be packed for 32 bits machines. +. +Revision 1.137 2000/02/05 22:22:20 set +* Added: Now if a program executes a dialog while the desktop is locked it is +temporally unlocked so the user can see the dialog and then is locked again. +. +Revision 1.136 2000/02/05 20:42:18 set +* Added: Add and Done buttons to the FileOpenDialog, they are controlled by +the fdDoneButton and fdAddButton options. They are suitable for selecting +files used in a list (list of MP3s and project in my editor). Seuggested for +RHIDE by Waldemar Schultz . +. +Revision 1.135 2000/02/05 00:14:55 root (set) +* Modified: [UNIX] gkeyli.cc now should compile in most UNIX systems that +have ncurses. All the funcy Linux stuff is conditional. +* Modified: [UNIX] the KEY_MOUSE ncurses value seems to be new in 1.9.9 so to +support older versions (as 1.8.6) now their use is conditional. +* Fixed: The dependencies in the Linux Makefile to accomodate the new +location of the headers. +* Added: -I/usr/local/include and -L/usr/local/lib to FreeBSD compilation +flags. Most of these changes are towards FreeBSD support with the help of +some tests by Alex Matulich . + +Revision 1.134 2000/02/04 02:18:44 root (set) +* Fixed: Tab is an exception to the modifications done in 1.129. + +Revision 1.133 2000/02/04 02:03:58 root (set) +* Modified: The configure process now only configures the target OS. +* Modified: TStatusItem now uses copies of the strings passed. + +Revision 1.132 2000/02/03 00:17:48 set +* Added: Win32 target to the configure process. I must admit the user needs a +very UNIXified system to run it joining Mingw32 with some goodies from Cygwin +and Perl from djgpp but works as well as the DOS and Linux process. +* Added: [Win32] A readme and a reference to it in the main readme. +* Modified: [Win32] The Makefile to generate the demo.exe from it and be +configured in a more common way. Also to name the library in the same way +used under DOS and Linux. I think that's the Right Thing(TM) because in this +ways programs can be ported from one platform to another without changes. +. +Revision 1.131 2000/02/01 01:51:36 set +* Changed: Now tv.h is located in $prefix/include/rhtvision and the rest in +$prefix/include/rhtvision/tv. It will avoid collisions with headers from +other libraries. Suggested by Andris. +. +Revision 1.130 2000/02/01 00:15:01 set +* Added: [Win32] A directory for the demo obj files. +* Added: [Win32] Workaround for a "feature" in Mingw32 980701-4 localtime +function. It returns a NULL pointer if the date is somewhat big. +* Added: [Win32] Get/SetWindowTitle() members to TDisplay. +* Added: Now the demo sets the window title (only supported for DOS target +running under W95+ and Win32 currently). +* Fixed: [Win32] Some warning in compilation. +. +Revision 1.129 2000/02/01 00:03:12 root (set) +* Fixed: [Linux] An old annoying "feature" that made the code report control +(arrows, etc.) keys as ASCII valid values. I got it reported many times but +finally Andris triggered the fix. + +Revision 1.128 2000/01/29 15:27:42 set +* NEW: Merged patches from Vadim Beloborodov to +support Win32 console. +. +Revision 1.127 2000/01/26 00:27:35 set +* Added: A new couple of TScreen members to Set/Get the window title under +Windows 9x. I hope to extend it to xterm. +. +----------------------------------------------------------------------------- +v1.0.10 release. + +Revision 1.126 2000/01/02 16:38:59 set +* Adjustments to realease v1.0.10. +. +Revision 1.125 1999/12/22 00:40:08 root (set) +* Bug found: [Linux] When suspending a TV application in a remote terminal +and using a font different than the default the frames gets scrambled when +resuming the application. I can reproduce it, but I don't have a clue about +the source of the problem. Remote terminals are complex and full of problems +so I don't plan to spend time searching the source of the problem. Reported +by Matt Mueller + +Revision 1.124 1999/12/19 19:50:08 root (set) +* Added: Now the library also patches the Ctrl+Shift+Tab combination so the +kernel reports it. Ivan reported it as a bug. + +Revision 1.123 1999/12/05 13:28:08 root (set) +* Applied patchs from Ivan for the Debian files (sets architecture to any). + +Revision 1.122 1999/12/05 13:12:59 root (set) +* Modified: Now the initialization of the TScreen is called from TProgInit. +I must test it under DOS. The old methode failed for the examples. +* Added: [Linux] An example on how to suspend an application with ^Z and then +resume it. +. +Revision 1.121 1999/12/02 23:47:57 set +* Fixed: A bug in the DeskLogo examples. Pointed as a problem by Arvin +Baccay . +. +Revision 1.120 1999/11/20 14:52:55 set +* Fixed: Problem with rhgdb messing terminal settings. Patch from Andris to +enable the old code that saves/restores the terminfo stuff. +. +Revision 1.119 1999/11/04 01:12:09 set +* Updated Debian files from Ivan. +. +Revision 1.118 1999/11/04 01:01:52 set +* Modified: The code used to disable ^Q/^S is now more generic and also +disables ^C, ^/ and ^Z. +. +Revision 1.117 1999/10/30 19:23:43 root (set) +* Changed: Now TScreen is initialized from the TApplication constructor and +not from a static variable that triggers the constructor. Suggested by +Christoph Bauer . + +Revision 1.116 1999/10/29 01:50:22 root (set) +* Added: [Linux] call to dch to update the Debian version. Suggested by Ivan. + +Revision 1.115 1999/10/26 00:07:30 set +* Added: TFileDialog is now "growable". +* Added: [Linux] TScreen disables the Xon/Xoff flow control so ^Q/^S can be +used in X terminals. +. +----------------------------------------------------------------------------- +v1.0.9 release. + +Revision 1.114 1999/10/17 22:30:03 set +* Updated for release of 1.0.9. + +Revision 1.113 1999/10/10 14:57:57 set +* Added: Support for DOS greek keyboards. +* Modified: Now all the classes that uses acelerators doesn't directly check +the ASCII of the acelerator with the keyboard ASCII. That's because the same +key could generate more than one ASCII. That's the case of greek keyboards +where the keyboard generates the latin and greeks values. +. +Revision 1.112 1999/10/02 15:18:07 set +* Added: some files missing in the distribution, not indispensable ones. +* Added: [DOS] Now the configure script patches libint.h in case the user +have a buggy one (found in gettext 0.10.32). +. +Revision 1.111 1999/09/28 02:25:00 set +* Fixed: Applied patch for Debian files from Ivan. +. +Revision 1.110 1999/09/24 02:57:52 set +* Fixed: I forgot to uncomment a test in the TListView class. It produced the +wrong broadcast when the focus changed. + +Revision 1.109 1999/09/24 02:08:05 set +* Fixed: Compilation problems in vgastate.h when using gcc 2.95. First +reported by Laurynas and then by "Sriviroolchai, Tanes" + who included some notes from gcc's FAQ +commenting about the problem. +. +Revision 1.108 1999/09/24 00:55:36 set +* Fixed: A bug introduced by us to the TFileList class in the vertical scroll +bar (wrong page step). I added a new member to TListViewer to fix it, is +called setNumCols(int aNumCols) and it also updates scroll bars (not just the +number of columns). Reported by Sean . +. +Revision 1.107 1999/09/24 00:28:24 set +* Added: Better handling of some situations in TScreen, patch from Robert: +"I made now a patch for tscreen.cc to use at firts the infromation +from terminfo to decide if we can use PAL_LOW ot PAL_HIGH +and as next I used in mapcolor as the first choice the +set_a_foreground and set_a_background strings and only if +they are not defined using set_foreground and set_background. +The reason for this is, that I analized some terminfo records and +found, that often the set_a_... are defined but not the set_..." +. +Revision 1.106 1999/09/23 23:55:42 root (set) +* Fixed: Relative symlinks for dynamic libraries [Linux]. Patch by Ivan. +* Fixed: Pemission 644 and not 755 for libraries [Linux]. Patch by Ivan. +* Added: Now the Linux compress updates the debian/control file. +* Modified: The Debian scripts (by Ivan). + +Revision 1.105 1999/09/17 03:38:30 root (set) +* Added: Support for the FHS in the configure script (not used for the +library). +* Fixed: Some details of the configure process for Linux. + +Revision 1.104 1999/09/16 02:26:54 set +* Modified: Now the file open dialog have space for 2 more filenames. +. +Revision 1.103 1999/09/12 19:47:54 set +* Moved a lot of code from the config.pl script to conflib.pl to share it +with the editor. +* Fixed: some small details in the configuration mechanism. Tested under DOS +and works OK. +. +Revision 1.102 1999/09/12 00:38:24 set +* Removed the compilation options from the .gpr files because that's +configured by the configure mechanism now. +* Added an option to makemak.pl to avoid displaying the installation options. +That's to avoid confusion when the script is called from the makefile. + +Revision 1.101 1999/09/09 02:25:16 root (set) +* Added: More details to the configure mechanism, including CFLAGS setting, +a script to set my default values, corrections in the readme.txt, etc. + +Revision 1.100 1999/09/08 02:09:39 root (set) +* Added: A config header (configtv.h), configuration for the makefiles and +RHIDE projects, unified the intl.h headers and made conditional using a +configuration variable and other configuration enhancements. +. +Revision 1.99 1999/09/07 01:12:26 set +* Added: First attempt for a UNIXified configure/make/make install mechanism. +Not using autoconf yet, just some Perl scripts. +. +Revision 1.98 1999/09/02 23:26:05 set +* Fixed: I forgot some files, so I'm releasing a fixed .zip. +. +----------------------------------------------------------------------------- +v1.0.8 pre-release. + +Revision 1.97 1999/08/29 20:20:13 set +* Changes for release. + +Revision 1.96 1999/08/26 00:32:19 set +* Applied 7 more patches from Laurynas Biveinis : +* Fixed: validation bypassed when switching windows +* Fixed: missing stream class members in TSortedListBox +* Fixed: memory leak in opstream::seekp +* Fixed: potential crash in TListViewer::setRange +* Fixed: Alt-number bypass view validation +* Fixed: THistory::handleEvent doesn't always put '\0' +* Fixed: TInputLine::options not read correctly +* Also: Now is possible to pass backslashes to TDirListBox. Patch suggested +by Laurynas too. + +Revision 1.95 1999/08/25 00:11:17 set +* Fixed: One of the new broadcasts was overlying a TButton command. Now I +moved the TButton command to the views.h file so it won't happend again. I +don't know why the original programmers left a lot of things in the .cc files +instead of putting them in the headers. +. +Revision 1.94 1999/08/22 23:26:54 set +* Fixed: the doit UNIX script to apply the patches. +* Modified: the number of one broadcast to be equal to the original. +. +Revision 1.93 1999/08/16 14:51:50 set +* Added: As the VGA Save State BIOS call is amazingly buggy in a lot of video +boards (Matrox in particular) I added a version of this service but made with +low level in/out commands. Is relative complex to enable right now but will +be easier in the future if I find it really solves the problems. Anders Blom + helped a lot testing it in your Matrox board +and now also Nate Eldredge is testing some of the +routines. +. +Revision 1.92 1999/08/14 02:13:32 set +* Applied 8 more patches from Laurynas Biveinis : +* Fixed: unnecesarry stack usage in drivers2.cc +* Fixed: TNSCollection::error should be not static +* Fixed: TPReadObjects::registerObject w/ and w/o assertion check. +* Fixed: incorrect scroll arrow display in TInputLine +* Fixed: EOF not always detected in ipstream +* Fixed: memory usage bug in HistRect ctor +* Fixed: TButton w/o bfDefault can became such. +* Fixed: TDirListBox is unusable outside TChDirDialog +* Added: I also added an oprator [] for collections. It isn't inline and can +be used as an alternative of at() when the speed isn't so important but the +size is the point. +. +Revision 1.91 1999/08/14 00:50:57 set +* Applied 6 more patches from Laurynas Biveinis : +* Fixed: unnecesary TInputLine scrolling. +* Fixed: if TListViewer has no scrollbar, it's never redrawed. +* Fixed: TMenuView bug - ability to execute disabled items. +* Fixed: TMenuView::updateMenu crash. +* Fixed: TStringList does not properly read strings. +* Fixed: TWindow frame lost if valid(cmClose) == False +. +Revision 1.90 1999/08/11 01:43:49 set +* Applied 7 patches from Laurynas Biveinis , he adapted +a lot of patches floating around the net for the original TV to this port: +* Fixed: TGroup re-entrancy fix +* Fixed: memory leak in TNSCollection +* Fixed: disabled views can be selected through labels +* Fixed: TCheckBoxes & TRadioButtons problem with streams +* Fixed: TChDirDialog::shutDown() +* Fixed: TEditor sometimes fails to find words +* Fixed: bug in TFileDialog::valid() + +Revision 1.89 1999/08/07 21:30:11 set +* Added: Now TListViewer is verbose and sends a broadcast when a new item is +focused. It can be used to update other views according to it. +* Updated Robert Hoehne's license text. +. +Revision 1.88 1999/08/03 02:04:57 set +* Added: Now TClusters (TRadioButton and TCheckBox) sends broadcasts to your +owner each time the movedTo and press member are called. This behavior is the +default but can be disabled setting the TCluster::extraOptions static +variable to 0. The new broadcasts sends a pointer to the view that is sending +the message, the owner must know what exactly is this pointer. +. +Revision 1.87 1999/08/02 00:44:24 set +* Modified: Now TFileCollection sorting is configurable. By default it sorts +like the Turbo Vision help says (directories at the end of the list, no case +sensitive, .. is the last in the list). I did it because many people seems to +like it, I like another layout and Robert yet another. So now everybody can +get what s/he wants ;-) +. +Revision 1.86 1999/08/01 18:01:46 set +* Added: Now TWindow::close() sends a broadcast cmClosingWindow to +TProgram::Application. +. +Revision 1.85 1999/08/01 13:34:13 set +* Added: Now is possible to setup TDeskTop so windows are tiled first +vertically. For it I added get/setOptions members to TDeskTop, it get/sets +a flags variable. The dsktTileVertical is the only flag available now. +. +Revision 1.84 1999/07/31 19:52:31 set +* Fixed: In the TDemo example: I forgot to add the link request for the +streaming structures of the calculator that now are in the library. Reported +by Laurynas. +. +Revision 1.83 1999/07/31 19:47:52 set +* Fixed: A couple of warnings about delete (void *) reported by gcc 2.95 in +the examples. +* Fixed: A call to delete without [] in dirent.h. Patch by Laurynas. +. +Revision 1.82 1999/07/27 22:06:03 root (set) +* Fixed: Some calls to delete instead of delete[] and delete instead of free. +Patches and suggestions by Laurynas Biveinis . +* Added: Now TProgram::idle() releases the CPU by default. You can avoid it +with TProgram::doNotReleaseCPU=1;. Suggested by Laurynas. + +Revision 1.81 1999/07/26 23:48:33 set +* Added: TListBoxRec is now publically available from the headers. +* Modified: TSortedListBox::searchPos is now protected instead of private so +childs can know something about the incremental selection. +. +Revision 1.80 1999/07/21 01:15:14 set +* Added: A script to create snap-shots as diffs. +. +Revision 1.79 1999/07/17 22:03:37 root (set) +* Fixed: When exiting and the screen is already suspended I avoid cleaning +it because it is supposed to be already cleaned. Not sure is the best, I +tested it in ttyN and ttypN and works ok for the command line options. + +----------------------------------------------------------------------------- +v1.0.7 release. + +Revision 1.78 1999/07/13 23:10:05 set +* Fixed: 18 const name... in the examples. Reported by Matt Mueller +. +* Added: example on how to release the CPU in the idle() member to the demo +example [Linux patch by Matt, I did the djgpp part]. +. +Revision 1.77 1999/07/12 23:36:58 root (set) +* Added: An Eterm theme example and instructions to install it. + +Revision 1.76 1999/07/07 23:02:04 set +* Added: a new couple of members to TCommandSet, they are used to enable or +disable a range of commands. I usedit in the editor to disable all the editor +commands when the editor loses the focus. I think that's usefull for any +class that have a big number of commands. The editor currently have over than +128 commands. +. +Revision 1.75 1999/07/03 16:55:54 set +* Fixed: Another call to delete instead of delete[] in the TInputLine +destructor. Patch by Laurynas Biveinis . +. +Revision 1.74 1999/07/01 02:42:49 root (set) +* Added: Support for the --report-as-keysyms options of Eterm 0.8.10. It +makes the programs work very well under Eterm, example: in my editor now is +posible to select text with shift and use strange keyboard combinations as +Ctrl+Shift+Insert. With it the support for Eterm is just excellent, slow but +very complet. (Note: I added this swithc to Eterm ;-) THANKs goes to mej +that accepted the patch and commited it in the CVS tree). + +Revision 1.73 1999/06/30 23:29:42 set +* Fixed: windowSizeChanged is from TDisplay, but was declared as TScreen +member, gcc 2.96 warns about it as an ANSI C++ violation. +. +Revision 1.72 1999/06/27 20:40:47 root (set) +* Added: More information in Linux TScreen module for cases where the +library fails to open the terminal for output. It seems to happend in some +new Linux installations. + +Revision 1.71 1999/06/27 20:19:47 set +* Fixed: TFileInfoPane was using an unitialized buffer when the open dialogs +didn't have any match. + +Revision 1.70 1999/06/25 01:29:06 root (set) +* Ported: The TChdirDialog class to Linux. It was there but was a dummy. Now +I can navigate the disk with it. +. +Revision 1.69 1999/06/24 22:33:53 set +* Modified: Now the File Dialog uses an horizontal scroll bar and 2 columns +when only SFNs are available and a vertical scroll bar and 1 column when LFNs +are available. Ivan complained about the horizontal bar ;-) +. +Revision 1.68 1999/06/24 01:55:10 set +* Added: The Calculator from the TVDemo to the library. I did a lot of +changes to the class (it was buggy and had portability problems). Now you +can have the calculator in any program use Uses_TCalculator, see the demo +for an example. +. +Revision 1.67 1999/06/23 23:05:34 set +* Added: Select button to the TFileDialog class (option: fdSelectButton +command: cmFileSelect). +* Modified/Fixed: Now the TFileList generates the cmFileDoubleClicked +broadcast as specified in the TVision help (was a bug in 1.03 fixed in 2.0). +. +Revision 1.66 1999/06/23 02:31:30 set +* Changed: The distance between the buttons in the File Dialog, it was 3 and +now is 2 to allow more buttons (my editor adds 2 buttons). +. +Revision 1.65 1999/06/23 01:15:56 set +* Modified: Now the file dialog doesn't show ".." in the root directory (DOS). +* Fixed: Calling the file dialog with fdNoLoadDir (needed to avoid an extra +directory read, sometimes quite slow) was using a null pointer, also fixed +a memory leak (not releasing the current directory in readDirectory) and +changed delete (char *)directory to delete[] directory; +. +Revision 1.64 1999/06/16 01:44:04 root +* Added: Now the Linux keyboard routines disables ^Z because it is dangerous. +Sugested by Luis Pistoia . +. +Revision 1.63 1999/06/12 00:16:15 set +* Fixed: Some calls to delete for memory allocated with new[]. Patchs from +Laurinas, some of them overlaps with patches from Andris. +. +Revision 1.62 1999/06/11 23:55:14 set +* Fixed: Some calls to delete operator passing a void *. Now falling back to +char *. Also the new operator in HistRec class was returning 0 and the new +drafts says it should rise an exception instead. These things are reported +by egcs 2.95.x snapshots with two new warnings: +warning: `void *' is not a pointer-to-object type +operator new should throw an exception, not return NULL +The basic patches (I changed them before applying) were sent bt Andris +Pavenis (he ever uses a cutting edge version of the compiler). +. +Revision 1.61 1999/06/11 00:21:52 set +* Included some files I forgot in the list (keyboard extender and pif +example). +. +----------------------------------------------------------------------------- +v1.0.6 release. + +Revision 1.59 1999/06/05 22:38:19 root (set) +* Applied patches for Debian package v1.0.5-2. (from Ivan). + +Revision 1.58 1999/06/05 02:18:59 set +* Modified: The destroy0 macro to be possible your use in cases like: +if (...) destroy0(...); Suggested by Laurynas Biveinis . +Patch from Laurynas rejected because is not practical (generates temporals). +. +Revision 1.57 1999/06/05 01:35:19 set +* Fixed: Calls to delete without using []. According to new standards: +Here is text from a relative old draft of the standard: +0 Accredited Standards Committee* Doc No:X3J16/96-0225 + X3, INFORMATION PROCESSING SYSTEMS WG21/N1043 +... + 5.3.4 New [expr.new] +... +21The way the object was allocated determines how it is freed: if it is + allocated by ::new, then it is freed by ::delete, and if it is an + array, it is freed by delete[] or ::delete[] as appropriate. +... + 5.3.5 Delete [expr.delete] +... +2 ... . In either alternative, if the value of the + operand of delete is the null pointer the operation has no effect. In + the first alternative (delete object), the value of the operand of + delete shall be a pointer to a non-array object created by a new- + expression, or a pointer to a sub-object (_intro.object_) representing + a base class of such an object (_class.derived_). If not, the behav- + ior is undefined. In the second alternative (delete array), the value + of the operand of delete shall be the pointer value which resulted + from a previous array new-expression.18) If not, the behavior is unde- + fined. [Note: this means that the syntax of the delete-expression + must match the type of the object allocated by new, not the syntax of + the new-expression. ] [Note: a pointer to a const type can be the + operand of a delete-expression; it is not necessary to cast away the + constness (_expr.const.cast_) of the pointer expression before it is + used as the operand of the delete-expression. ] + _________________________ + 18) For non-zero-length arrays, this is the same as a pointer to the + first element of the array created by that new-expression. Zero- + length arrays do not have a first element. +And the comp.lang.c++ FAQ says: +[16.12] Can I drop the [] when deleteing array of some built-in type +(char, int, etc)? +No! +Patches to add [] in some necesary places and FAQ quotation provided by +Laurynas Biveinis . +I also applied the part that says that is not necesary to cast a const +char * to char * when calling delete. +. +Revision 1.56 1999/06/05 00:40:35 set +* Fixed: Some key bindings in TEditor class (Enter and Backspace for example). +* Modified: Now the doEditDialog function provided in tvedit3.cc can be used +for quick applications because I defined a new version: +ushort doEditDialogDefault( int dialog, va_list arg ) +So you can set TEditor to your own function, handle only some cases and call +doEditDialogDefault for the rest. I used it for the installer of the editor. +. +Revision 1.55 1999/05/29 00:52:23 root (set) +* Removed some Debian files no longer needed (Ivan). + +Revision 1.54 1999/05/28 01:02:39 set +* Added: Windows NT detection (using the OS environment variable) to the +mouse class so now if NT is detected the mouse is polled and not hooked. +Looks like NT's mouse driver emulation fails to call the RMCB and jumps to +nowhere crashing. Now the mouse is functional in NT. +* Added: A workaround for a bug in Windows NT 4.0 when setting the video +modes with int 0x10. Looks like this bug isn't reproductable in all the +machines but happends in the one I used. NT is clobbering the number of tics +since midnight in the BIOS data area, the number that appears is big enough +to generate a divide overflow in the next call to int 0x21 service 0x2C (get +time), as that's an exception in the real mode code the djgpp program is +killed or hangs. +. +Revision 1.53 1999/05/26 00:03:51 set +* Fixed: a leak in TResourceFile constructor. Patch submited by Laurynas +Biveinis . + +Revision 1.52 1999/05/23 22:58:08 root (set) +* Modified: Now, in Linux, left alt and right alt are different keys. I did +it because that's the only way to paste with gpm. +. +Revision 1.51 1999/05/21 14:10:02 root (set) +* Fixed: When I removed some code in TScreen I made stdout the output of the +library, but then redirecting the stdout from the program and printing sent +undesired escape sequences to the redirected file. For this reason I open the +tty with other file handle. *NHP* (Never Hit Public, it means only I used a +version with this bug). + +Revision 1.50 1999/05/20 22:57:25 root (set) +* Fixed: Now Uses_TStrListMaker defines Uses_TStringList. Patch by Laurynas +Biveinis . + +Revision 1.49 1999/05/20 02:00:02 root (set) +* Changed: Now TScreen shows an error message if you redirect stdout in the +Linux version, that's nicer than the old behavior: SIGSEGVs ;-) +* Modified: Now TScreen includes sys/io.h instead of sys/perm.h for glibc +because looks like sys/perm.h isn't included in Alpha/Linux's glibc. +Sugested by Dim Zegebart . + +Revision 1.48 1999/05/19 23:27:55 set +* Fixed: a bug in TStrListMaker destructor, ugh! looks like nobody used it +;-). Patch by Laurynas Biveinis . +. +Revision 1.47 1999/05/16 22:09:14 root (set) +* Added: My DOS TSR to enhance the keyboard to the distribution. +* Added: A .pif example showing how to prevent using the program in a window +and recover some keys like Alt+Space. +* Moved the Linux code from screen.cc to classes/linux/tscreen.cc. +* Added: The ability to use VCSAs even if they are write only. +* Removed the tcget/setattr calls from TScreen because that's done by ncurses. +* Added: A variable to fine tune the video driver called +TurboVision_screenOptions, by now only have meaning under Linux and is used +to tell the TScreen class to not use VCSAs if they are write only (because +then suspend/resume doesn't work properly). +* Modified: Now Alt+key doesn't have any ASCII value associated so if you +press Alt+8 the program won't display 8 if there is no action for Alt+8. +* Added: Documentation in the readmes about the limitations and +particularities of each platform. For example: what doesn't work when using +telnet, how can you paste using gpm, etc. + +Revision 1.46 1999/05/15 23:51:09 root (set) +* Good news for xterm funs: +* Fixed: A bug in the startcurses() that made xterm report the wrong codes +for arrow keys and other keys. +* Fixed: A bug and a lack of some stuff during the exit that left the +terminal in a wrong state after exit (including not restoring the screen) +* Added: Support for mouse, isn't as good as gpm because you can't track the +position in real time, but you can resize and move windows anyways. +* Fixed: A bug in the bold reset code, it made a funny effect: when starting +the desktop was with normal fonts, but with the use all were becoming bold. +* Fixed: xterm (and others) doesn't have 16 backgrounds and the color dialog +was trying to show 16. +* Fixed: Now the "User screen" works when the program is in a terminal. +* Added: A temporal workaround to support Eterm when the user have TERM=xterm +(the default in Debian, bug mess Home and End). You need ncurses 4.2 for that. +* Discovered: A thing that was floating in my mind: why mc interfers? simply: +mc runs the childs in ttypN consoles, so you are in a terminal when starting +the editor from mc. +* Modified: Now the ESC delay is 100ms and not 1s. +* Fixed: The DEC character mapping for the scroll bar that is full and the +block used for the color selector. They aren't pretty but at least you can +understand what they mean. +* Added: Handling for SIGWINCH, so now TV applications are resized if the +xterm window is resized. + +Revision 1.45 1999/05/13 03:05:03 root (set) +* Added: Support for xterm way of reporting ALT+key (key | 0x80). Now the +startcurses() routine sets the "XtermMode" when the TERM is xterm*. It makes +the editor work much better under xterm, at least in my system. + +Revision 1.44 1999/05/12 00:46:41 set +* Fixed: A bug in TSortedListBox when pressing delete it was dereferencing +curString[65536] when the variable is a 256 bytes buffer producing random +crashes. Reported by Christopher Nelson . +* Fixed: The logic in backspace used by TSortedListBox was wrong, now seems +to work as expected. I saw it while fixing the other. +. +Revision 1.43 1999/05/10 22:44:32 set +*** NEW *** Thanks to the effort by Dim Zegebart +(who had patient to test my patches in this platform and send me the errors +reported by gcc and trace backs from the crashes) we managed to get the first +TV programs running in Alpha/Linux. +* Changed: Now the TScreen::screenBuffer member is an (ushort *) instead of +a long. I did it because the code for screen used a lot of casts and have +some errors casting this value to (int) which works in i386 but generated a +SIGSEGV under Alpha ;-). +. +Revision 1.42 1999/05/08 01:49:00 set +* Changed: The initialization for TEventQueue::eventQueue. Looks like egcs +2.91.66 doesn't like partially initialized structures and what is worst likes +to crash if the non-initialized part is an anonymous union (like in TEvent). +In Linux egcs dies, in W95 survives and you get the warning. Ivan reported it +when he tried to make a .deb for Potato using egcs 1.1.2. +. +Revision 1.41 1999/05/06 03:36:24 set +* Added: Now TMenuBar and TStatusLine uses one character around the name of +the item in *both* sides and don't overlap with the next. That's the original +behavior of TV. As it will reduce the number of visible items in the menu +bar for RHIDE (specially in spanish ;-) I added code to automagically compact +the items when they don't have enough space. The compactXXXX member reflects +it and can be forced externally. The value is computed in the constructors +and in the changeBounds. The changes where based in a patch that "Norberto +Alfredo Bensa" sent me to unconditionally +have the original behavior (which is unacceptable for RHIDE). So I did it in +a way that won't mess RHIDE and is good for users at the same time. +. +Revision 1.40 1999/05/02 14:00:36 set +* Added: The desklogo example to the distribution. I already added it in the +CVS tree (see Revision 1.26) but forgot to add it to the list of distributed +files. Noted by "Norberto Alfredo Bensa" +. +Revision 1.39 1999/05/02 13:51:09 set +* Avoided the distribution of the Debian files in the DOS release because +these files aren't 8+3 clean and will confuse users. +. +Revision 1.38 1999/04/28 22:57:09 set +* Enclosed all the monochrome code that makes I/O access to the MDA registers +and maps the video memory under Linux with #ifdef __i386__ because looks like +it isn't good idea for Alpha machines ;-). +. +Revision 1.37 1999/04/27 22:34:24 set +* Ported the TParamText class from TV 2.0. The old version seems to be from +1.03 and wasn't portable, in fact it failed to even compile under Alpha +Linux. I added some check to avoid a buffer overflow, something that the +original library never did. I also adapted the getText member for our port +that uses an extra parameter (again to avoid buffer overflows). +. +----------------------------------------------------------------------------- +v1.0.5 released. Sources uploaded to DJ's server and my home page. Linux +sources uploaded to my home page. Sources sent to www.linux.org.ar (DanX). + +Revision 1.36 1999/04/21 22:46:34 set +* Fixed: The open dialog didn't allow to open files using [];,=+ That's OK +for plain DOS, but when running in Win9x+GUI the LFN API supports it. + +Revision 1.35 1999/04/18 22:19:18 root +* Applied changes to the Debian files from Ivan. +. +Revision 1.34 1999/04/13 00:58:11 set +* Modified: The default VESA routines to avoid using DOS allocated memory for +the video mode information. I did it because at least one VESA 2.0 TSR for +S3 chipsets returns more memory than the specified by the spec and corrupts +memory. It could be one of the problems with S3 boards. +. +Revision 1.33 1999/04/10 23:44:10 set +* I was debugging my editor with YAMD to find malloc/free errors, out of +bounds read/writes and leaks. As a result I added propper memory deallocation +to various classes: +* Added: delete mouse to ~TEventQueue. +* Added: delete font to ~TDisplay. +* Modified: TPWriteObjects to destroy your items. +* Added: free to the screen stuff. +* Added: destroy0 to the object.h, that's a macro to call destroy and assign +0 to the freed pointer. +* Added: a member function to collections called setOwnerShip. Passing false +to it the items of the collection aren't removed by shutDown (usefull for +collections of static strings). +. +Revision 1.32 1999/04/04 01:42:36 set +* Fixed: Problems in intl.h with glibc>=2.1. Patch provided by Andris. +* Fixed: TChDirDialog used a fixed maxlength for the directory name instead +of using a limit from the headers. Patch provided by Andris. +* Fixed: TTerminal::prevLine was 100% broken. I rewrote it. Reported by +Andris. +* Fixed?: a label at the end of the post inst files for Debian. Ivan told me +what was needed, not sure if I did it ok. +. +Revision 1.31 1999/04/01 01:28:52 set +* Fixed: Now you can set a VESA video mode using void TDisplay::setCrtMode. +It wasn't possible before because it ever used service 0, now if the mode is +greater than 0x100 I use VBE. +. +Revision 1.30 1999/03/24 23:03:38 root +* Incorporated the 1.0.3-6 Debian package diffs. +* Fixed: Problem with dependencies of the .so library (by Ivan). +. +Revision 1.29 1999/03/23 01:01:38 set +* Added an explanation in the readme.txt about the debian directory that will +generate warnings when uncompressed in plain DOS. +* Modified the compress.pl scripts to only replace vX.X.X in the readme and +not just X.X.X. +. +Revision 1.28 1999/03/23 00:50:35 set +* Changed the name of the library because Sigala's port is older in the Linux +arena and I think the right thing is to differentiate this port calling it +librhtv.a instead of libtv.a. For this reason I changed all the references to +the old name. +* Changed to version 1.0.5 in the scripts. +* Added the Debian stuff to the sources distribution. It will generate some +warnings when using 8+3 filenames in the uncompressor but these files aren't +needed for DOS. +. +Revision 1.27 1999/02/23 22:45:26 root +* Tested the Debian distribution stuff. Works after a couple of small patches +to the rules make script. +. +Revision 1.26 1999/02/23 00:06:25 set +* Added an example of how to change the desktop appearance. Contributed by +Joel . +. +Revision 1.25 1999/02/22 23:04:30 set +* Included the debian directory for the debianization but yet not included in +the distribution package. Debian package by Ivan Baldo +. +Revision 1.24 1999/02/18 02:41:34 set +* Compiled with djgpp v2.02 and gcc 2.8.1. +. +----------------------------------------------------------------------------- +v1.0.4 released. Sources and binaries uploaded to DJ's server and my home +page. Linux sources and binaries uploaded to my home page (including a +dynamic version). + +Revision 1.23 1999/02/16 00:33:56 set +* Added more information in readme.txt and fixed some typos. +* Changed the version to 1.0.4 because I'll release it soon. + +Revision 1.22 1999/02/10 22:10:29 set +* Fixed a bug in the new terminals code for frames (I forgot to initialize +the array when we use the PC characters). +. +Revision 1.21 1999/02/07 13:56:54 set +* Added a "Try" button to the TColorDialog. It makes a redraw of the screen +and generates a cmUpdateColorsChanged broadcast. The broadcast should be used +by special classes that needs to know that the colors changed, the only one +I know about is my own editor that have a color's cache. This idea was based +on a crazy report by "a.meyer" ;-). +* Added a Uses_TColorCommands request for the cmUpdateColorsChanged located +in colorsel.h. +. +Revision 1.20 1999/02/02 23:03:19 root (set) +* Adapted the TEditor family to Linux (file I/O stuff and \r\n differences). + +Revision 1.19 1999/02/02 01:55:54 set +* Added the TEditor, TFileEditor, TEditorWindow and TMemo classes. I taked +the code from the old RHIDE BETA 4 and adapted it for the new keyboard and +did other small changes. +* Added TEditorApp to the library and a small example to test it. + +Revision 1.18 1999/02/02 00:56:55 set +* Minor changes in the readme.txt and porting.txt to give some hints. +. +Revision 1.17 1999/01/31 20:12:44 set +* Added support for S3 (buggy) BIOSes in vesa.cc. It helps to support VESA +text modes when using S3 boards. Reported and tested by Jerzy Witkowski +. + +Revision 1.16 1999/01/31 19:20:14 root (set) +* Adjusted the examples for Linux (some used dos.h). +* Cleaned the /usr/... dependencies in the example gprs. +* Trying to start a shared repository between DOS and Linux. +. +Revision 1.10 1999/01/22 01:21:19 root (set) +Passed the changes from DOS to Linux. + +Revision 1.14 1999/01/22 01:05:37 set +* Fixed the UNIX terminals code to use the ACS_xxxx macros for the frames +instead of falling back to just ASCII. It makes the program look *much* +better when using xterm, gnome-terminal, eterm, etc. + +Revision 1.13 1999/01/22 00:34:11 set +* Added clarification in the readme.txt about: license, RHIDE version needed +no-rtti stuff. +* Made the n() macro in tvutil.h visible only when Uses_n is defined. +(Problems reported by Jerzy Witkowski ). +* Fixed the examples to avoid warnings about NULL redefined. +. +Revision 1.12 1999/01/19 22:54:22 set +* Fixed the gkey.gpr to be usable by anyone ;-). I added an rhide.env file to +give just another example on how to use it with TVision. +. +Revision 1.11 1999/01/19 22:33:36 set +* Released the 1.0.3 version and uploaded to DJ's server. +. +Revision 1.9 1999/01/18 22:55:18 root (set) +* Copied the changes from DOS. +* Added the versions of libraries I use for Linux in the change.log. + +Revision 1.10 1999/01/18 22:41:54 set +* Fixed the djgpp makefile switchs. +* Added code to the compress perl script to regenerate the makefile if the +it's older than the project. + +Revision 1.9 1999/01/13 23:26:57 set +* Added "delete.me" files to ensure the empty directories are packaged. +* Silly boy, silly boy, I don't how but some silly options were included in +the DOS libtv.gpr (-funsigned-char and a -W that makes problems with gcc +2.7.x). +* Moved the #include of the standard headers to include these headers before +the C++ headers. If I don't do it default djgpp installations barf about +redefined NULL (no Linux libc5 nor glibc). +* Added instructions to workaround a bug in the gettext distribution for +djgpp. +. +Revision 1.8 1999/01/13 00:55:43 set +Passed the changes to DOS. +. +Revision 1.7 1999/01/13 00:35:35 root (set) +Added a linuxso directory to create the dynamically linked version of the +library. + +Revision 1.7 1999/01/10 16:25:41 set +Fixed the demohelp.h32 name (to be lowercase). + +Revision 1.6 1999/01/10 16:04:05 root (set) +Added demo to the Linux distribution. +. +Revision 1.6 1999/01/10 00:47:21 set +Added the Borland's TVision demo. I taked it from the Sigala's port. + +Revision 1.5 1999/01/09 20:13:10 set +Incorporated nine examples that implements various widgets. They are very +small applications so the user can see how a simple TVision application can +be setup. +. +Revision 1.4 1999/01/09 17:29:09 set +Changed compress.bat for a Perl script that generates the manifest and +version djgpp files and compress the files in the djgpp fashion. Asked by DJ. +. +Revision 1.3 1999/01/09 17:24:58 set +Modifications from Linux version. +. +Revision 1.4 1999/01/09 16:14:41 root (set) +Changed linux/compress by a Perl script that updates readme.txt (version), +generates the tarred files with the right version name and creates the .lsm. +(linux/compress) + +Revision 1.3 1999/01/09 14:40:24 root (set) +Changed the Linux compress script to be much more efficient. Added a couple +of files to indicate files to include/exclude in the Linux distribution. +Changed the name of the Linux distribution to 'rhtvision' to avoid collisions +with the already existing tvision package by Sergio Sigala. + +gkey.cc +Modified to support a command line switch that enables the new keyboard +mapping the old is the default because is the most common (Debian 2.0 and +Red Hat 5.1). + +gkeyli.cc +Added TGKey::SetKbdMapping to support the new keyboard mapping found in the +kbd package shipped with Red Hat 5.2. Using +TGKey::SetKbdMapping(KBD_REDHAT52_STYLE) the new mapping is enabled. It +supports F1-F12, Shift+F1-F12 and Ctrl+F1-F12. Not only a special keyboad map +is needed but a special linux terminfo description is needed too. +If the program runs in console that's not needed but you'll get only F1-F10. + +Revision 1.2 1998/12/30 01:01:12 set +Removed the redundant translation of the Linux IOCTL shift flags to BIOS +format. +Moved 90% of the conditional code to the Linux module. +Fixed the Linux code to report left and right alt. +Added entries to patch the right alt + function key, not only left alt. +Added Shit+PgUp, Shift+PgDn, Ctrl+Backspace and Ctrl+Space to the list of +patched keys. + +Release 1.0.1 + +* Some changes in the readmes and gpr files. +* Patches from Robert. + +date: 1998/12/14 23:36:35; author: set; +Converted all the calls to ctype functions to macros. These macros avoids +passing negative values. +Added right dependencies in gpr and makefiles. + +Revision 1.1 1998/12/22 23:57:46 set +Renamed readme.src to readme.txt. +Added a small change.log, not yet definitive. + +Release 1.0.0 + +* Arranged the first release + +date: 1998/12/14 22:03:08; author: set; +Imported the pre-release 1.0.0. These are the files I sent to Robert for +revision. + diff --git a/tvision/classes/alcon/alcon.cc b/tvision/classes/alcon/alcon.cc new file mode 100644 index 0000000..df3754b --- /dev/null +++ b/tvision/classes/alcon/alcon.cc @@ -0,0 +1,1632 @@ +/* + Copyright (c) 2001-2009 by Salvador E. Tropea (SET) + Copyright (c) 2003-2004 by Grzegorz Adam Hankiewicz + + This code is covered by the GPL license. A copy of the license should + be provided in the same package. + + Modified by Grzegorz Adam Hankiewicz + to be used as a Turbo Vision driver. + + conio.h emulation library on top of Allegro +*/ + +#include + +#define Uses_stdio +#define Uses_string +#define Uses_TScreen +#define Uses_TEvent +#define Uses_TGKey +#include +#include +#include + +#ifdef HAVE_ALLEGRO + +#include + +// Forward declarations. +static void AlCon_LoadCustomFont(const char *filename, uchar *fdata, unsigned fw, unsigned fh); +static void AlCon_AllocateMemoryBuffer(void); + +// Globals internal to AlCon. +static FONT *Alcon_CurrentFont=NULL; + +static FONT Alcon_PrimaryFont; +static FONT_GLYPH *Alcon_ASCIIDataP[256]; +static FONT_MONO_DATA Alcon_ASCIIMonoFontP = +{ + 0x0, 0x100, /* begin, end characters */ + Alcon_ASCIIDataP, /* the data set */ + 0 /* next */ +}; + +static FONT Alcon_SecondaryFont; +static FONT_GLYPH *Alcon_ASCIIDataS[256]; +static FONT_MONO_DATA Alcon_ASCIIMonoFontS = +{ + 0x0, 0x100, /* begin, end characters */ + Alcon_ASCIIDataS, /* the data set */ + 0 /* next */ +}; + +static FONT Alcon_CursorFont; +static FONT_GLYPH *Alcon_CursorData[2]; +static FONT_MONO_DATA Alcon_CursorMonoFont = +{ + 0x0, 0x2, /* begin, end characters */ + Alcon_CursorData, /* the data set */ + 0 /* next */ +}; + +static +AlCon_Color BIOSPalette[16]={ +{ 0x00, 0x00, 0x00, 0 }, +{ 0x00, 0x00, 0xA8, 0 }, +{ 0x00, 0xA8, 0x00, 0 }, +{ 0x00, 0xA8, 0xA8, 0 }, +{ 0xA8, 0x00, 0x00, 0 }, +{ 0xA8, 0x00, 0xA8, 0 }, +{ 0xA8, 0x54, 0x00, 0 }, +{ 0xA8, 0xA8, 0xA8, 0 }, +{ 0x54, 0x54, 0x54, 0 }, +{ 0x54, 0x54, 0xFC, 0 }, +{ 0x54, 0xFC, 0x54, 0 }, +{ 0x54, 0xFC, 0xFC, 0 }, +{ 0xFC, 0x54, 0x54, 0 }, +{ 0xFC, 0x54, 0xFC, 0 }, +{ 0xFC, 0xFC, 0x54, 0 }, +{ 0xFC, 0xFC, 0xFC, 0 }}; +AlCon_Color AlCon_CurPalette[16]; + +static int cursorX, cursorY; +static int cursorPX, cursorPY; + +/* + The variables AlCon_ScreenWidth, AlCon_ScreenHeight, + AlCon_FontWidth and AlCon_FontHeight are read only. They are + modified ONLY when the font is changed. The first two tell the + number of text characters that fit into the physical screen. The + last two tell the number of screen pixels a text cell has in + Allegro. The font size is initialised by default to a 8x16 font so + the AlCon_Init function can set a reasonable default screen size. +*/ +static int AlCon_ScreenWidth, AlCon_ScreenHeight; +static int AlCon_FontWidth=8, AlCon_FontHeight=16; + +static int colors[16]; +static int fg,bg; +static char cursorEnabled=1, cursorInScreen=0; +static char AlCon_UseSecFont=0; +static unsigned char *chars, *attrs; +static unsigned char curAttr; +static char AlCon_CursorShapeFrom, AlCon_CursorShapeTo; +//static int al_text_mode; +static int al_mouse_buttons = 0; +static int al_mouse_wheel; + +/* Extra flags reserved for silly cursor effects */ +int AlCon_CursorBits = 0; +char AlCon_ForcedKeyboard[4] = ""; + +void AlCon_EnableSecFont() +{ + AlCon_UseSecFont=1; +} + +void AlCon_DisableSecFont() +{ + AlCon_UseSecFont=0; +} + +/***************************************************************************** + + Functions to hide/unhide the mouse and text cursors. + I use the scare_mouse() stuff and also implemented the same concept for the +text cursor. + +*****************************************************************************/ + + +void AlCon_UnDrawCursor(int *aFgCol); + +#define maxCurMode 32 +char CursorMode[maxCurMode]; +int CursorModeIndex=0; + +static +void PushCursorMode() +{ + if (CursorModeIndex 0 && x <= AlCon_ScreenWidth); + ASSERT(y > 0 && y <= AlCon_ScreenHeight); + AlCon_ScareCursor(); + cursorX = x; cursorY = y; + cursorPX = (x - 1) * AlCon_FontWidth; + cursorPY = (y - 1) * AlCon_FontHeight; + AlCon_UnScareCursor(); +} + +int AlCon_WhereX() +{ + return cursorX; +} + +int AlCon_WhereY() +{ + return cursorY; +} + +int AlCon_ScreenCols() +{ + return AlCon_ScreenWidth; +} + +int AlCon_ScreenRows() +{ + return AlCon_ScreenHeight; +} + + +/***************************************************************************** + + Color selection routines + +*****************************************************************************/ + +void AlCon_SetColors(int aFg, int aBg) +{ + fg=aFg; bg=aBg; + curAttr=(bg<<4) | (fg & 0xF); +} + +void AlCon_TextAttr(int attr) +{ + unsigned char aBg=attr>>4; + unsigned char aFg=attr & 0xF; + curAttr=attr; + fg=aFg; bg=aBg; +} + +void AlCon_TextBackground(int aBg) +{ + AlCon_SetColors(fg,aBg); +} + +void AlCon_TextColor(int aFg) +{ + AlCon_SetColors(aFg,bg); +} + +/***************************************************************************** + + Clear routines + +*****************************************************************************/ + +void AlCon_Clear() +{ + AlCon_DisableAsync(); + clear_to_color(screen,bg); + AlCon_EnableAsync(); + memset(chars,' ', AlCon_ScreenWidth * AlCon_ScreenHeight); + memset(attrs,curAttr, AlCon_ScreenWidth * AlCon_ScreenHeight); +} + +void AlCon_ClrScr() +{ + AlCon_Clear(); + AlCon_CursorHome(); +} + +/***************************************************************************** + + Text output routines, including newline and tab management + +*****************************************************************************/ + +void AlCon_NewLine() +{ + if (cursorY == AlCon_ScreenHeight) + { // Scroll + int ybot,xmax; + unsigned offset; + AlCon_DisableAsync(); + ybot = (AlCon_ScreenHeight - 1) * AlCon_FontHeight; + xmax = AlCon_ScreenWidth * AlCon_FontWidth; + blit(screen, screen, 0, AlCon_FontHeight, 0, 0, xmax, ybot); + rectfill(screen,0,ybot,xmax, AlCon_ScreenHeight * AlCon_FontHeight, colors[bg]); + AlCon_EnableAsync(); + + // Same for buffers + memcpy(chars, chars + AlCon_ScreenWidth, AlCon_ScreenWidth * (AlCon_ScreenHeight - 1)); + memcpy(attrs, attrs + AlCon_ScreenWidth, AlCon_ScreenWidth * (AlCon_ScreenHeight - 1)); + offset = (AlCon_ScreenHeight - 1) * AlCon_ScreenWidth; + memset(chars+offset,' ', AlCon_ScreenWidth); + memset(attrs+offset,curAttr, AlCon_ScreenWidth); + + AlCon_GotoXY(1,cursorY); + } + else + AlCon_GotoXY(1,cursorY+1); +} + +inline +void AlCon_TextOut(const char *str, unsigned x, unsigned y, int fg, int bg) +{ + if (AlCon_UseSecFont && (fg & 8)) + textout_ex(screen,&Alcon_SecondaryFont,str,x,y,colors[fg],colors[bg]); + else + textout_ex(screen,Alcon_CurrentFont,str,x,y,colors[fg],colors[bg]); +} + +void AlCon_PutStr(const char *s) +{ + ASSERT(s); + ASSERT(Alcon_CurrentFont); + + int l=strlen(s); + AlCon_DisableAsync(); + while (cursorX + l > AlCon_ScreenWidth) + { + char b[AlCon_ScreenWidth + 1]; + int count = AlCon_ScreenWidth - cursorX + 1; + unsigned offset; + strncpy(b,s,count); + b[count]=0; + AlCon_TextOut(b,cursorPX,cursorPY,fg,bg); + + offset = (cursorX - 1) + (cursorY - 1) * AlCon_ScreenWidth; + memcpy(chars+offset,b,count); + memset(attrs+offset,curAttr,count); + + AlCon_NewLine(); + s+=count; + l-=count; + } + if (*s) + { + unsigned offset; + AlCon_TextOut(s,cursorPX,cursorPY,fg,bg); + + offset = (cursorX - 1) + (cursorY - 1) * AlCon_ScreenWidth; + memcpy(chars+offset,s,l); + memset(attrs+offset,curAttr,l); + + cursorX+=l; + cursorPX += l * AlCon_FontWidth; + } + AlCon_EnableAsync(); +} + +void AlCon_Puts(const char *s) +{ + AlCon_PutStr(s); + AlCon_NewLine(); +} + +void AlCon_Tab() +{ + int count=8-(cursorX & 7); + char b[9]; + memset(b,' ',count); + b[count]=0; + AlCon_PutStr(b); +} + +void AlCon_CPrintf(AL_CONST char *format, ...) +{ + char buf[4096]; + int ret; + char *s,*next,aux; + + va_list ap; + va_start(ap, format); + // TODO: vsnprintf + ret=vsprintf(buf, format, ap); + if (ret>4090) + { + set_gfx_mode(GFX_TEXT,0,0,0,0); + allegro_message("Buffer overflow in AlCon_CPrintf\n"); + exit(100); + } + va_end(ap); + + s=buf; + while ((next=strpbrk(s,"\n\t"))!=0 && *next) + { + aux=*next; *next=0; + AlCon_PutStr(s); + *next=aux; + if (aux=='\n') + AlCon_NewLine(); + else if (aux=='\t') + AlCon_Tab(); + s=next+1; + } + if (*s) + AlCon_PutStr(s); +} + +#if 0 +// Avoiding to redraw characters that didn't change: 2.5 times faster +void AlCon_PutBuf(unsigned offset, uint16 *values, int count) +{ + unsigned x,y; + x=(offset%AlCon_ScreenWidth)*AlCon_FontWidth; + y=(offset/AlCon_ScreenWidth)*AlCon_FontHeight; + + uchar *b=(uchar *)values,newChar,newAttr; + uchar *sc=(uchar *)(chars+offset); + AlCon_DisableAsync(); + unsigned char aux[2]; + aux[1]=0; + while (count--) + { + newChar=b[charPos]; + newAttr=b[attrPos]; + if (newChar!=chars[offset] || newAttr!=attrs[offset]) + { + aux[0]=chars[offset]=newChar; + attrs[offset]=newAttr; + int nBg,nFg; + nBg=b[attrPos]>>4; + nFg=b[attrPos] & 0xF; + AlCon_TextOut((char *)aux,x,y,nFg,nBg); + } + x+=AlCon_FontWidth; b+=2; offset++; + } + AlCon_EnableAsync(); +} +#else +// Avoiding to redraw characters that didn't change: 2.5 times faster +// Grouping chars of the same colour: 9 to 15% faster +void AlCon_PutBuf(unsigned offset, uint16 *values, int count) +{ + unsigned x,y,xf; + x=(offset%AlCon_ScreenWidth)*AlCon_FontWidth; + y=(offset/AlCon_ScreenWidth)*AlCon_FontHeight; + + uchar *b=(uchar *)values,newChar,newAttr,oldAttr; + AlCon_DisableAsync(); + uchar aux[count+1]; + newChar=b[charPos]; + newAttr=b[attrPos]; + while (count) + { + if (newChar!=chars[offset] || newAttr!=attrs[offset]) + { + uchar *ind=aux; + oldAttr=newAttr; + xf=x; + do + { + *(ind++)=chars[offset]=newChar; + attrs[offset]=newAttr; + xf+=AlCon_FontWidth; + count--; + if (!count) + break; + offset++; + b+=2; + newChar=b[charPos]; + newAttr=b[attrPos]; + } + while (newAttr==oldAttr && newChar!=chars[offset] && newAttr!=attrs[offset]); + *ind=0; + int nBg,nFg; + nBg=oldAttr>>4; + nFg=oldAttr & 0xF; + AlCon_TextOut((char *)aux,x,y,nFg,nBg); + x=xf; + } + else + { + x+=AlCon_FontWidth; + count--; + offset++; + b+=2; + newChar=b[charPos]; + newAttr=b[attrPos]; + } + } + AlCon_EnableAsync(); +} +#endif + +// TODO: Optimize!!! +void AlCon_Redraw() +{ + ASSERT(Alcon_CurrentFont); + + int nBg,nFg; + unsigned offset=0; + unsigned mx=AlCon_ScreenWidth*AlCon_FontWidth; + unsigned my=AlCon_ScreenHeight*AlCon_FontHeight; + unsigned char aux[2]; + aux[1]=0; + + AlCon_DisableAsync(); + for (unsigned y=0; y>4; + nFg=attrs[offset] & 0xF; + AlCon_TextOut((char *)aux,x,y,nFg,nBg); + } + } + AlCon_EnableAsync(); +} + +void AlCon_GetScrChars(unsigned offset, uint16 *buffer, unsigned count) +{ + unsigned char *b=(unsigned char *)buffer; + + offset/=2; + while (count--) + { + b[charPos]=chars[offset]; + b[attrPos]=attrs[offset]; + b+=2; + offset++; + } +} + +void AlCon_PutChar(unsigned offset, uint16 value) +{ + ASSERT(Alcon_CurrentFont); + int nBg,nFg; + unsigned char *b=(unsigned char *)&value; + unsigned char aux[2]; + unsigned x,y; + aux[1]=0; + + offset/=2; + x = (offset % AlCon_ScreenWidth) * AlCon_FontWidth; + y = (offset / AlCon_ScreenWidth) * AlCon_FontHeight; + AlCon_DisableAsync(); + + aux[0]=chars[offset]=b[charPos]; + attrs[offset]=b[attrPos]; + nBg=b[attrPos]>>4; + nFg=b[attrPos] & 0xF; + AlCon_TextOut((char *)aux,x,y,nFg,nBg); + + AlCon_EnableAsync(); +} + +/***************************************************************************** + + Text cursor routines. + +*****************************************************************************/ + +void AlCon_UnDrawCursor(int *aFgCol) +{ + ASSERT(Alcon_CurrentFont); + ASSERT(aFgCol); + unsigned offset = (cursorX - 1) + (cursorY - 1) * AlCon_ScreenWidth; + int bg=attrs[offset]>>4; + int fg=attrs[offset] & 0xF; + char b[2]; + b[0]=chars[offset]; b[1]=0; + AlCon_TextOut(b,cursorPX,cursorPY,fg,bg); + *aFgCol=colors[fg]; +} + +void AlCon_IntCursor() +{ + if (cursorEnabled) + { + int aFg; + scare_mouse(); + cursorInScreen=!cursorInScreen; + AlCon_UnDrawCursor(&aFg); + if (cursorInScreen) + { + if (!(AlCon_CursorBits & ALCON_CURSOR_HIDE_NORMAL)) + textout_ex(screen, &Alcon_CursorFont, "\x1", cursorPX,cursorPY, aFg, -1); + + if (AlCon_CursorBits & ALCON_CURSOR_ON_SQUARE) + rect(screen, cursorPX, cursorPY, cursorPX + AlCon_FontWidth - 1, + cursorPY + AlCon_FontHeight - 1, aFg); + + if (AlCon_CursorBits & ALCON_CURSOR_ON_CROSS) + { + line(screen, cursorPX, cursorPY, cursorPX + AlCon_FontWidth - 1, + cursorPY + AlCon_FontHeight - 1, aFg); + line(screen, cursorPX, cursorPY + AlCon_FontHeight - 1, + cursorPX + AlCon_FontWidth - 1, cursorPY, aFg); + } + } + unscare_mouse(); + } +} + +/**[txh]******************************************************************** + + Description: Sets the cursor shape. Pass the start and end lines + (inclusive) of the cursor. The lines must be in the range 0 to less than + font's height. Since the start and end are inclusive, you cannot set an + "invisible" cursor shape. Use AlCon_HideCursor() for that. + +***************************************************************************/ + +void AlCon_SetCursorShape(int from, int to) +{ + ASSERT(from <= to); + ASSERT(from >= 0); + ASSERT(to < AlCon_FontHeight); + + unsigned wb=(AlCon_FontWidth+7)/8; + memset(Alcon_CursorData[1]->dat, 0, wb*AlCon_FontHeight); + memset(Alcon_CursorData[1]->dat + wb*from, 0xFF, wb*(to - from + 1)); + AlCon_CursorShapeFrom = from; + AlCon_CursorShapeTo = to; +} + +void AlCon_GetCursorShape(int *from, int *to) +{ + ASSERT(from || to); + if (from) + *from = AlCon_CursorShapeFrom; + if (to) + *to = AlCon_CursorShapeTo; +} + +void Alcon_CreateNewCursor() +{ + Alcon_CursorData[0] =0; + unsigned wb=(AlCon_FontWidth+7)/8; + if (Alcon_CursorData[1]) + free(Alcon_CursorData[1]); + Alcon_CursorData[1] =(FONT_GLYPH *)malloc(sizeof(FONT_GLYPH)+wb*AlCon_FontHeight); + Alcon_CursorData[1]->w = AlCon_FontWidth; + Alcon_CursorData[1]->h = AlCon_FontHeight; + AlCon_SetCursorShape(87 * AlCon_FontHeight / 100, AlCon_FontHeight - 1); +} + +void AlCon_HideCursor() +{ + cursorEnabled=0; +} + +void AlCon_ShowCursor() +{ + cursorEnabled=1; +} + +int AlCon_IsVisCursor() +{ + return cursorEnabled; +} + +/***************************************************************************** + + Initialization routines + +*****************************************************************************/ + +/**[txh]******************************************************************** + + Description: Initialization of the AlCon layer. Pass the number of text + characters you want to have with a default 8x16 font. + + Return: Zero if everything went fine, non zero otherwise. + +***************************************************************************/ + +int AlCon_Init(int w, int h, int fw, int fh, uchar *fdata, AlCon_Color *pal) +{ + if (fw!=-1 && fh!=-1) { + AlCon_FontWidth=fw; + AlCon_FontHeight=fh; + } + + set_uformat(U_ASCII); + //set_uformat(U_UTF8); + + allegro_init(); + + /* Maybe force a specific keyboard layout? */ + if (*AlCon_ForcedKeyboard) { + AlCon_ForcedKeyboard[3] = 0; + set_config_string("system", "keyboard", AlCon_ForcedKeyboard); + } + + install_keyboard(); + al_mouse_buttons = install_mouse(); + al_mouse_wheel = mouse_z; + // Clamp allegro return of "no mouse" to TVision interpretation. + if (al_mouse_buttons < 0) + al_mouse_buttons = 0; + // And add "fake wheel buttons" if the mouse has at least two. + if (al_mouse_buttons > 1) + al_mouse_buttons = 5; + install_timer(); + + /* If we are in a graphic mode and we know the depth use it */ + if (desktop_color_depth()) { + set_color_depth(desktop_color_depth()); + } else { + #ifdef BPP + set_color_depth(BPP); + #else + set_color_depth(8); + #endif + } + + if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, AlCon_FontWidth * w, AlCon_FontHeight * h, + AlCon_FontWidth * w, AlCon_FontHeight * h)) { + set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); + allegro_message("Can't initialize graphics mode\n%s\n",allegro_error); + return 2; + } + // Set the size of the font and screen. + AlCon_ScreenWidth =w; + AlCon_ScreenHeight=h; + + /* Load a binary font. Hack to get the font/screen properties set. */ + ASSERT(fdata); + AlCon_LoadCustomFont(0,fdata,AlCon_FontWidth,AlCon_FontHeight); + //AlCon_LoadCustomFont("rom-PC437.016"); + + /* Create default cursor shape */ + Alcon_CreateNewCursor(); + + /* Create the text mode palette */ + AlCon_SetDisPaletteColors(0,16,pal ? pal : BIOSPalette); + + /* Allocate "screen" buffers */ + AlCon_AllocateMemoryBuffer(); + + install_int(AlCon_IntCursor, 500); + + AlCon_SetColors(7, 0); + AlCon_ClrScr(); + show_mouse(screen); + return 0; +} + +/**[txh]******************************************************************** + + Description: Called when you want to change the font size. You + can call this first with the font size you would like, and see + if AlCon is able to resize the screen to that size. + + Return: Zero on success. A positive number if the resolution was + not set, but AlCon was able to restore the previous screen size + using the old parameters. A negative number if the resolution was + not set, and trying to set it AlCon lost the previous screen, + leaving the whole graphic mode in a mess you can only abort + execution. + +***************************************************************************/ + +int AlCon_Resize(unsigned sW, unsigned sH, int new_font_width, + int new_font_height) +{ + ASSERT(screen && "Did you really initialise me properly?"); + ASSERT(new_font_width > 0); + ASSERT(new_font_height > 0); + ASSERT(AlCon_ScreenWidth > 0); + ASSERT(AlCon_ScreenHeight > 0); + + // Save here the previous parameters... + const int old_w = SCREEN_W; + const int old_h = SCREEN_H; + const int old_card = gfx_driver->id; + + // Hide the mouse during the change. If we don't do it the cursor gets damaged. + show_mouse(NULL); + int temp; + AlCon_UnDrawCursor(&temp); + + // Be brave and try the new screen resolution. + // TODO: Get rid of explicit driver. Maybe use configuration file? + int ret = set_gfx_mode(GFX_AUTODETECT_WINDOWED, + sW * new_font_width, sH * new_font_height, + sW * new_font_width, sH * new_font_height); + + if (ret == 0) + { + AlCon_ScreenWidth=sW; + AlCon_ScreenHeight=sH; + // Reallocate internal memory for text video. + AlCon_AllocateMemoryBuffer(); + // Fix up cursor position, it may have ended up outside screen. + if (cursorX > AlCon_ScreenWidth || cursorY > AlCon_ScreenHeight) + AlCon_GotoXY(1, 1); + + // Clean up the screen, just in case... + clear_to_color(screen, 0); + + show_mouse(screen); + return 0; + } + + // Oops, try to fix our mistake. + ret = set_gfx_mode(old_card, old_w, old_h, old_w, old_h); + if (ret != 0) + return -1; // Bail out completely. + show_mouse(screen); + return 1; // At least we kept our head safe... +} + +/**[txh]******************************************************************** + + Description: Removes allegro from the system, freeing any internal + memory and resetting the graphic mode and other subsystems. + +***************************************************************************/ + +void AlCon_Exit() +{ + ASSERT(chars); + ASSERT(attrs); + + remove_int(AlCon_IntCursor); + set_gfx_mode(GFX_TEXT,0,0,0,0); + allegro_exit(); + free(chars); + free(attrs); + chars = attrs = 0; +} + +int AlCon_SetDisPaletteColors(int from, int number, AlCon_Color *c) +{ + int i; + + for (i=0; i>8; + int ascii=key & 0xFF; + int name,flags; + + //AlCon_CPrintf("key: 0x%04X scan: 0x%02X ascii: 0x%02X ",key,scan,ascii); + if (ascii>=32 && ascii<128) + name=KeyCodeByASCII[ascii-32]; + else + name=keyCode[scan]; + + flags=0; + if (key_shifts & KB_SHIFT_FLAG) + flags|=kbShiftCode; + if (key_shifts & KB_CTRL_FLAG) + flags|=kbCtrlCode; + if (key_shifts & KB_ALT_FLAG) + flags|=kbAltLCode; + + *aSymbol=ascii; + *aFlags=flags; + *aScan=scan; + + return name|flags; +} + +void AlCon_ClearKeyBuf() +{ + clear_keybuf(); +} + +/***************************************************************************** + + Mouse input routines + +*****************************************************************************/ + +// Returns 0 if there is no mouse. +int AlCon_GetMouseButtons(void) +{ + return al_mouse_buttons; +} + +void AlCon_GetMousePos(int *x, int *y, int *buttons) +{ + if (al_mouse_buttons == 1) + return ; + + poll_mouse(); + *x = mouse_x / AlCon_FontWidth; + *y = mouse_y / AlCon_FontHeight; + *buttons = mouse_b; + + // Emulate 4th and 5th buttons through wheelmouse control. + if (mouse_z > al_mouse_wheel) + *buttons |= 1 << 3; + if (mouse_z < al_mouse_wheel) + *buttons |= 1 << 4; + al_mouse_wheel = mouse_z; +} + +uchar AlCon_ShapeFont10x20[]= +{ + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x4C,0x80,0x4C,0x80,0x7C,0x80,0x79,0x80,0x73,0x80,0x73,0x80,0x73,0x80,0x7F,0x80,0x73,0x80,0x73,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x80,0x6D,0x80,0x67,0x00,0x00,0x00,0x39,0x80,0x6D,0x80,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x36,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x67,0x80,0x66,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x36,0x00,0x1F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x6D,0x80,0x6D,0x80,0x6F,0x80,0x6C,0x00,0x6C,0x00,0x6D,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x3F,0x00,0x7F,0x80,0x7F,0x80,0x3F,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x7E,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x00,0x00,0x1F,0x80,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x7C,0x00,0x60,0x00,0x60,0x00,0x78,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x0F,0x80,0x0C,0x00,0x0C,0x00,0x0F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x3C,0x00,0x66,0x00,0x60,0x00,0x60,0x00,0x66,0x00,0x3C,0x00,0x00,0x00,0x1F,0x00,0x19,0x80,0x19,0x80,0x1F,0x00,0x1E,0x00,0x1B,0x00,0x19,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x3E,0x00,0x00,0x00,0x0F,0x80,0x0C,0x00,0x0C,0x00,0x0F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x55,0x40,0x00,0x00,0xAA,0x80,0x00,0x00,0x55,0x40,0x00,0x00,0xAA,0x80,0x00,0x00,0x55,0x40,0x00,0x00,0xAA,0x80,0x00,0x00,0x55,0x40,0x00,0x00,0xAA,0x80,0x00,0x00,0x55,0x40,0x00,0x00,0xAA,0x80,0x00,0x00, + 0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80, + 0x55,0x40,0xFF,0xC0,0xAA,0x80,0xFF,0xC0,0x55,0x40,0xFF,0xC0,0xAA,0x80,0xFF,0xC0,0x55,0x40,0xFF,0xC0,0xAA,0x80,0xFF,0xC0,0x55,0x40,0xFF,0xC0,0xAA,0x80,0xFF,0xC0,0x55,0x40,0xFF,0xC0,0xAA,0x80,0xFF,0xC0, + 0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0, + 0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00, + 0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0, + 0x00,0x00,0x00,0x00,0x66,0x00,0x76,0x00,0x7E,0x00,0x7E,0x00,0x6E,0x00,0x66,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x3C,0x00,0x3C,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x1F,0x80,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x38,0x00,0x0E,0x00,0x03,0x80,0x0E,0x00,0x38,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,0x0E,0x00,0x38,0x00,0xE0,0x00,0x38,0x00,0x0E,0x00,0x03,0x80,0x00,0x00,0x00,0x00,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x18,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x07,0x80,0x1F,0x80,0x7F,0x80,0x7F,0x80,0x1F,0x80,0x07,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x78,0x00,0x7E,0x00,0x7F,0x80,0x7F,0x80,0x7E,0x00,0x78,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x3F,0x00,0x6D,0x80,0x4C,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x4C,0x80,0x6D,0x80,0x3F,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x06,0x00,0x03,0x00,0xFF,0x80,0xFF,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0xFF,0x80,0xFF,0x80,0x60,0x00,0x30,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x3F,0x00,0x6D,0x80,0x4C,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x4C,0x80,0x6D,0x80,0x3F,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0x33,0x00,0x61,0x80,0xFF,0xC0,0xFF,0xC0,0x61,0x80,0x33,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x19,0x80,0x31,0x80,0x7F,0x80,0x7F,0x80,0x30,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x33,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x3F,0xC0,0x1B,0x00,0x1B,0x00,0x1B,0x00,0x7F,0x80,0x36,0x00,0x36,0x00,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x3F,0x00,0x6D,0x80,0x6C,0x00,0x6C,0x00,0x6C,0x00,0x3F,0x00,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x6D,0x80,0x3F,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x80,0x6D,0x80,0x6F,0x00,0x3B,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x1B,0x80,0x1E,0xC0,0x36,0xC0,0x33,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x3C,0x00,0x18,0x00,0x38,0x00,0x6C,0x00,0x66,0xC0,0x63,0x80,0x63,0x00,0x77,0x80,0x3C,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x7F,0x80,0x1E,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1C,0x00,0x3C,0x00,0x6C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x01,0x80,0x01,0x80,0x03,0x00,0x0E,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x01,0x80,0x03,0x00,0x0E,0x00,0x03,0x00,0x01,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x07,0x00,0x0F,0x00,0x1B,0x00,0x33,0x00,0x63,0x00,0x63,0x00,0x7F,0x80,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0x80,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x01,0x80,0x21,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x00,0x01,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x67,0x80,0x6F,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6F,0x00,0x66,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x66,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x66,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x67,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x63,0x00,0x63,0x00,0x66,0x00,0x66,0x00,0x7C,0x00,0x66,0x00,0x66,0x00,0x63,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x73,0x80,0x73,0x80,0x7F,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x71,0x80,0x71,0x80,0x79,0x80,0x79,0x80,0x6D,0x80,0x6D,0x80,0x67,0x80,0x67,0x80,0x63,0x80,0x63,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x6D,0x80,0x67,0x80,0x33,0x00,0x1F,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x66,0x00,0x63,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x60,0x00,0x60,0x00,0x30,0x00,0x1E,0x00,0x03,0x00,0x01,0x80,0x01,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x73,0x80,0x73,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x1E,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0x80,0x01,0x80,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x06,0x00,0x03,0x00,0x03,0x00,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x73,0x00,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x1D,0x80,0x33,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x7F,0x80,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x19,0x80,0x19,0x80,0x18,0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x80,0x63,0x80,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x60,0x00,0x3F,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x3F,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x00,0x00,0x07,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x31,0x80,0x31,0x80,0x31,0x80,0x1F,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x63,0x00,0x66,0x00,0x6C,0x00,0x78,0x00,0x7C,0x00,0x66,0x00,0x63,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5B,0x00,0x7F,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x73,0x00,0x6E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1D,0x80,0x33,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0x00,0x39,0x80,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x60,0x00,0x3F,0x00,0x01,0x80,0x01,0x80,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x19,0x80,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x7F,0x80,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x33,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x61,0x80,0x33,0x00,0x1E,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x01,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x3F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x78,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x07,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x07,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x80,0x6D,0x80,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00, + 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00, + 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x0F,0xC0,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00, + 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0xF8,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00, + 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0xFF,0xC0,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x04,0x00,0x07,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x13,0xC0,0x10,0x00,0x1F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00, + 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xC0,0x10,0x00,0x13,0xC0,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00, + 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x13,0xC0,0x10,0x00,0x13,0xC0,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x08,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0xF2,0x00,0x02,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0xF3,0xC0,0x00,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x02,0x00,0xF2,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00, + 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0xF2,0x00,0x02,0x00,0xF2,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00,0xF3,0xC0,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00, + 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0xF3,0xC0,0x00,0x00,0xF3,0xC0,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x00,0x60,0x00,0x60,0x00,0x61,0x00,0x33,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x19,0x80,0x19,0x80,0x18,0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x7C,0x00,0x56,0xC0,0x73,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x3F,0x00,0x6D,0x80,0x6C,0x00,0x6C,0x00,0x6C,0x00,0x3F,0x00,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x6D,0x80,0x3F,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x3F,0x00,0x0C,0x00,0x3F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x63,0x00,0x30,0x00,0x3C,0x00,0x66,0x00,0x33,0x00,0x19,0x80,0x0F,0x00,0x03,0x00,0x31,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x5E,0x80,0x52,0x80,0x50,0x80,0x52,0x80,0x5E,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x21,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x80,0x0D,0x80,0x1B,0x00,0x36,0x00,0x6C,0x00,0xD8,0x00,0x6C,0x00,0x36,0x00,0x1B,0x00,0x0D,0x80,0x04,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x7F,0x80,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x5E,0x80,0x52,0x80,0x5E,0x80,0x54,0x80,0x56,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x00,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x36,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x36,0x00,0x06,0x00,0x0C,0x00,0x06,0x00,0x36,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x77,0x00,0x7D,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x7F,0x80,0x7D,0x80,0x7D,0x80,0x7D,0x80,0x3D,0x80,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x06,0x00,0x36,0x00,0x1C,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x38,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x36,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x1C,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x6C,0x00,0x36,0x00,0x1B,0x00,0x0D,0x80,0x06,0xC0,0x0D,0x80,0x1B,0x00,0x36,0x00,0x6C,0x00,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x60,0x00,0x20,0x80,0x21,0x00,0x72,0x00,0x04,0x00,0x09,0x00,0x13,0x00,0x25,0x00,0x4F,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x60,0x00,0x20,0x80,0x21,0x00,0x72,0x00,0x04,0x00,0x0B,0x00,0x14,0x80,0x20,0x80,0x41,0x00,0x02,0x00,0x07,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x08,0x00,0x30,0x80,0x09,0x00,0x72,0x00,0x04,0x00,0x09,0x00,0x13,0x00,0x25,0x00,0x4F,0x80,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x19,0x00,0x3F,0x00,0x26,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x1E,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x1E,0x00,0x36,0x00,0x36,0x00,0x66,0x00,0x66,0x00,0x7F,0x80,0x66,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x67,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x61,0x80,0x33,0x00,0x1E,0x00,0x0C,0x00,0x06,0x00,0x36,0x00,0x1C,0x00, + 0x00,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x00,0x00,0x3F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x3F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x3F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x3F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0xF9,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x19,0x00,0x3F,0x00,0x26,0x00,0x00,0x00,0x61,0x80,0x71,0x80,0x79,0x80,0x79,0x80,0x6D,0x80,0x6D,0x80,0x67,0x80,0x67,0x80,0x63,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x19,0x00,0x3F,0x00,0x26,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x63,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x36,0x00,0x63,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x80,0x1F,0x00,0x33,0x00,0x63,0x80,0x63,0x80,0x65,0x80,0x65,0x80,0x65,0x80,0x69,0x80,0x69,0x80,0x69,0x80,0x71,0x80,0x33,0x00,0x3E,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x3F,0x00,0x31,0x80,0x31,0x80,0x31,0x80,0x31,0x80,0x31,0x80,0x3F,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x1B,0x00,0x31,0x80,0x31,0x80,0x33,0x00,0x76,0x00,0x36,0x00,0x33,0x00,0x31,0x80,0x31,0x80,0x31,0x80,0x33,0x00,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x00,0x3F,0x00,0x26,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3B,0x00,0x4D,0x80,0x0D,0x80,0x0F,0x00,0x3C,0x00,0x6C,0x00,0x6C,0x80,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x0C,0x00,0x06,0x00,0x36,0x00,0x1C,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x7F,0x80,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x7F,0x80,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x7F,0x80,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x7F,0x80,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x00,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x07,0xC0,0x01,0x80,0x1D,0x80,0x33,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x00,0x3F,0x00,0x26,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x00,0x3F,0x00,0x26,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x7F,0x80,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x1F,0x00,0x33,0x00,0x65,0x80,0x65,0x80,0x69,0x80,0x69,0x80,0x33,0x00,0x3E,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x61,0x80,0x33,0x00,0x1E,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x3E,0x00,0x33,0x00,0x31,0x80,0x31,0x80,0x31,0x80,0x33,0x00,0x3E,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x61,0x80,0x33,0x00,0x1E,0x00, +}; + +// Exported +uchar AlCon_ShapeFont8x16[]= +{ + 0x00,0x00,0x7E,0xC3,0x99,0x99,0xF3,0xE7,0xE7,0xFF,0xE7,0xE7,0x7E,0x00,0x00,0x00, // 0 + 0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x6E,0xF8,0xD8,0xD8,0xDC,0xD8,0xD8,0xD8,0xF8,0x6E,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0x00,0x6E,0xDB,0xDB,0xDF,0xD8,0xDB,0x6E,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00, //  + 0x00,0x88,0x88,0xF8,0x88,0x88,0x00,0x3E,0x08,0x08,0x08,0x08,0x00,0x00,0x00,0x00, //  + 0x00,0xF8,0x80,0xE0,0x80,0x80,0x00,0x3E,0x20,0x38,0x20,0x20,0x00,0x00,0x00,0x00, //  + 0x00,0x70,0x88,0x80,0x88,0x70,0x00,0x3C,0x22,0x3C,0x24,0x22,0x00,0x00,0x00,0x00, //  + 0x00,0x80,0x80,0x80,0x80,0xF8,0x00,0x3E,0x20,0x38,0x20,0x20,0x00,0x00,0x00,0x00, //  + 0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44, // \t + 0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA, // \n + 0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77, // + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // \r + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //  + 0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0, //  + 0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, //  + 0x00,0x88,0xC8,0xA8,0x98,0x88,0x00,0x20,0x20,0x20,0x20,0x3E,0x00,0x00,0x00,0x00, //  + 0x00,0x88,0x88,0x50,0x50,0x20,0x00,0x3E,0x08,0x08,0x08,0x08,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0x0E,0x38,0xE0,0x38,0x0E,0x00,0xFE,0x00,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0xE0,0x38,0x0E,0x38,0xE0,0x00,0xFE,0x00,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x06,0x0C,0xFE,0x18,0x30,0xFE,0x60,0xC0,0x00,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0x06,0x1E,0x7E,0xFE,0x7E,0x1E,0x06,0x00,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0xC0,0xF0,0xFC,0xFE,0xFC,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // 0x1A + 0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0x00,0x28,0x6C,0xFE,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0x06,0x36,0x66,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // + 0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // ! + 0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // " + 0x00,0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00, // # + 0x00,0x10,0x10,0x7C,0xD6,0xD0,0xD0,0x7C,0x16,0x16,0xD6,0x7C,0x10,0x10,0x00,0x00, // $ + 0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00, // % + 0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // & + 0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ' + 0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00, // ( + 0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00, // ) + 0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00, // * + 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // + + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00, // , + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // - + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // . + 0x00,0x00,0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00,0x00,0x00,0x00,0x00, // / + 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 0 + 0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00, // 1 + 0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00, // 2 + 0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3 + 0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00, // 4 + 0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5 + 0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 6 + 0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00, // 7 + 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 8 + 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00, // 9 + 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, // : + 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00, // ; + 0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00, // < + 0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // = + 0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00, // > + 0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // ? + 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0x7C,0x00,0x00,0x00,0x00, // @ + 0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // A + 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00, // B + 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00, // C + 0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00, // D + 0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00, // E + 0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // F + 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00, // G + 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // H + 0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // I + 0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00, // J + 0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // K + 0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00, // L + 0x00,0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // M + 0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // N + 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // O + 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // P + 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00, // Q + 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // R + 0x00,0x00,0x7C,0xC6,0xC6,0x64,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // S + 0x00,0x00,0x7E,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // T + 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // U + 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00, // V + 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00, // W + 0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00, // X + 0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // Y + 0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00, // Z + 0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00, // [ + 0x00,0x00,0x00,0x00,0x00,0xC0,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00,0x00, // \ . + 0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00, // ] + 0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ^ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00, // _ + 0x00,0x30,0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ` + 0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // a + 0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00, // b + 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // c + 0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // d + 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // e + 0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // f + 0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0xCC,0x78,0x00, // g + 0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // h + 0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // i + 0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00, // j + 0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00, // k + 0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // l + 0x00,0x00,0x00,0x00,0x00,0xEC,0xFE,0xD6,0xD6,0xD6,0xD6,0xC6,0x00,0x00,0x00,0x00, // m + 0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, // n + 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // o + 0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00, // p + 0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00, // q + 0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // r + 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00, // s + 0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00, // t + 0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // u + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00, // v + 0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00, // w + 0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00, // x + 0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00, // y + 0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00, // z + 0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00, // { + 0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // | + 0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00, // } + 0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ~ + 0x00,0x66,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // € + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ‚ + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ƒ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // „ + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // … + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // † + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // ‡ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ˆ + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ‰ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Š + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ‹ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // Œ + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // Ž + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00, // + 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ‘ + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x60,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ’ + 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6F,0x60,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // “ + 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C, // ” + 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C, // • + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x60,0x6F,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C, // – + 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6F,0x60,0x6F,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C, // — + 0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x0C,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ˜ + 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0xEC,0x0C,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ™ + 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // š + 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0xEF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // › + 0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x0C,0xEC,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C, // œ + 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0xEC,0x0C,0xEC,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C, // + 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xEF,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C, // ž + 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0xEF,0x00,0xEF,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C, // Ÿ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0xFE,0x00,0x00,0x00,0x00, //   + 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00, // ¡ + 0x00,0x00,0x00,0x00,0x10,0x7C,0xD6,0xD0,0xD0,0xD0,0xD6,0x7C,0x10,0x00,0x00,0x00, // ¢ + 0x00,0x00,0x38,0x6C,0x60,0x60,0xF0,0x60,0x60,0x66,0xF6,0x6C,0x00,0x00,0x00,0x00, // £ + 0x00,0x00,0x00,0x00,0xC6,0x7C,0x6C,0x6C,0x7C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00, // ¤ + 0x00,0x00,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // ¥ + 0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // ¦ + 0x00,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00, // § + 0x00,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ¨ + 0x00,0x00,0x3C,0x42,0x99,0xA5,0xA1,0xA5,0x99,0x42,0x3C,0x00,0x00,0x00,0x00,0x00, // © + 0x00,0x00,0x3C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ª + 0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00, // « + 0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00, // ¬ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ­ + 0x00,0x00,0x3C,0x42,0xB9,0xA5,0xB9,0xA5,0xA5,0x42,0x3C,0x00,0x00,0x00,0x00,0x00, // ® + 0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ¯ + 0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ° + 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x7E,0x00,0x00,0x00,0x00, // ± + 0x38,0x6C,0x18,0x30,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ² + 0x38,0x6C,0x18,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ³ + 0x00,0x18,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ´ + 0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xF6,0xC0,0xC0,0xC0,0x00, // µ + 0x00,0x00,0x7F,0xD6,0xD6,0x76,0x36,0x36,0x36,0x36,0x36,0x36,0x00,0x00,0x00,0x00, // ¶ + 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // · + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x6C,0x38,0x00, // ¸ + 0x30,0x70,0x30,0x30,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ¹ + 0x00,0x00,0x38,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // º + 0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,0x00, // » + 0x00,0x60,0xE0,0x60,0x66,0x0C,0x18,0x30,0x66,0xCE,0x1A,0x3F,0x06,0x06,0x00,0x00, // ¼ + 0x00,0x60,0xE0,0x60,0x66,0x0C,0x18,0x30,0x6E,0xDB,0x06,0x0C,0x1F,0x00,0x00,0x00, // ½ + 0x70,0xD8,0x30,0xD8,0x76,0x0C,0x18,0x30,0x66,0xCE,0x1A,0x3F,0x06,0x06,0x00,0x00, // ¾ + 0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x30,0x60,0xC6,0xC6,0x7C,0x00,0x00, // ¿ + 0x60,0x30,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // À + 0x0C,0x18,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // Á + 0x10,0x38,0x6C,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, //  + 0x76,0xDC,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // à + 0x00,0x6C,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // Ä + 0x38,0x6C,0x38,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // Å + 0x00,0x00,0x3E,0x78,0xD8,0xD8,0xFC,0xD8,0xD8,0xD8,0xD8,0xDE,0x00,0x00,0x00,0x00, // Æ + 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x0C,0x66,0x3C,0x00, // Ç + 0x60,0x30,0x00,0xFE,0x66,0x60,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00, // È + 0x0C,0x18,0x00,0xFE,0x66,0x60,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00, // É + 0x10,0x38,0x6C,0x00,0xFE,0x66,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00, // Ê + 0x00,0x6C,0x00,0xFE,0x66,0x60,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00, // Ë + 0x60,0x30,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // Ì + 0x06,0x0C,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // Í + 0x18,0x3C,0x66,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // Î + 0x00,0x66,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // Ï + 0x00,0x00,0xF8,0x6C,0x66,0x66,0xF6,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00, // Ð + 0x76,0xDC,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // Ñ + 0x60,0x30,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // Ò + 0x0C,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // Ó + 0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // Ô + 0x76,0xDC,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // Õ + 0x00,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // Ö + 0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0x18,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00, // × + 0x00,0x00,0x7E,0xC6,0xCE,0xCE,0xDE,0xF6,0xE6,0xE6,0xC6,0xFC,0x00,0x00,0x00,0x00, // Ø + 0x60,0x30,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // Ù + 0x0C,0x18,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // Ú + 0x10,0x38,0x6C,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // Û + 0x00,0x6C,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // Ü + 0x06,0x0C,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // Ý + 0x00,0x00,0xF0,0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x60,0xF0,0x00,0x00,0x00,0x00, // Þ + 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xCC,0xC6,0xC6,0xC6,0xD6,0xDC,0x80,0x00,0x00,0x00, // ß + 0x00,0x60,0x30,0x18,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // à + 0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // á + 0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // â + 0x00,0x00,0x76,0xDC,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // ã + 0x00,0x00,0x00,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // ä + 0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // å + 0x00,0x00,0x00,0x00,0x00,0x7E,0xDB,0x1B,0x7F,0xD8,0xDB,0x7E,0x00,0x00,0x00,0x00, // æ + 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x18,0x6C,0x38,0x00, // ç + 0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // è + 0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // é + 0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // ê + 0x00,0x00,0x00,0x6C,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // ë + 0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // ì + 0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // í + 0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // î + 0x00,0x00,0x00,0x6C,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // ï + 0x00,0x78,0x30,0x78,0x0C,0x7E,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // ð + 0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, // ñ + 0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // ò + 0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // ó + 0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // ô + 0x00,0x00,0x76,0xDC,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // õ + 0x00,0x00,0x00,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // ö + 0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // ÷ + 0x00,0x00,0x00,0x00,0x00,0x7E,0xCE,0xDE,0xFE,0xF6,0xE6,0xFC,0x00,0x00,0x00,0x00, // ø + 0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // ù + 0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // ú + 0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // û + 0x00,0x00,0x00,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // ü + 0x00,0x0C,0x18,0x30,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00, // ý + 0x00,0x00,0xF0,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00,0x00, // þ + 0x00,0x00,0x00,0x6C,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00 // 255 +}; + +void AlCon_SetFont(int which, uchar *fnt, unsigned w, unsigned h) +{ + unsigned sizeChanged=w!=(unsigned)AlCon_FontWidth || + h!=(unsigned)AlCon_FontHeight; + AlCon_FontWidth =w; + AlCon_FontHeight=h; + unsigned wb=(w+7)/8; + unsigned sizeGlyph=wb*h; + + FONT_GLYPH **p=which ? Alcon_ASCIIDataS : Alcon_ASCIIDataP; + // Copy font from buffer to internal structure. + for (int i=0; i<0x100; i++) + {// Free previously allocated memory. + if (p[i]) + free(p[i]); + + p[i]=(FONT_GLYPH *)malloc(sizeof(FONT_GLYPH)+sizeGlyph); + p[i]->w=AlCon_FontWidth; + p[i]->h=AlCon_FontHeight; + + memcpy(p[i]->dat,fnt,sizeGlyph); + fnt+=sizeGlyph; + } + Alcon_PrimaryFont.height = + Alcon_SecondaryFont.height= + Alcon_CursorFont.height =AlCon_FontHeight; + + if (sizeChanged) + Alcon_CreateNewCursor(); +} + +/**[txh]******************************************************************** + + Description: Loads the specified binary format font into an internal + structure like Allegro's font and then sets the static global font pointer + to that. If the font could not be loaded, the previously loaded custom + font will be used. If this was the first custom font call, Allegro's + default font will be used if everything fails. If the filename is a NULL + pointer, the default font will be used. + +***************************************************************************/ + +static +void AlCon_LoadCustomFont(const char *filename, uchar *fdata, unsigned fw, + unsigned fh) +{ + ASSERT(screen && "You have to call set_gfx_mode before."); + static bool one_custom_font_loaded = false; + unsigned wb=(fw+7)/8; + + FILE *file = NULL; + if (filename) + file = fopen(filename, "rb"); + + unsigned maxRead=wb*fh*0x100; + uchar *font_buffer, buffer[maxRead]; + int read_bytes=0; + if (!file) { + if (fdata) { + font_buffer=fdata; + read_bytes=maxRead; + } else { + font_buffer=AlCon_ShapeFont8x16; + wb=1; fw=8; fh=16; + read_bytes=4096; + } + } else { + font_buffer=buffer; + int read_bytes=fread(font_buffer, 1, maxRead, file); + fclose(file); + if (read_bytes < 256) {// Absurd size limit + allegro_message("Absurd custom font size (%d bytes)", read_bytes); + exit(3); + } + one_custom_font_loaded = true; + } + + // Initialize global variables. + Alcon_CurrentFont=&Alcon_PrimaryFont; + Alcon_PrimaryFont.vtable=font->vtable; + Alcon_PrimaryFont.data=&Alcon_ASCIIMonoFontP; + Alcon_SecondaryFont.vtable=font->vtable; + Alcon_SecondaryFont.data=&Alcon_ASCIIMonoFontS; + Alcon_CursorFont.vtable=font->vtable; + Alcon_CursorFont.data=&Alcon_CursorMonoFont; + + AlCon_SetFont(0,font_buffer,fw,read_bytes/(0x100*wb)); +} + +/**[txh]******************************************************************** + + Description: Fills in the width and height of a text cell. + +***************************************************************************/ + +void AlCon_GetFontGeometry(unsigned int *w, unsigned int *h) +{ + ASSERT(w || h); + if (w) + *w = AlCon_FontWidth; + if (h) + *h = AlCon_FontHeight; +} + +/**[txh]******************************************************************** + + Description: Allocates for the chars and attrs global buffers + enough memory as specified by the variables AlCon_ScreenWidth + and AlCon_ScreenHeight. If these global variables already had + something allocated to them (ie: you are resizing the screen), + that memory is freed before the new allocation takes place. + +***************************************************************************/ + +static void AlCon_AllocateMemoryBuffer(void) +{ + if (chars) { + ASSERT(attrs); + free(chars); + free(attrs); + } + chars = (unsigned char *)malloc(AlCon_ScreenWidth * AlCon_ScreenHeight); + attrs = (unsigned char *)malloc(AlCon_ScreenWidth * AlCon_ScreenHeight); + ASSERT(chars && attrs); +} + +#endif // HAVE_ALLEGRO diff --git a/tvision/classes/alcon/alcondis.cc b/tvision/classes/alcon/alcondis.cc new file mode 100644 index 0000000..132708f --- /dev/null +++ b/tvision/classes/alcon/alcondis.cc @@ -0,0 +1,119 @@ +/***************************************************************************** + + Copyright (c) 2003-2004 by Grzegorz Adam Hankiewicz + Copyright (c) 2004-2009 by Salvador E. Tropea (SET) + + TDisplayAlcon + AlCon driver for Turbo Vision. It uses the conio.h emulation library on top + of Allegro. + + Contributed by Grzegorz Adam Hankiewicz + + This is part of Turbo Vision ditribution and covered by the same license. + +*****************************************************************************/ + +#include + +#define Uses_TScreen +#define Uses_TEvent +#define Uses_TGKey +#include + +#include +#include +#include +#define Uses_AlCon_conio +#include + +#ifdef HAVE_ALLEGRO + +void TDisplayAlcon::Init() +{ + setCursorPos=SetCursorPos; + getCursorPos=GetCursorPos; + getCursorShape=GetCursorShape; + setCursorShape=SetCursorShape; + // DOS version has this, where? TDisplay::clearScreen=ClearScreen; + getRows=GetRows; + getCols=GetCols; +// TDisplay::setCrtMode=SetCrtMode; +// TDisplay::getCrtMode=GetCrtMode; +// TDisplay::setCrtModeExt=SetCrtModeExt; +// TDisplay::setCrtModeRes_p=SetCrtModeRes; +// TDisplay::getWindowTitle=GetWindowTitle; +// TDisplay::setWindowTitle=SetWindowTitle; +// TDisplay::setDisPaletteColors=SetDisPaletteColors; +// TDisplay::getDisPaletteColors=GetDisPaletteColors; +// TDisplay::beep=Beep; +} + +TDisplayAlcon::~TDisplayAlcon() +{ +} + +void TDisplayAlcon::GetCursorPos(unsigned &x, unsigned &y) +{ + // AlCon returns vars in the range of 1 <= var <= inf. + x = AlCon_WhereX() - 1; + y = AlCon_WhereY() - 1; +} + +void TDisplayAlcon::SetCursorPos(unsigned x, unsigned y) +{ + // AlCon expects a range of 1 <= var <= inf. + AlCon_GotoXY(x + 1, y + 1); +} + +/**[txh]******************************************************************** + + Description: Called with percentage values from 0 to 100 inclusive. + If start is bigger or equal end (usually both 0), this means hide the + cursor. + +***************************************************************************/ + +void TDisplayAlcon::SetCursorShape(unsigned start, unsigned end) +{ + if (start >= end && getShowCursorEver()) + return; + + if (start >= end) { + AlCon_HideCursor(); + } else { + AlCon_ShowCursor(); + unsigned int h; + AlCon_GetFontGeometry(0, &h); + AlCon_SetCursorShape(int(start * (h - 0.00001f) / 100), + int(end * (h - 0.00001f) / 100)); + } +} + +/**[txh]******************************************************************** + + Description: Fills into start and end the beginning and end of the cursor + shape as percentage values from 0 to 1. + +***************************************************************************/ + +void TDisplayAlcon::GetCursorShape(unsigned &start, unsigned &end) +{ + int _start, _end; + unsigned int h; + AlCon_GetCursorShape(&_start, &_end); + AlCon_GetFontGeometry(0, &h); + start = 100 * _start / h; + end = 100 * _end / h; +} + +ushort TDisplayAlcon::GetRows() +{ + return AlCon_ScreenRows(); +} + +ushort TDisplayAlcon::GetCols() +{ + return AlCon_ScreenCols(); +} + +#endif // HAVE_ALLEGRO diff --git a/tvision/classes/alcon/alconkey.cc b/tvision/classes/alcon/alconkey.cc new file mode 100644 index 0000000..c434c34 --- /dev/null +++ b/tvision/classes/alcon/alconkey.cc @@ -0,0 +1,79 @@ +/***************************************************************************** + + Copyright (c) 2003-2004 by Grzegorz Adam Hankiewicz + Copyright (c) 2004-2009 by Salvador E. Tropea (SET) + + TGKeyAlcon + AlCon driver for Turbo Vision. It uses the conio.h emulation library on top + of Allegro. + + Contributed by Grzegorz Adam Hankiewicz + + This is part of Turbo Vision ditribution and covered by the same license. + +*****************************************************************************/ + +#include + +#define Uses_TScreen +#define Uses_TEvent +#define Uses_TGKey +#include + +#include +#define Uses_AlCon_conio +#include + +#ifdef HAVE_ALLEGRO + +/***************************************************************************** + + TGKeyAlcon keyboard stuff. + +*****************************************************************************/ + +unsigned TGKeyAlcon::Symbol; +uchar TGKeyAlcon::Scan; +unsigned TGKeyAlcon::Flags; + +void TGKeyAlcon::Init() +{ + TGKey::kbhit = KbHit; + TGKey::clear = Clear; + TGKey::gkey = GKey; + TGKey::fillTEvent = FillTEvent; +// TGKey::getShiftState=GetShiftState; +} + +int TGKeyAlcon::KbHit() +{ + return AlCon_KbHit(); +} + +void TGKeyAlcon::Clear() +{ + AlCon_ClearKeyBuf(); +} + +ushort TGKeyAlcon::GKey() +{ + return AlCon_GetKey(&Symbol, &Scan, &Flags); +} + +void TGKeyAlcon::FillTEvent(TEvent &e) +{ + ushort Abstract=GKey(); + e.keyDown.charScan.charCode=((Flags & kbAltLCode) && (Symbol<128)) ? 0 : Symbol; + e.keyDown.charScan.scanCode=Scan; + e.keyDown.raw_scanCode=Scan; + e.keyDown.keyCode=Abstract; + e.keyDown.shiftState=0; + // TODO: fill the shiftState correctly. + //e.keyDown.shiftState=kbFlags; + + // TODO: Unicode? Yeah right. + //e.keyDown.charCode=Unicode; // Should I do the same as with Symbol? + e.what=evKeyDown; +} + +#endif // HAVE_ALLEGRO diff --git a/tvision/classes/alcon/alconmouse.cc b/tvision/classes/alcon/alconmouse.cc new file mode 100644 index 0000000..a6e6143 --- /dev/null +++ b/tvision/classes/alcon/alconmouse.cc @@ -0,0 +1,47 @@ +/***************************************************************************** + + Copyright (c) 2003-2004 by Grzegorz Adam Hankiewicz + Copyright (c) 2004-2009 by Salvador E. Tropea (SET) + + THWMouseAlcon + AlCon driver for Turbo Vision. It uses the conio.h emulation library on top + of Allegro. + + Contributed by Grzegorz Adam Hankiewicz + + This is part of Turbo Vision ditribution and covered by the same license. + +*****************************************************************************/ + +#include + +#define Uses_stdio +#define Uses_TScreen +#define Uses_TEvent +#define Uses_TGKey +#include + +#include +#define Uses_AlCon_conio +#include + +#ifdef HAVE_ALLEGRO + +void THWMouseAlcon::Init() +{ + THWMouse::GetEvent=GetEvent; + buttonCount=AlCon_GetMouseButtons(); +} + +THWMouseAlcon::~THWMouseAlcon() +{ +} + +void THWMouseAlcon::GetEvent(MouseEventType &me) +{ + int buttons; + AlCon_GetMousePos(&me.where.x, &me.where.y, &buttons); + me.buttons = uchar(buttons & 255); + me.doubleClick=False; +} +#endif // HAVE_ALLEGRO diff --git a/tvision/classes/alcon/alconscr.cc b/tvision/classes/alcon/alconscr.cc new file mode 100644 index 0000000..643bbdb --- /dev/null +++ b/tvision/classes/alcon/alconscr.cc @@ -0,0 +1,509 @@ +/***************************************************************************** + + Copyright (c) 2003-2004 by Grzegorz Adam Hankiewicz + Copyright (c) 2004-2009 by Salvador E. Tropea (SET) + + TScreenAlcon + AlCon driver for Turbo Vision. It uses the conio.h emulation library on top + of Allegro. + + Contributed by Grzegorz Adam Hankiewicz + + This is part of Turbo Vision ditribution and covered by the same license. + +*****************************************************************************/ + +#include + +#define Uses_stdio // DEBUG +#define Uses_TScreen +#define Uses_TEvent +#define Uses_TGKey +#include + +#include +#include +#include +#define Uses_AlCon_conio +#include + +#ifdef HAVE_ALLEGRO + +#define PRINTF(FORMAT, args...) printf("%s " FORMAT "\n", __PRETTY_FUNCTION__, ## args) + +const unsigned foWmin=5, foHmin=7, foWmax=20, foHmax=32; +TScreenFont256 TScreenAlcon::font8x16={ 8,16,AlCon_ShapeFont8x16 }; +TScreenFont256 TScreenAlcon::font10x20={ 10,20,AlCon_ShapeFont10x20 }; +TScreenFont256 *TScreenAlcon::defaultFont=&font8x16; +uchar TScreenAlcon::primaryFontChanged=0; +unsigned TScreenAlcon::fontW; +unsigned TScreenAlcon::fontWb; +unsigned TScreenAlcon::fontH; +unsigned TScreenAlcon::fontSz; + +TScreen *TV_AlconDriverCheck() +{ + TScreenAlcon *drv = new TScreenAlcon(); + if (!TScreen::initialized) { + delete drv; + return 0; + } + return drv; +} + + +TScreenAlcon::TScreenAlcon() +{ + // TODO: That's wrong we should be shure Allegro will succeed before doing it. + if (dCB) dCB(); + + screenWidth=80; screenHeight=25; + fontW=8; fontH=16; + + /* Code page */ + optSearch("AppCP",forcedAppCP); + optSearch("ScrCP",forcedScrCP); + optSearch("InpCP",forcedInpCP); + /* User settings have more priority than detected settings */ + codePage=new TVCodePage(forcedAppCP!=-1 ? forcedAppCP : TVCodePage::ISOLatin1Linux, + forcedScrCP!=-1 ? forcedScrCP : TVCodePage::ISOLatin1Linux, + forcedInpCP!=-1 ? forcedInpCP : TVCodePage::ISOLatin1Linux); + SetDefaultCodePages(TVCodePage::ISOLatin1Linux,TVCodePage::ISOLatin1Linux, + TVCodePage::ISOLatin1Linux); + + long aux; + if (optSearch("ScreenWidth",aux)) + screenWidth=aux; + if (optSearch("ScreenHeight",aux)) + screenHeight=aux; + if (optSearch("FontWidth",aux)) + fontW=aux; + if (optSearch("FontHeight",aux)) + fontH=aux; + + const char *lang = optSearch("KeyboardMapping"); + if (lang) { + AlCon_ForcedKeyboard[0] = lang[0]; + if (lang[0]) + AlCon_ForcedKeyboard[1] = lang[1]; + } + + // Set extra cursor bits through config parameters. + #define READ_BIT(CONFIG_NAME, BIT_NAME) \ + { \ + if (optSearch(CONFIG_NAME, aux)) \ + if (aux) \ + AlCon_CursorBits |= BIT_NAME; \ + } + + READ_BIT("CursorHideNormal", ALCON_CURSOR_HIDE_NORMAL); + READ_BIT("CursorOnSquare", ALCON_CURSOR_ON_SQUARE); + READ_BIT("CursorOnCross", ALCON_CURSOR_ON_CROSS); + + #undef READ_BIT + + uchar *fontData=NULL; + int freeFontData=1; + TScreenFont256 *secFont=NULL; + TScreenFont256 *useFont=NULL; + + if (fontW==10 && fontH==20) + defaultFont=&font10x20; + + if (!frCB || !(useFont=frCB(0,fontW,fontH))) + { + useFont=defaultFont; + freeFontData=0; + } + + fontW=useFont->w; + fontH=useFont->h; + fontWb=(useFont->w+7)/8; + fontSz=fontWb*fontH; + fontData=useFont->data; + + // Create screen. + TScreenColor *pal=parseUserPalette() ? UserStartPalette : PC_BIOSPalette; + int res=AlCon_Init(screenWidth,screenHeight,fontW,fontH,fontData,(AlCon_Color *)pal); + if (freeFontData) + {/* Provided by the call back */ + DeleteArray(useFont->data); + delete useFont; + } + if (res) + return; + + // Secondary font. + aux=0; + if (frCB && optSearch("LoadSecondaryFont",aux) && aux) + { + secFont=frCB(1,fontW,fontH); + if (secFont) + { + AlCon_SetFont(1,secFont->data,fontW,fontH); + DeleteArray(secFont->data); + delete secFont; + } + } + + /* + Even though we initialised AlCon with a wanted screen + width and height, it might have had to change it in order + to accomodate the font which was loaded. + */ + screenWidth = AlCon_ScreenCols(); + screenHeight = AlCon_ScreenRows(); + memcpy(ActualPalette,AlCon_CurPalette,sizeof(ActualPalette)); + memcpy(OriginalPalette,AlCon_CurPalette,sizeof(OriginalPalette)); + + // Find font geometry + AlCon_GetFontGeometry(&fontW,&fontH); + fontWb=(fontW+7)/8; + fontSz=fontWb*fontH; + + TDisplayAlcon::Init(); + + TScreen::Resume=Resume; + TScreen::Suspend=Suspend; + TScreen::clearScreen=clearScreen; + TScreen::getCharacters=getCharacters; + TScreen::getCharacter=getCharacter; + TScreen::setCharacter=setCharacter; + TScreen::setCharacters=setCharacters; + TScreen::setDisPaletteColors=SetDisPaletteColors; + // Fonts stuff + TScreen::getFontGeometry=GetFontGeometry; + TScreen::getFontGeometryRange=GetFontGeometryRange; + TScreen::setFont_p=SetFont; + TScreen::restoreFonts=RestoreFonts; + TScreen::setCrtModeRes_p=SetCrtModeRes; + initialized=1; + + TGKeyAlcon::Init(); + THWMouseAlcon::Init(); + + // Tell TScreen that there is a cursor. + setCrtData(); + startupCursor = cursorLines; + startupMode = screenMode; + + // Create memory buffer for screen. We want a buffer (even though + // AlCon is buffered) because otherwise TVision will use simple + // memcpy calls to "paint" the screen. We don't want this, because + // Allegro has to be told when to update the screen. So it's a + // buffer on top of Allegro's buffer so that Allegro get's called. + // Wicked. But works. + screenBuffer=new uint16[screenWidth*screenHeight]; + + flags0|=CanSetPalette | CanReadPalette | CanSetBFont | CanSetSBFont | + CanSetVideoSize; + + suspended=0; +} + +void TScreenAlcon::Resume() +{ + AlCon_Redraw(); + AlCon_EnableAsync(); +} + +void TScreenAlcon::Suspend() +{ + AlCon_DisableAsync(); +} + +TScreenAlcon::~TScreenAlcon() +{ + delete[] screenBuffer; + + // Deinitialize all. + AlCon_Exit(); +} + + +void TScreenAlcon::clearScreen() +{ + TDisplay::clearScreen(AlCon_ScreenCols(), AlCon_ScreenCols()); +} + + +ushort TScreenAlcon::getCharacter(unsigned offset) +{ + ushort buffer; + AlCon_GetScrChars(offset, &buffer, 1); + return buffer; +} + + +void TScreenAlcon::getCharacters(unsigned offset, ushort *buffer, unsigned count) +{ + AlCon_GetScrChars(offset, buffer, count); +} + + +void TScreenAlcon::setCharacter(unsigned offset, ushort value) +{ + AlCon_PutChar(offset, value); +} + + +void TScreenAlcon::setCharacters(unsigned offset, ushort *values, unsigned count) +{ + AlCon_PutBuf(offset, values, count); +} + + +int TScreenAlcon::GetFontGeometry(unsigned &w, unsigned &h) +{ + w=fontW; + h=fontH; + return 1; +} + +int TScreenAlcon::GetFontGeometryRange(unsigned &wmin, unsigned &hmin, + unsigned &wmax, unsigned &hmax) +{ + wmin=foWmin; + hmin=foHmin; + wmax=foWmax; + hmax=foHmax; + return 1; +} + +int TScreenAlcon::SetFont(int changeP, TScreenFont256 *fontP, + int changeS, TScreenFont256 *fontS, + int fontCP, int appCP) +{ + if (!changeP && !changeS) return 1; + // Check for restore fonts + if (changeP && !fontP && ((!changeS && !useSecondaryFont) || (changeS && !fontS))) + fontP=defaultFont; + + // Solve the sizes + unsigned wP, hP, wS, hS; + if (changeP) + { + if (fontP) + { + wP=fontP->w; + hP=fontP->h; + } + else + { + wP=defaultFont->w; + hP=defaultFont->h; + } + } + else + { + wP=fontW; + hP=fontH; + } + if (changeS) + { + if (fontS) + { + wS=fontS->w; + hS=fontS->h; + } + else + {// Disabled + wS=wP; + hS=hP; + } + } + else + { + if (useSecondaryFont) + { + wS=fontW; + hS=fontH; + } + else + {// Disabled + wS=wP; + hS=hP; + } + } + // Size missmatch + if (wP!=wS || hP!=hS) return 0; + // This driver currently doesn't support changing the font size on the fly + //if (wP!=fontW || hP!=fontH) return 0; + // Check if the size is in the range + if (wPfoWmax || hPfoHmax) + return 0; + + // Change the requested fonts + if (changeP) + { + if (fontP && fontP->data) + { + AlCon_SetFont(0,fontP->data,wP,hP); + primaryFontChanged=1; + } + else + { + AlCon_SetFont(0,defaultFont->data,wP,hP); + primaryFontChanged=0; + } + } + if (changeS) + { + if (fontS) + { + AlCon_SetFont(1,fontS->data,wP,hP); + useSecondaryFont=1; + AlCon_EnableSecFont(); + } + else + { + useSecondaryFont=0; + AlCon_DisableSecFont(); + } + } + // Change the code page + if (changeP && fontCP!=-1) + { + if (appCP==-1) + TVCodePage::SetScreenCodePage(fontCP); + else + TVCodePage::SetCodePage(appCP,fontCP,-1); + } + if (wP!=fontW || hP!=fontH) + { + DoResize(wP,hP); + } + AlCon_Redraw(); + + return 1; +} + +void TScreenAlcon::RestoreFonts() +{ + SetFont(1,NULL,1,NULL,TVCodePage::ISOLatin1Linux,TVCodePage::ISOLatin1Linux); +} + +int TScreenAlcon::SetDisPaletteColors(int from, int number, TScreenColor *colors) +{ + int i=AlCon_SetDisPaletteColors(from,number,(AlCon_Color *)colors); + AlCon_Redraw(); + return i; +} + +/**[txh]******************************************************************** + + Description: Called to perform a screen resize. The fonts for the new + screen size have already been loaded. The parameters indicate the size + in pixels of each text cell. Therefore, this function adjusts the cursor, + some internal variables, and requests Allegro to set a different size. + +***************************************************************************/ + +void TScreenAlcon::DoResize(unsigned w, unsigned h) +{ + ASSERT(w>0); + ASSERT(h>0); + + int ret=AlCon_Resize(screenWidth,screenHeight,w,h); + if (ret!=0) + { + PRINTF("Ayeeee! A monkey with three heads! %d\n", ret); + exit(ret); + } + if (w!=fontW || h!=fontH) + { + int cShapeFrom, cShapeTo; + AlCon_GetCursorShape(&cShapeFrom,&cShapeTo); + double start=cShapeFrom/(double)fontH; + double end =cShapeTo/(double)fontH; + fontW=w; + fontWb=(w+7)/8; + fontH=h; + fontSz=fontWb*h; + + /* Change the cursor shape */ + cShapeFrom=int(start*fontH+0.5); + cShapeTo =int(end*fontH+0.5); + if ((unsigned)cShapeFrom>=fontH) cShapeFrom=fontH-1; + if ((unsigned)cShapeTo>=fontH) cShapeTo=fontH-1; + AlCon_SetCursorShape(cShapeFrom,cShapeTo); + } + + /* Compute cursor position and draw it */ + AlCon_GotoXY(AlCon_WhereX(),AlCon_WhereY()); +} + +int TScreenAlcon::SetCrtModeRes(unsigned w, unsigned h, int fW, int fH) +{ + if (fW==-1) fW=fontW; + if (fH==-1) fH=fontH; + if (w==screenWidth && h==screenHeight && + fontW==(unsigned)fW && fontH==(unsigned)fH) return 0; + + unsigned nW=fontW, nH=fontH; + TScreenFont256 *nFont=NULL,*nsFont=NULL; + int releaseFont=0, releaseSFont=0, resetFont=0; + + // Solve the fonts, don't change them yet. + if ((unsigned)fW!=fontW || (unsigned)fH!=fontH) + { + if (primaryFontChanged) + {// The application set a font, ask for this new one + if (frCB && (nFont=frCB(0,fW,fH))) + releaseFont=1; + else + {// No replacement available, revert to our font. + resetFont=1; + nFont=&font8x16; + } + } + else + { + if (fW==8 && fH==16) + resetFont=1, nFont=&font8x16; + else if (frCB && (nFont=frCB(0,fW,fH))) + releaseFont=1; + else + resetFont=1, nFont=&font8x16; + } + nW=nFont->w; + nH=nFont->h; + if ((nW!=fontW || nH!=fontH) && useSecondaryFont) + { + if (frCB && (nsFont=frCB(1,nW,nH))) + releaseSFont=1; + } + } + + + AlCon_DisableAsync(); + if (nFont) + { + AlCon_SetFont(0,nFont->data,nW,nH); + if (resetFont) + primaryFontChanged=0; + if (releaseFont) + { + DeleteArray(nFont->data); + delete nFont; + } + } + if (useSecondaryFont) + { + if (nsFont) + AlCon_SetFont(1,nsFont->data,nW,nH); + } + // Should I check the size? + screenWidth=w; screenHeight=h; + + delete[] screenBuffer; + screenBuffer=new uint16[screenWidth*screenHeight]; + memset(screenBuffer,0,screenWidth*screenHeight*sizeof(uint16)); + AlCon_EnableAsync(); + + DoResize(nW,nH); + + return (nW==(unsigned)fW && nH==(unsigned)fH) ? 1 : 2; +} + +#endif // HAVE_ALLEGRO diff --git a/tvision/classes/calcdisp.cc b/tvision/classes/calcdisp.cc new file mode 100644 index 0000000..dfb4310 --- /dev/null +++ b/tvision/classes/calcdisp.cc @@ -0,0 +1,291 @@ +/*------------------------------------------------------------*/ +/* */ +/* Turbo Vision 1.0 */ +/* Copyright (c) 1991 by Borland International */ +/* */ +/* Calc.cpp: TCalcDisplay member functions */ +/* */ +/*------------------------------------------------------------*/ + +/* + Modified by Salvador Eduardo Tropea + + I ported it from TV 1.03. + SET: Added locale support for the decimal point. + */ + +// SET: moved the standard headers before tv.h +#define Uses_string +#define Uses_stdlib +#define Uses_ctype +#define Uses_stdio // sprintf +#define Uses_nl_langinfo + +#define Uses_TKeys +#define Uses_TKeys_Extended +#define Uses_TRect +#define Uses_TEvent +#define Uses_TButton +#define Uses_TKeys +#define Uses_TDrawBuffer +#define Uses_TStreamableClass +#define Uses_TStreamable +#define Uses_TView +#define Uses_TPalette // SET: added +#define Uses_TCalcDisplay +#include + +#define cpCalcPalette "\x13" + +TCalcDisplay::TCalcDisplay(TRect& r) : TView ( r ) +{ + options |= ofSelectable; + eventMask = (evKeyboard | evBroadcast); + number = new char[DISPLAYLEN]; + clear(); + +} + +TCalcDisplay::~TCalcDisplay() +{ + DeleteArray(number); +} + +TPalette& TCalcDisplay::getPalette() const +{ + static TPalette palette( cpCalcPalette, sizeof(cpCalcPalette)-1 ); + return palette; +} + + +void TCalcDisplay::handleEvent(TEvent& event) +{ + // SET: Independent of the label + static char keys[]={'C','\x8','%','_','7','8','9','/','4','5','6', + '*','1','2','3','-','0','.','=','+'}; + TView::handleEvent(event); + + switch(event.what) + { + case evKeyboard: + calcKey(event.keyDown.charScan.charCode,event.keyDown.keyCode); + clearEvent(event); + break; + case evBroadcast: + if(event.message.command>=cmCalcButton && + event.message.command<=cmCalcButton+19) + { + calcKey(keys[event.message.command-cmCalcButton],0); + clearEvent(event); + } + break; + } +} + + +void TCalcDisplay::draw() +{ + char color = getColor(1); + int i; + TDrawBuffer buf; + + i = size.x - strlen(number) - 2; + buf.moveChar(0, ' ', color, size.x); + buf.moveChar(i, sign, color, 1); + buf.moveStr(i+1, number, color); + writeLine(0, 0, size.x, 1, buf); +} + + +void TCalcDisplay::error() +{ + status = csError; + strcpy(number, _("Error")); + sign = ' '; +} + + +void TCalcDisplay::clear() +{ + status = csFirst; + strcpy(number, "0"); + sign = ' '; + operate = '='; +} + + +void TCalcDisplay::setDisplay(double r) +{ + int len; + char str[64]; + //ostrstream displayStr( str, sizeof str );SET: Removed this waste + + if(r < 0.0) + { + sign = '-'; + sprintf(str,"%f",-r); + } + else + { + sprintf(str,"%f",r); + sign = ' '; + } + + len = strlen(str) - 1; // Minus one so we can use as an index. + + if(len > DISPLAYLEN) + error(); + else + strcpy(number, str); +} + + +void TCalcDisplay::checkFirst() +{ + if( status == csFirst) + { + status = csValid; + strcpy(number, "0"); + sign = ' '; + } +} + + +void TCalcDisplay::calcKey(unsigned char key, unsigned code) +{ + char stub[2] = " "; + double r; + char *decPoint=nl_langinfo(RADIXCHAR); + + switch(code) + { + case kbBackSpace: + key=8; + break; + case kbEsc: + key=27; + break; + case kbEnter: // Added by Mike + key=13; + break; + } + + key = (unsigned char)toupper(key); + if( status == csError && key != 'C') + key = ' '; + + switch(key) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + checkFirst(); + if (strlen(number) < 15) + { // 15 is max visible display length + if (!strcmp(number, "0")) + number[0] = '\0'; + stub[0] = key; + strcat(number, stub); + } + break; + + case 8: + case 27: + int len; + + checkFirst(); + if( (len = strlen(number)) == 1 ) + strcpy(number, "0"); + else + number[len-1] = '\0'; + break; + + case '_': // +- + sign = (sign == ' ') ? '-' : ' '; + break; + + case '.': + checkFirst(); + if(strstr(number, decPoint) == NULL) + strcat(number, decPoint); + break; + + case '+': case '-': case '*': case '/': + case '=': case '%': case 13: + if(status == csValid) + { + status = csFirst; + r = getDisplay() * ((sign == '-') ? -1.0 : 1.0); + if( key == '%' ) + { + if(operate == '+' || operate == '-') + r = (operand * r) / 100; + else + r /= 100; + } + switch( operate ) + { + case '+': + setDisplay(operand + r); + break; + + case '-': + setDisplay(operand - r); + break; + + case '*': + setDisplay(operand * r); + break; + + case '/': + if(r == 0) + error(); + else + setDisplay(operand / r); + break; + + } + } + operate = key; + operand = getDisplay() * ((sign == '-') ? -1.0 : 1.0); + break; + + case 'C': + clear(); + break; + + } + drawView(); +} + +#if !defined( NO_STREAM ) +TStreamable *TCalcDisplay::build() +{ + return new TCalcDisplay( streamableInit ); +} + +void TCalcDisplay::write( opstream& os ) +{ + TView::write( os ); + os.writeBytes(&status, sizeof(status)); + os.writeString(number); + os.writeByte(sign); + os.writeByte(operate); + os.writeBytes(&operand, sizeof(operand)); +} + + +void *TCalcDisplay::read( ipstream& is ) +{ + TView::read( is ); + number = new char[DISPLAYLEN]; + is.readBytes(&status, sizeof(status)); + is.readString(number, DISPLAYLEN); + sign = is.readByte(); + operate = is.readByte(); + is.readBytes(&operand, sizeof(operand)); + return this; +} +#endif // NO_STREAM + + + diff --git a/tvision/classes/calculat.cc b/tvision/classes/calculat.cc new file mode 100644 index 0000000..9204155 --- /dev/null +++ b/tvision/classes/calculat.cc @@ -0,0 +1,68 @@ +/*------------------------------------------------------------*/ +/* */ +/* Turbo Vision 1.0 */ +/* Copyright (c) 1991 by Borland International */ +/* */ +/* Calc.cpp: TCalculator constructor */ +/* */ +/*------------------------------------------------------------*/ + +/* + Modified by Salvador Eduardo Tropea + + I ported it from TV 1.03. + */ + +#define Uses_TKeys +#define Uses_TKeys_Extended +#define Uses_TRect +#define Uses_TEvent +#define Uses_TButton +#define Uses_TStreamableClass +#define Uses_TStreamable +#define Uses_TView +#define Uses_TDialog +#define Uses_TCalculator +#include + +// SET: Moved to the class, made ASCII +const char *TCalculator::keyChar[20] = + { "C", "<-", "%", "+-", + "7", "8", "9", "/", + "4", "5", "6", "*", + "1", "2", "3", "-", + "0", ".", "=", "+" + }; + +TCalculator::TCalculator() : + // SET: The display size must be satisfied + TWindowInit( &TCalculator::initFrame ), + TDialog( TRect(5, 3, 5+6+DISPLAYLEN, 18), __("Pocket Calculator") ) +{ + TView *tv; + TRect r; + + options |= ofFirstClick; + + // SET: enlarged buttons + for(int i = 0; i <= 19; i++) + { + int x = (i%4)*6+3; + int y = (i/4)*2+4; + r = TRect( x, y, x+6, y+2 ); + + tv = new TButton( r, keyChar[i], cmCalcButton+i, bfNormal | bfBroadcast ); + tv->options &= ~ofSelectable; + insert( tv ); + } + r = TRect( 3, 2, 3+DISPLAYLEN, 3 ); // SET, that's checked in setDisplay + insert( new TCalcDisplay(r) ); +} + +#if !defined( NO_STREAM ) +TStreamable *TCalculator::build() +{ + return new TCalculator( streamableInit ); +} +#endif + diff --git a/tvision/classes/codepage.cc b/tvision/classes/codepage.cc new file mode 100644 index 0000000..2b4eb37 --- /dev/null +++ b/tvision/classes/codepage.cc @@ -0,0 +1,2769 @@ +/**[txh]******************************************************************** + + Copyright 1996-2002 by Salvador Eduardo Tropea (SET) + This file is covered by the GPL license. + + Module: Code Page + Include: TVCodePage + Comments: + This module provides code page remapping needed to adapt the special +character to all the supported terminals.@p + It was originally designed for SETEdit and moved to Turbo Vision in 2002.@p + The internal encoding system maps the first 256 to CP 437.@p + Important: The Turbo Vision never had such a thing and this is completly +new code that affects a lot of TV components.@p + The mechanism used is similar to what Linux kernel uses, why? simple:@* +1) That's the most complex mechanism I found in all the targets so far.@* +2) This is quite crazy but at the same time flexible.@* + What's similar?@* + We have two maps. The first map is what Linux calls SFM (Screen Font Map). +It defines which internal codes are rendered by each font character (which +unicodes in Linux kernel). This is basically a map that describes the font. +This is the only map I had in the editor. The curScrCP variable holds the +ID of this map.@p + The second map is what the Linux kernel calls ACM (Application Charset +Map). This map describes how is the application data encoded, as an example: +how is encoded the text. It doesn't have to map one to one with the font, +and that's the complex stuff. For this reason this map is used to do an +"on-the-fly" remap before sending the characters to the screen. If this map +is identical to the SFM (maps 1 to 1 => what Linux calls trivial mapping) +we don't do the remap. The OnTheFlyRemapNeeded() and OnTheFlyRemap(uchar val) +are used for the remap. The curAppCP holds the ID of this map.@p + Is important to note that we don't do 8-bits -> ACM -> Unicode -> SFM -> +8-bits Screen like the Linux kernel does. We recode the application using +the ACM and if ACM!=SFM we use a simple table that makes: 8-bits -> 8-bits +Screen and if it isn't needed we just send the code to the screen.@p + I added a new code page to this: the input code page. In Linux systems +the input is supposed to be encoded in the ACM code page. In Windows systems +they can be different and they are asked with different calls. It can be +useful if you want to use an encoding different than the currently used by +the OS. You can change the screen encoding and load an appropriate font for +it, then you change the application code page and you can properly see +documents encoded in the target code page. But in order to edit them you +need to translate the codes that come from keyboard to the target code page. +That's a good use for the input code page. + +***************************************************************************/ + +#define Uses_stdio + +#define Uses_string +#define Uses_stdlib //bsearch +#define Uses_TStringCollection +#define Uses_TVCodePage + +// Classes we remap chars +#define Uses_TScreen +#define Uses_TRadioButtons +#define Uses_TMenuBox +#define Uses_TFrame +#define Uses_TIndicator +#define Uses_THistory +#define Uses_TColorSelector +#define Uses_TMonoSelector +#define Uses_TColorDialog +#define Uses_TInputLine +#define Uses_TStatusLine +#define Uses_TCheckBoxes +#define Uses_TScrollBar +#define Uses_TButton +#define Uses_TDirListBox +#define Uses_TFileEditor +#define Uses_TFileInfoPane +#define Uses_TDeskTop +#define Uses_TListViewer +#define Uses_TGKey + +// Needed for extra remaps +#define Uses_TProgram +#define Uses_TBackground +#define Uses_TEvent + +#include + +// List of supported code pages +TVCodePageCol *TVCodePage::CodePages=NULL; +// The full description of desired code page +ushort TVCodePage::CPTable[257]; +// toUpper/Lower and isAlpha tables +// I initialize it with some defaults in case they are needed before setting a +// code page, in this case only the ASCII range is really usable. The tables +// are for PC437. +uchar TVCodePage::AlphaTable[256]= +{ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05, + 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x00,0x00,0x00,0x00,0x00, + 0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00, + 0x05,0x03,0x03,0x01,0x03,0x01,0x03,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x05,0x05, + 0x05,0x03,0x05,0x01,0x03,0x01,0x01,0x01,0x01,0x05,0x05,0x00,0x00,0x00,0x00,0x00, + 0x01,0x01,0x01,0x01,0x03,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +}; +uchar TVCodePage::toUpperTable[256]= +{ + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, + 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,0x3F, + 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,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,0x7B,0x7C,0x7D,0x7E,0x7F, + 0x80,0x9A,0x90,0x83,0x8E,0x85,0x8F,0x80,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, + 0x90,0x92,0x92,0x93,0x99,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, + 0xA0,0xA1,0xA2,0xA3,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF +}; +uchar TVCodePage::toLowerTable[256]= +{ + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, + 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,0x3F, + 0x40,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,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, + 0x87,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x84,0x86, + 0x82,0x91,0x91,0x93,0x94,0x95,0x96,0x97,0x98,0x94,0x81,0x9B,0x9C,0x9D,0x9E,0x9F, + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA4,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF +}; +// Some Linux codepages aren't what they claim to be just to put the frames +// in a better place. +uchar TVCodePage::OnTheFlyMap[256]; +char TVCodePage::NeedsOnTheFlyRemap=0; +// This is a translation for the codes from keyboard. +uchar TVCodePage::OnTheFlyInpMap[256]; +char TVCodePage::NeedsOnTheFlyInpRemap=0; +// Current code pages +// The source code is encoded in CP 437 +int TVCodePage::curAppCP=437; +// We assume the screen is also CP 437, if it isn't true the driver will inform it. +int TVCodePage::curScrCP=437; +// What we get from the keyboard +int TVCodePage::curInpCP=437; +// Default values suggested by the current driver +int TVCodePage::defAppCP=437; +int TVCodePage::defScrCP=437; +int TVCodePage::defInpCP=437; +// User provided function to call each time we change the code page. +// This is called before sending a broadcast. +void (*TVCodePage::UserHook)(ushort *map)=NULL; +// Table used to find something that can represent an absent code. +// This is for CP 437 use +uchar TVCodePage::Similar[]= +{ + ' ', '@', '@', '*', '*', '*', '*', '*', // 0- 7 + 0x04, 'o',0xDB, 'M', 'F', 'd', 'd', '*', // 8- 15 + 0x1A,0x1B, 'I',0xBA, 'P', 'S',0xDC,0x12, // 16- 23 + '^', 'V', '>', '<',0xC0, '-',0x18,0x19, // 24- 31 + ' ', '!', '"', '#', '$', '%', '&','\'', // 32- 39 + '(', ')', '*', '+', ',', '-', '.', '/', // 40- 47 + '0', '1', '2', '3', '4', '5', '6', '7', // 48- 55 + '8', '9', ':', ';', '<', '=', '>', '?', // 56- 63 + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', // 64- 71 + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', // 72- 79 + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', // 80- 87 + 'X', 'Y', 'Z', '[','\\', ']', '^', '_', // 88- 95 + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', // 96-103 + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', // 104-111 + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', // 112-119 + 'x', 'y', 'z', '{', '|', '}', '~', '^', // 120-127 + 'C', 'u', 'e', 'a', 'a', 'a', 'a', 'c', // 128-135 + 'e', 'e', 'e', 'i', 'i', 'i', 'A', 'A', // 136-143 + 'E', 'a', 'A', 'o', 'o', 'o', 'u', 'u', // 144-151 + 'y', 'O', 'U', 'c', 'L', 'Y', 'P', 'f', // 152-159 + 'a', 'i', 'o', 'u', 'n', 'N', 'a', 'o', // 160-167 + '?',0xDA,0xBF, '*', '*', '!', '<', '>', // 168-175 + ' ', ' ', ' ', '|',0xB3,0xB3,0xBA,0xBF, // 176-183 + 0xBF,0xBA,0xB3,0xBF,0xD9,0xD9,0xD9, '*', // 184-191 + '*',0xC4,0xC4,0xB3, '-', '+',0xB3,0xBA, // 192-199 + 0xC0,0xDA,0xCD,0xCD,0xBA,0xC4,0xBA,0xCD, // 200-207 + 0xC4,0xCD,0xC4,0xC0,0xC0,0xDA,0xDA,0xC5, // 208-215 + 0xC5, '*', '*', ' ', ' ', ' ', ' ', ' ', // 216-223 + 'a', 'B', 'G', 'p', 'S', 's', 'm', 't', // 224-231 + 'F', 'f', 'O', 'd', 'i', 'o', 'e', 'U', // 232-239 + '=', '+', '>', '<',0xDA,0xD9, '/', '~', // 240-247 + 'o', '.', '.', 'V', 'n', '2', '*', ' ', // 248-255 +}; +// This table is used to reduce any of our codes into a similar one when absent. +// It covers all the known symbols not covered by Similar and if the value doesn't +// exist in the current code page you must enter in the table again until you get +// an ASCII value. +ushort TVCodePage::Similar2[]= +{ + 'c','l','n','r','s','y','z', // 0x100-0x106 small acute + 'A','C','I','L','N','O','R','S','U','Y','Z', // 0x107-0x111 capital acute + 'U', // 0x112 double acute + 'A','E','I','O','U', // 0x113-0x117 capital grave + 'E','I', // 0x118-0x119 capital diaeresis + 'U','u', // 0x11A-0x11B ring above + 'a','o','u','A','O', // 0x11C-0x120 tilde/double acute + 'A','E','I','O','U', // 0x121-0x125 capital circumflex + 'c','n','r','s','z','C','D','E','N','R','S','T','Z', // 0x126-0x132 caron + 's','t','S','T', // 0x133-0x136 cedilla + 'a','e','A','E', // 0x137-0x13A ogonek + 'z','Z', // 0x13B-013C dot above + 'l','o','L','O','d', // 0x13D-0x141 stroke + 0x141, // 0x142 latin small letter eth + 'D', // 0x143 stroke + 'd','l','t','L', // 0x144-0x147 caron + 'a','e','A', // 0x14-0x14A breve + '$', // 0x14B currency sign (o four feets), I guess that's a good fall back + // specially thinking all people understand $ as money + 'P','p', // 0x14C-0x14D thorn (Icelandic) sorry I know that's arbitrary and + // silly. Anyone have a better choice? + '*', // 14E multiplication sign + 'R', // 14F registered sign (R) + 'c', // 150 copyright sign (c) + 'i', // 151 latin small letter dotless i + '|', // 152 broken bar (|) + '_', // 153 macron (_ but high) + '\'',// 154 acute accent + '-', // 155 soft hyphen (- long) + '_', // 156 double low line (_ double) + '3', // 157 vulgar fraction three quarters + ',', // 158 cedilla + '"', // 159 diaeresis (di‚resis, umlaut) + '1', // 15a superscript one + '3', // 15b superscript three + '"', // 15c double acute accent + ';', // 15d ogonek (cedilla inv.) + '<', // 15e caron (mandarin chinese third tone) + '(', // 15f breve + '.', // 160 dot above (mandarin chinese light tone) + 'o','O', // 0x161-0x162 double acute + 0x145,0x147,0x146,'e',0x144, // 0x163-0x167 caron, fall back to the other representation + // 0x168 + 'A','B','G','D','Z','I','J','L','P','U','F','C','C','S','S','"','Y','"', + 'E','U','A', // 0x168-0x17C Cyrillic capitals group 1 + 'b','v','g','d','z','z','i','j','k','l','m','n','p','t','u','f','c','c', + 's','s','\'','y','\'','e','u','a', // 0x17D-0x196 Cyrillic smalls group 1 + 'I','i', // 0x197-0x198 ukrainian ie + 'Z', // 0x199 capital letter ze + ' ', // 0x19A free slot + 'N', // 0x19B number + // ISO-5 cyrillics: + 'D', // 19C capital letter dje (Serbocroatian) (¢)-5 + 'd', // 19D small letter dje (Serbocroatian) (ò)-5 + 'G', // 19E capital letter gje (£)-5 + 'g', // 19F small letter gje (ó)-5 + 'Y', // 1A0 capital letter yi (Ukrainian) (¦)-5 + 'L', // 1A1 capital letter lje (©)-5 + 'l', // 1A2 small letter lje (ù)-5 + 'N', // 1A3 capital letter nje (ª)-5 + 'n', // 1A4 small letter nje (ú)-5 + 'T', // 1A5 capital letter tshe (Serbocroatian) («)-5 + 't', // 1A6 small letter tshe (Serbocroatian) (û)-5 + 'K', // 1A7 capital letter kje (¬)-5 + 'k', // 1A8 small letter kje (ü)-5 + 'V', // 1A9 capital letter short U (Byelorussian) (®)-5 + 'v', // 1AA small letter short U (Byelorussian) (þ)-5 + 'D', // 1AB capital letter dzhe (¯)-5 + 'd', // 1AC small letter dzhe (ÿ)-5 + // Windows CP 1251 (russian) + '"', // 1AD double low-9 quotation mark („)-cp1251 + '.', // 1AE horizontal ellipsis (…)-cp1251 + '|', // 1AF dagger (†)-cp1251 + '|', // 1B0 double dagger (‡)-cp1251 + '%', // 1B1 per mille sign (‰)-cp1251 + '"', // 1B2 left double quotation mark (“)-cp1251 + '"', // 1B3 right double quotation mark (”)-cp1251 + 'T', // 1B4 trade mark sign (™)-cp1251 + 0x16A, // 1B5 cyrillic capital letter ghe with upturn, default to GHE (¥)-cp1251 + 0x17F, // 1B6 cyrillic small letter ghe with upturn, default to ghe (´)-cp1251 + '?', // 1B7 That's a ? inside a circle, it means the character is unknown + 'O', // 1B8 latin capital ligature OE + 'o', // 1B9 latin small ligature oe + // Idiot ISO-1 font found in Linux, only to break standards and annoy people + 't', // 1BA symbol for horizontal tabulation + 'f', // 1BB symbol for form feed + 'c', // 1BC symbol for carriage return + 'l', // 1BD symbol for line feed + 'n', // 1BE symbol for newline + 'v', // 1BF symbol for vertical tabulation + '#', // 1C0 not equal to + 'v', // 1C1 downwards arrow with corner leftwards + 'Y', // 1C2 latin capital letter y with diaeresis + ' ', // 1C3 free + 0xB3,// 1C4 box drawings light up ()-1 linux + 0xC4,// 1C5 box drawings light right (‚)-1 linux + 0xB3,// 1C6 box drawings light down („)-1 linux + 0xC4,// 1C7 box drawings light left (ˆ)-1 linux + ' ', // 1C8 free + 0xBA,// 1C9 box drawings heavy up (‘)-1 linux + 0xCD,// 1CA box drawings heavy right (’)-1 linux + 0xBA,// 1CB box drawings heavy down (”)-1 linux + 0xCD,// 1CC box drawings heavy left (˜)-1 linux + 0x1A8,//1CD latin small letter kra + 'N','n', // Latin letter eng + // Circumflex 1D0-1DD + 'C','c','G','g','H','h','J','j','S','s','W','w','Y','y', + // Dot above 1DE-1EF + 'B','b','C','c','D','d','F','f','g','I','M','m','P','p','S','s','T','t', + // Macron 1F0-1F7 + 'E','e','I','i','O','o','U','u', + // Breve 1F8-1FD + 'G','g','I','i','U','u', + // Cedilla 1FE-205 + 'G','g','K','k','N','n','R','r', + // Tilde 206-209 + 'I','i','U','u', + // Ogonek 20A-20F + 'I','i','U','u','W','w', + 'Y',// 210 0x1EF2 LATIN CAPITAL LETTER Y WITH GRAVE + 'y',// 211 0x1EF3 LATIN SMALL LETTER Y WITH GRAVE + 'W',// 212 0x1E82 LATIN CAPITAL LETTER W WITH ACUTE + 'w',// 213 0x1E83 LATIN SMALL LETTER W WITH ACUTE + 'W',// 214 0x1E84 LATIN CAPITAL LETTER W WITH DIAERESIS + 'w',// 215 0x1E85 LATIN SMALL LETTER W WITH DIAERESIS + 'H',// 216 0x0126 LATIN CAPITAL LETTER H WITH STROKE + 'h',// 217 0x0127 LATIN SMALL LETTER H WITH STROKE + 'T',// 218 0x0166 LATIN CAPITAL LETTER T WITH STROKE + 't',// 219 0x0167 LATIN SMALL LETTER T WITH STROKE + 'O',// 21A 0x01A0 LATIN CAPITAL LETTER O WITH HORN + 'o',// 21B 0x01A1 LATIN SMALL LETTER O WITH HORN + 'U',// 21C 0x01AF LATIN CAPITAL LETTER U WITH HORN + 'u',// 21D 0x01B0 LATIN SMALL LETTER U WITH HORN + 'E',// 21E 0x0116 LATIN CAPITAL LETTER E WITH DOT ABOVE + 'e',// 21F 0x0117 LATIN SMALL LETTER E WITH DOT ABOVE + 'L',// 220 0x013B LATIN CAPITAL LETTER L WITH CEDILLA + 'l',// 221 0x013C LATIN SMALL LETTER L WITH CEDILLA + // Greek smalls 222-22F + 'g','z','h','u','i','l','n','j','r','s','y','x','c','v', + // Greek capitals 230-233 + 'D','J','P','C', + // Greek accented + 0x159,// 234 0x0385 GREEK DIALYTIKA TONOS => diaeresis + 0xE0, // 235 0x03AC GREEK SMALL LETTER ALPHA WITH TONOS => alpha + 0xEE, // 236 0x03AD GREEK SMALL LETTER EPSILON WITH TONOS => epsilon + 0x224,// 237 0x03AE GREEK SMALL LETTER ETA WITH TONOS => eta + 0x226,// 238 0x03AF GREEK SMALL LETTER IOTA WITH TONOS => iota + 'o', // 239 0x03CC GREEK SMALL LETTER OMICRON WITH TONOS => omicron + 0x22C,// 23A 0x03CD GREEK SMALL LETTER UPSILON WITH TONOS => upsilon + 0x22F,// 23B 0x03CE GREEK SMALL LETTER OMEGA WITH TONOS => omega + 'A', // 23C 0x0386 GREEK CAPITAL LETTER ALPHA WITH TONOS + 'E', // 23D 0x0388 GREEK CAPITAL LETTER EPSILON WITH TONOS + 'H', // 23E 0x0389 GREEK CAPITAL LETTER ETA WITH TONOS + 'I', // 23F 0x038A GREEK CAPITAL LETTER IOTA WITH TONOS + 'O', // 240 0x038C GREEK CAPITAL LETTER OMICRON WITH TONOS + 'Y', // 241 0x038E GREEK CAPITAL LETTER UPSILON WITH TONOS + 0xEA, // 242 0x038F GREEK CAPITAL LETTER OMEGA WITH TONOS => omega + 0x226,// 243 0x03CA GREEK SMALL LETTER IOTA WITH DIALYTIKA => iota + 0x22C,// 244 0x03CB GREEK SMALL LETTER UPSILON WITH DIALYTIKA => upsilon + 0x238,// 245 0x0390 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS => iota + tonos + 0x23A,// 246 0x03B0 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS => upsilon + tonos + 'L', // 247 GREEK CAPITAL LETTER LAMDA + 'a','A', // 248/9 LATIN LETTER A WITH MACRON + 'G', // 24A LATIN CAPITAL LETTER G WITH DOT ABOVE + 'E', // 24B Euro Sign + // Cyrillics that are identical to latin letters + 'B','E','K','M','H','O','P','C','T','X','a','e','o','p','c','x', + 137,280,'s','i',139,'j',281,'J','S', + // Greeks that are identical to latin letters + 0xE1,0x185,0xE6,'o','A','B','E','Z','H','I','K','M','N','O','P','T','Y','X', + 0x119,0x1C2, +}; + + +// We use an internal code. This is currently a 16 bits code. +// The ammount of defined symbols: [0 ... maxSymbolDefined-1] +const unsigned maxSymbolDefined=632+1; + +// Helper to sort Unicode tables or search in sorted Unicode tables +static +int compare(const void *v1, const void *v2) +{ + stIntCodePairs *p1=(stIntCodePairs *)v1; + stIntCodePairs *p2=(stIntCodePairs *)v2; + return (p1->unicode>p2->unicode)-(p1->unicodeunicode); +} + +// This is what usually call: TNoCaseNoOwnerStringCollection, but isn't +// available in TV, yet +class TVCodePageCol : public TStringCollection +{ +public: + TVCodePageCol(ccIndex aLimit, ccIndex aDelta) : + TStringCollection(aLimit,aDelta) {}; + int compare(void *s1,void *s2) { return strcasecmp((char *)s1,(char *)s2); }; + void freeItem(void *) {}; +}; + +/***************************************************************************** + Defined code pages sorted by ID: + +Name ID +PC 437 ASCII ext. 437 +PC 737 Greek 737 +PC 775 DOS Baltic Rim 775 +PC 850 Latin 1 850 +PC 852 Latin 2 852 +PC 855 Russian 2 855 +PC 857 Turkish 857 +PC 860 Portuguese 860 +PC 861 Icelandic 861 +PC 863 French 863 +PC 865 Nordic 865 +PC 866 Russian 866 +PC 869 Greek 2 869 +CP 1250 Win Latin 2 1250 +CP 1251 Win Russian 1251 +CP 1252 Win Latin 1 1252 +CP 1253 Win Greek 1253 +CP 1254 Win Turkish 1254 +CP 1257 Win Baltic 1257 +Mac Cyr. CP 10007 10007 +ISO 8859-1 Latin 1 88791 +ISO 8859-2 Latin 2 88792 +ISO 8859-3 Latin 3 88593 +ISO 8859-4 Latin 4 88594 +ISO 8859-5 Russian 88595 +ISO 8859-7 Greek 88597 +ISO 8859-9 88599 +ISO Latin 1 (Linux) 885901 +ISO Latin 1u(Linux) 885911 +ISO 8859-14 885914 +ISO 8859-15 Icelan. 885915 +ISO Latin 2 (Linux) 885920 +ISO Latin 2u(Linux) 885921 +ISO Latin 2 (Sun) 885922 +ISO Latin 2+Euro (Linux) 885923 +KOI-8r (Russian) 100000 +KOI-8 with CRL/NMSU 100001 +Mac OS Ukrainian 100072 +Osnovnoj Variant Russian 885951 +Alternativnyj Variant RU 885952 +U-code Russian 885953 +Mazovia (polish) 1000000 +ISO 5427 ISO-IR-37 KOI-7 3604494 +ECMA-Cyr.ISO-IR-111 17891342 +JUS_I.B1.003-SERB ISOIR146 21364750 +JUS_I.B1.003-MAC ISO-IR-147 21430286 +Cyrillic ISO-IR-153 22216718 + +*****************************************************************************/ + +// PC437 doesn't need traslation, they are the first 256 chars. +CodePage TVCodePage::stPC437= +{ "PC 437 ASCII ext.", + 437, + { 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 }, + "‚†„Ž‡€š‘’”™¤¥", + "ƒ…ˆ‰Š‹Œ“•–—˜ ¡¢£á",0,0 +}; + +CodePage TVCodePage::stPC737= +{ "PC 737 Greek", + 737, + { 617,618,226,560,619,620,621,233,622,623,583,624,625,561,626,562, + 627,228,628,629,232,630,563,234,224,613,546,235,238,547,548,549, + 550,614,551,615,552,553,616,227,554,229,555,231,556,237,557,558, + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 559,565,566,567,579,568,569,570,580,571,572,573,574,575,576,577, + 578,241,342,343,631,632,246,344,248,345,250,346,347,253,254,255 }, + "˜€™¯–›ƒœ„­”š‚ž† ˆ¥¡‰¢Š£‹¤Œ¦Ž§¨©‘«’à—ª‘®•¬“…áêâëãìåíæîéðçïäôèõ", + "Ÿ",0,0 +}; + +CodePage TVCodePage::stPC775= +{ "PC 775 DOS Baltic Rim", + 775, + { 264,129,130,584,132,511,134,256,317,497,516,517,499,273,142,143, + 144,145,146,501,148,510,155,270,260,153,154,318,156,320,334,331, + 585,498,162,316,315,262,435,338,336,335,170,171,172,319,174,175, + 176,177,178,179,180,313,299,314,542,185,186,187,188,522,304,191, + 192,193,194,195,196,197,524,502,200,201,202,203,204,205,206,306, + 311,294,312,543,523,297,525,503,298,217,218,219,220,221,222,223, + 268,225,500,267,285,288,230,258,512,513,544,545,515,496,514, 39, + 341,241,434,343, 20, 21,246,429,248,249,250,346,347,253,254,255 + }, + "‡€‹Šš‚ƒ „Ž…•†ˆ­‰íŒ¡¥‘’“â”™˜—›¢à¤£ÐµÑ¶Ò·Ó¸Ô½Õ¾ÖÆ×ÇØÏçãäåéèëêìî", + "áæ",0,0 +}; + +CodePage TVCodePage::stPC850= +{ "PC 850 Latin 1", + 850, + { 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151,152,153,154,318,156,320,334,159, + 160,161,162,163,164,165,166,167,168,335,170,171,172,173,174,175, + 176,177,178,179,180,263,289,275,336,185,186,187,188,155,157,191, + 192,193,194,195,196,197,284,287,200,201,202,203,204,205,206,331, + 321,323,290,280,276,337,265,291,281,217,218,219,220,338,277,223, + 268,225,292,278,285,288,230,332,333,271,293,279,261,272,339,340, + 341,241,342,343, 20, 21,246,344,248,345,250,346,347,253,254,255 }, + "‡€š‚ƒ¶„Ž…·†ˆÒ‰ÓŠÔ‹ØŒ×Þ‘’“â”™•ã–ê—ë› µ¡Ö¢à£é¤¥ÆÇÐÑäåçèìí", + "˜ÏÕáæ",0,0 +}; + +CodePage TVCodePage::stPC852= +{ "PC 852 Latin 2", + 852, + { 128,129,130,131,132,282,256,135,317,137,354,353,140,273,142,264, + 144,266,257,147,148,327,325,270,260,153,154,305,326,319,334,294, + 160,161,162,163,313,311,306,298,314,312, 0,262,299,307,174,175, + 176,177,178,179,180,263,289,301,309,185,186,187,188,316,315,191, + 192,193,194,195,196,197,330,328,200,201,202,203,204,205,206,331, + 321,323,300,280,324,302,265,291,358,217,218,219,220,310,283,223, + 268,225,292,267,258,295,304,297,269,271,259,274,261,272,308,340, + 341,348,349,350,351, 21,246,344,248,345,352,286,303,296,254,255 }, + "‡€š‚ƒ¶„Ž…Þ†ˆ‰Ó‹ŠŒ×«’‘“â”™–•˜—Ÿ¬ µ¡Ö¢à£é¥¤§¦©¨­¸Ø·¾½ÇÆÐÑåÕîÝäãçæêèûëìíýü", + "›œÏÒÔá",0,0 +}; + +// PC855 Russian DOS code page +CodePage TVCodePage::stPC855= +{ "PC 855 Russian 2", + 855, + { 413,412,415,414,604,605,408,407,606,612,607,610,608,416,609,611, + 418,417,420,419,422,421,424,423,426,425,428,427,405,379,401,375, + 598,360,381,361,397,371,384,363,599,589,396,370,383,362,174,175, + 176,177,178,179,180,603,597,387,365,185,186,187,188,388,366,191, + 192,193,194,195,196,197,389,590,200,201,202,203,204,205,206,331, + 390,367,391,591,392,592,600,593,393,217,218,219,220,368,406,223, + 380,601,594,602,595,394,596,395,369,385,364,382,588,403,377,411, + 341,402,376,386,409,399,373,404,378,400,374,398,372, 21,254,255 }, + "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­µ¶·¸½¾ÆÇÐÑÒÓÔÕÖ×ØÝÞàáâãäåæçèéêëìíîñòóôõö÷øùúûü", + "",0,0 +}; + +CodePage TVCodePage::stPC857= +{ "PC 857 Turkish", + 857, + { 128,129,130,131,132,133,134,135,136,137,138,139,140,337,142,143, + 144,145,146,147,148,149,150,151,487,153,154,318,156,320,309,307, + 160,161,162,163,164,165,504,505,168,335,170,171,172,173,174,175, + 176,177,178,179,180,263,289,275,336,185,186,187,188,155,157,191, + 192,193,194,195,196,197,284,287,200,201,202,203,204,205,206,331, + 167,166,290,280,276,276,265,291,281,217,218,219,220,338,277,223, + 268,225,292,278,285,288,230,230,334,271,293,279,141,152,339,340, + 341,241,241,343, 20, 21,246,344,248,345,250,346,347,253,254,255 }, + "‡€š‚ƒ¶„Ž…·†ˆÒ‰ÓŠÔ‹ØŒ×˜‘’“â”™•ã–ê—뛟ž µ¡Ö£é¤¥§¦ÆÇ¢àÞìäå", + "Õáæçí",0,0 +}; + +CodePage TVCodePage::stPC860= +{ "PC 860 Portuguese", + 860, + { 128,129,130,131,284,133,263,135,136,290,138,265,140,141,287,289, + 144,275,276,147,285,149,271,151,277,288,154,155,156,279,158,268, + 160,161,162,163,164,165,166,167,168,278,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 }, + "‡€š‚ƒ„Ž…‘ †ˆ‰Š’¡‹“Œ˜”™•©£–—¢Ÿ¤¥", + "á",0,0 +}; + +CodePage TVCodePage::stPC861= +{ "PC 861 Icelandic", + 861, + { 128,129,130,131,132,133,134,135,136,137,138,323,322,333,142,143, + 144,145,146,147,148,332,150,272,261,153,154,318,156,320,158,159, + 160,161,162,163,263,265,268,271,168,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 }, + "š‚„Ž†‡€Œ‹•‘’”™˜—› ¤¡¥¢¦£§", + "ƒ…ˆ‰Š“–àáâãåäæçèéêëíîŸ",0,0 +}; + +CodePage TVCodePage::stPC863= +{ "PC 863 French", + 863, + { 128,129,130,131,289,133, 20,135,136,137,138,139,140,342,275, 21, + 144,276,290,147,280,281,150,151,331,292,154,155,156,279,158,159, + 338,340,162,163,345,344,347,339,291,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 }, + "‡€š‚ƒ„…Žˆ’‰”Š‘‹•Œ¨“™–ž—", + "˜¢£á",0,0 +}; + +CodePage TVCodePage::stPC865= +{ "PC 865 Nordic", + 865, + { 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151,152,153,154,318,156,320,158,159, + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,331, + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 }, + "‡€š›‚„Ž†‘’¤¥”™", + "ƒ…ˆ‰Š‹Œ“•–—˜ ¡¢£¯á",0,0 +}; + +CodePage TVCodePage::stPC869= +{ "PC 869 Greek 2", + 869, + { 0x20,0x20,0x20,0x20,0x20,0x20,572,572,250,170,338, 96, 39,573,341,574, + 575,631,576,576,576,577,632,336,578,253,347,565,156,566,567,568, + 579,581,569,570,617,618,226,560,619,620,621,171,233,622,174,175, + 176,177,178,179,180,623,583,624,625,185,186,187,188,561,626,191, + 192,193,194,195,196,197,562,627,200,201,202,203,204,205,206,228, + 628,629,232,630,563,234,224,613,546,217,218,219,220,235,238,223, + 547,548,549,550,614,551,615,552,553,616,227,554,229,555,231,340, + 341,241,556,237,557, 21,558,564,248,345,559,580,582,571,254,255 }, + "›†žŸ ‘¢’£•û–ý˜Ö¤×¥Ø¦Ý§Þ¨à©áªâ¬ã­äµå¶æ·ç¸è½é¾êÆëÇìÏíÏîÐòÑóÒôÓöÔúÕ", + "¡ü",0,0 +}; + +CodePage TVCodePage::ISO8879_1= +{ "ISO 8859-1 Latin 1", + 88791, + { 218,196,191,192,217,179,195,180,194,193,197,201,205,187,200,188, + 186,199,182,209,207,219,178,177,176,223,220,222,221,254,254,254, + 32,173,155,156, 36,157,338, 21,345,336,166,174,170,341,335,341, + 248,241,253,347,340,230, 20,249,344,346,167,175,172,171,343,168, + 275,263,289,287,142,143,146,128,276,144,290,280,277,265,291,281, + 323,165,278,268,292,288,153,334,320,279,271,293,154,272,333,225, + 133,160,131,284,132,134,145,135,138,130,136,137,141,161,140,139, + 321,164,149,162,147,285,148,246,318,151,163,150,129,261,332,152 }, + "àÀáÁâÂãÃäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏðÐñÑòÒóÓôÔõÕöÖøØùÙúÚûÛüÜýÝþÞ", + "µßÿ",0,0 +}; + +ushort TVCodePage::LowCrazyCharsRemaped[] = +{ 439,247,440,441, 4,442,443,444,445,176,177,178,219,220,223,221, + 222,446,447,242,243,448, 17, 16, 24, 25, 26, 27, 18, 29,449/*447*/,227, // 449 in lat1.sfm + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,450 }; + + +CodePage TVCodePage::ISO8859_1_Lat1= +{ "ISO Latin 1 (Linux)", + 885901, + { 451,452,453,192,454,179,218,195,455,217,196,193,191,180,194,197, + 456,457,458,200,459,186,201,204,460,188,205,202,187,185,203,206, + 255,173,155,156, 36,157,338, 21,345,336,166,174,170,341,335,341, + 248,241,253,347,340,230, 20,249,344,346,167,175,172,171,343,168, + 275,263,289,287,142,143,146,128,276,144,290,280,277,265,291,281, + 323,165,278,268,292,288,153,334,320,279,271,293,154,272,333,225, + 133,160,131,284,132,134,145,135,138,130,136,137,141,161,140,139, + 321,164,149,162,147,285,148,246,318,151,163,150,129,261,332,152 }, + "àÀáÁâÂãÃäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏðÐñÑòÒóÓôÔõÕöÖøØùÙúÚûÛüÜÿýÝþÞ", + "µß", + 128,LowCrazyCharsRemaped +}; + +CodePage TVCodePage::ISO8859_1u_Lat1= +{ "ISO Latin 1u(Linux)", + 885911, + { 275,263,289,287,142,143,146,128,276,144,290,280,277,265,291,281, + 323,165,278,268,292,288,153,334,320,279,271,293,154,272,333,225, + 32,173,155,156, 36,157,338, 21,345,336,166,174,170,341,335,341, + 248,241,253,347,340,230, 20,249,344,346,167,175,172,171,343,168, + 451,452,453,192,454,179,218,195,455,217,196,193,191,180,194,197, + 456,457,458,200,459,186,201,204,460,188,205,202,187,185,203,206, + 133,160,131,284,132,134,145,135,138,130,136,137,141,161,140,139, + 321,164,149,162,147,285,148,246,318,151,163,150,129,261,332,152 }, + "à€áâ‚ãƒä„å…æ†ç‡èˆé‰êŠë‹ìŒíîŽïðñ‘ò’ó“ô”õ•ö–ø˜ù™úšû›üœÿýþž", + "µŸ", + 128,LowCrazyCharsRemaped +}; + +CodePage TVCodePage::ISO8879_2= +{ "ISO 8859-2 Latin 2", + 88792, + { 218,196,191,192,217,179,195,180,194,193,197,201,205,187,200,188, + 186,199,182,209,207,219,178,177,176,223,220,222,221,254,254,254, + 255,313,351,319,331,356,270, 21,345,304,309,305,273,341,306,316, + 248,311,349,317,340,325,260,350,344,297,307,326,262,348,298,315, + 269,263,289,330,142,266,264,128,299,144,314,280,301,265,291,300, + 323,267,302,268,292,354,153,334,303,282,271,274,154,272,310,225, + 259,160,131,328,132,257,256,135,294,130,312,137,358,161,140,324, + 321,258,295,162,147,353,148,246,296,283,163,286,129,261,308,352 }, + "±¡³£µ¥¶¦¹©ºª»«¼¬¾®¿¯àÀáÁâÂãÃäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏðÐñÑòÒóÓôÔõÕöÖøØùÙúÚûÛüÜýÝþÞ", + "",0,0 +}; + +CodePage TVCodePage::ISO8859_2_Lat2= +{ "ISO Latin 2 (Linux)", + 885920, + {451,452,453,192,454,179,218,195,455,217,196,193,191,180,194,197, + 456,457,458,200,459,186,201,204,460,188,205,202,187,185,203,206, + 255,313,351,319,331,356,270, 21,345,304,309,305,273,341,306,316, + 248,311,349,317,340,325,260,350,344,297,307,326,262,348,298,315, + 269,263,289,330,142,266,264,128,299,144,314,280,301,265,291,300, + 323,267,302,268,292,354,153,334,303,282,271,274,154,272,310,225, + 259,160,131,328,132,257,256,135,294,130,312,137,358,161,140,324, + 321,258,295,162,147,353,148,246,296,283,163,286,129,261,308,352 }, + "±¡³£µ¥¶¦¹©ºª»«¼¬¾®¿¯àÀáÁâÂãÃäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏðÐñÑòÒóÓôÔõÕöÖøØùÙúÚûÛüÜýÝþÞ", + "",0,0 +}; + +CodePage TVCodePage::ISO8859_2u_Lat2= +{ "ISO Latin 2u(Linux)", + 885921, + {269,263,289,330,142,266,264,128,299,144,314,280,301,265,291,300, + 323,267,302,268,292,354,153,334,303,282,271,274,154,272,310,225, + 255,313,351,319,331,356,270, 21,345,304,309,305,273,341,306,316, + 248,311,349,317,340,325,260,350,344,297,307,326,262,348,298,315, + 451,452,453,192,454,179,218,195,455,217,196,193,191,180,194,197, + 456,457,458,200,459,186,201,204,460,188,205,202,187,185,203,206, + 259,160,131,328,132,257,256,135,294,130,312,137,358,161,140,324, + 321,258,295,162,147,353,148,246,296,283,163,286,129,261,308,352 }, + "±¡³£µ¥¶¦¹©ºª»«¼¬¾®¿¯à€áâ‚ãƒä„å…æ†ç‡èˆé‰êŠë‹ìŒíîŽïðñ‘ò’ó“ô”õ•ö–ø˜ù™úšû›üœýþž", + "",0,0 +}; + +// This code page have the Euro +CodePage TVCodePage::ISO8859_2_Sun= +{ "ISO Latin 2 (Sun)", + 885922, + {255,313,351,319,331,356,270, 21,345,304,309,305,273,341,306,316, + 248,311,349,317,340,325,260,350,344,297,307,326,262,348,298,315, + 269,263,289,330,142,266,264,128,299,144,314,280,301,265,291,300, + 176,177,178,179,180,323,267,302,268,185,186,187,188,292,354,191, + 192,193,194,195,196,197,153,334,200,201,202,203,204,205,206,303, + 282,271,274,154,272,310,225,587,216,217,218,219,220,221,222,223, + 259,160,131,328,132,257,256,135,294,130,312,137,358,161,140,324, + 321,258,295,162,147,353,148,246,296,283,163,286,129,261,308,352 }, + "‘“ƒ•…–†–‰šŠ›‹œŒžŽŸà á¡â¢ã£ä¤å¥æ¦ç§è¨é©êªë«ì¬í­î®ï¯ðµñ¶ó¸ô½õ¾öÆøÏùÐúÑûÒüÓýÔþÕ", + "Ö",0,0 +}; + +CodePage TVCodePage::ISO8859_2e_Lat2= +{ "ISO Latin 2+Euro (Linux)", + 885923, + {451,452,453,192,454,179,218,195,455,217,196,193,191,180,194,197, + 456,457,458,200,459,186,201,204,460,188,205,202,187,185,203,206, + 255,313,351,319,587,356,270, 21,345,304,309,305,273,341,306,316, + 248,311,349,317,340,325,260,350,344,297,307,326,262,348,298,315, + 269,263,289,330,142,266,264,128,299,144,314,280,301,265,291,300, + 323,267,302,268,292,354,153,334,303,282,271,274,154,272,310,225, + 259,160,131,328,132,257,256,135,294,130,312,137,358,161,140,324, + 321,258,295,162,147,353,148,246,296,283,163,286,129,261,308,352 }, + "±¡³£µ¥¶¦¹©ºª»«¼¬¾®¿¯àÀáÁâÂãÃäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏðÐñÑòÒóÓôÔõÕöÖøØùÙúÚûÛüÜýÝþÞ", + "",0,0 +}; + +CodePage TVCodePage::ISO8859_3= +{ "ISO 8859-3 Latin 3", + 88593, + { 218,196,191,192,217,179,195,180,194,193,197,201,205,187,200,188, + 186,199,182,209,207,219,178,177,176,223,220,222,221,254,254,254, + 255,534,351,156,331,0x20,468, 21,345,487,309,504,470,341,0x20,316, + 248,535,253,347,340,230,469,250,344,337,307,505,471,171,0x20,315, + 275,263,289,0x20,142,480,464,128,276,144,290,280,277,265,291,281, + 0x20,165,278,268,292,586,153,334,466,279,271,293,154,508,472,225, + 133,160,131,0x20,132,481,465,135,138,130,136,137,141,161,140,139, + 0x20,164,149,162,147,486,148,246,467,151,163,150,129,509,473,352 + }, + "±¡¶¦¹©ºª»«¼¬¿¯àÀáÁâÂäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏñÑòÒóÓôÔõÕöÖøØùÙúÚûÛüÜýÝþÞ", + "ßµ",0,0 +}; + +CodePage TVCodePage::ISO8859_4= +{ "ISO 8859-4 Latin 4", + 88594, + { 218,196,191,192,217,179,195,180,194,193,197,201,205,187,200,188, + 186,199,182,209,207,219,178,177,176,223,220,222,221,254,254,254, + 255,313,461,516,331,518,544, 21,345,304,496,510,536,341,306,339, + 248,311,349,517,340,519,545,350,344,297,497,511,537,462,298,463, + 585,263,289,287,142,143,146,522,299,144,314,280,542,265,291,498, + 323,514,500,512,292,288,153,334,320,524,271,293,154,520,502,225, + 584,160,131,284,132,134,145,523,294,130,312,137,543,161,140,499, + 321,515,501,513,147,285,148,246,318,525,163,150,129,521,503,352 + }, + "±¡³£µ¥¶¦¹©ºª»«¼¬¾®¿½àÀáÁâÂãÃäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏðÐñÑòÒóÓôÔõÕöÖøØùÙúÚûÛüÜýÝþÞ", + "ߢ",0,0 +}; + +// PC866 Russian DOS code page +CodePage TVCodePage::stPC866= +{ "PC 866 Russian", + 866, + { 360,361,588,362,363,589,364,409,365,366,590,367,591,592,593,368, + 594,595,596,369,370,597,371,372,373,374,375,376,377,378,379,380, + 598,381,382,383,384,599,385,386,387,388,389,390,391,392,600,393, + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 601,602,394,395,396,603,397,398,399,400,401,402,403,404,405,406, + 605,604,407,408,610,608,409,410,248,249,250,251,411,331,254,255 }, + " €¡¢‚£ƒ¤„¥…¦†§‡¨ˆ©‰ªŠ«‹¬Œ­®Ž¯àá‘â’ã“ä”å•æ–ç—è˜é™êšë›ìœíîžïŸñðóòõô÷ö", + "",0,0 +}; + +// ISO 8859-5 Russian ISO layout +CodePage TVCodePage::ISO8859_5= +{ "ISO 8859-5 Russian", + 88595, + { 218,196,191,192,217,179,195,180,194,193,197,201,205,187,200,188, + 186,199,182,209,207,219,178,177,176,223,220,222,221,254,254,254, + 32,605,412,414,407,612,416,610,611,417,419,421,423,341,425,427, + 360,361,588,362,363,589,364,409,365,366,590,367,591,592,593,368, + 594,595,596,369,370,597,371,372,373,374,375,376,377,378,379,380, + 598,381,382,383,384,599,385,386,387,388,389,390,391,392,600,393, + 601,602,394,395,396,603,397,398,399,400,401,402,403,404,405,406, + 411,604,413,415,408,606,607,608,609,418,420,422,424, 21,426,428 }, + "ñ¡ò¢ó£ô¤õ¥ö¦÷§ø¨ù©úªû«ü¬þ®ÿ¯Ð°Ñ±Ò²Ó³Ô´ÕµÖ¶×·Ø¸Ù¹ÚºÛ»Ü¼Ý½Þ¾ß¿àÀáÁâÂãÃäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏ", + "",0,0 +}; + +// KOD OBMENA INFORMATSIEY - 8bit RUSSKIY +// ëïä ïâíåîá éîæïòíáôóéåù I think that's close to the original ;-) +CodePage TVCodePage::KOI_8r= +{ "KOI-8r (Russian)", + 100000, + { 196,179,218,191,192,217,195,180,194,193,197,223,220,219,221,222, + 176,177,178,244,254,249,251,247,243,242,255,245,248,253,250,246, + 205,186,213,604,214,201,184,183,187,212,211,200,190,189,188,198, + 199,204,181,605,182,185,209,210,203,207,208,202,216,215,206,336, + 405,598,381,397,384,599,396,383,603,387,388,389,390,391,392,600, + 393,406,601,602,394,395,385,382,403,402,386,399,404,400,398,401, + 379,360,361,371,363,589,370,362,597,365,366,590,367,591,592,593, + 368,380,594,595,596,369,364,588,377,376,409,373,378,374,372,375 }, + "ÀàÁáÂâÃãÄäÅåÆæÇçÈèÉéÊêËëÌìÍíÎîÏïÐðÑñÒòÓóÔôÕõÖöØøÙùÚúÛûÜüÝýÞþßÿ£³", + "",0,0 +}; + +// KOI8 with CRL/NMSU extensions for SerboCroat +CodePage TVCodePage::KOI_8crl= +{ "KOI-8 with CRL/NMSU", + 100001, + { 218,196,191,192,217,179,195,180,194,193,197,201,205,187,200,188, // grf + 186,199,182,209,207,219,178,177,176,223,220,222,221,254,254,254, // grf + 0x20,0x20,0x20,604,413,609,418,420,422,428,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,605,412,611,417,419,421,427,0x20,0x20,0x20,0x20,0x20,0x20, + 405,598,381,397,384,599,396,383,603,387,388,389,390,391,392,600, + 393,406,601,602,394,395,385,382,403,402,386,399,404,400,398,401, + 379,360,361,371,363,589,370,362,597,365,366,590,367,591,592,593, + 368,380,594,595,596,369,364,588,377,376,409,373,378,374,372,375 }, + "£³¤´¥µ¦¶§·¨¸©¹ÀàÁáÂâÃãÄäÅåÆæÇçÈèÉéÊêËëÌìÍíÎîÏïÐðÑñÒòÓóÔôÕõÖö×÷ØøÙùÚúÛûÜüÝýÞþßÿ", + "",0,0 +}; + +// ECMA-Cyrillic ISO-IR-111 +CodePage TVCodePage::ISO_IR_111= +{ "ECMA-Cyr.ISO-IR-111", + 0x0111000E, + { 218,196,191,192,217,179,195,180,194,193,197,201,205,187,200,188, + 186,199,182,209,207,219,178,177,176,223,220,222,221,254,254,254, + 255,413,415,604,408,606,607,608,609,418,420,422,424,341,426,428, + 411,412,414,605,407,612,610,416,611,417,419,421,423,331,425,427, + 405,598,381,397,384,599,396,383,603,387,388,389,390,391,392,600, + 393,406,601,602,394,395,385,382,403,402,386,399,404,400,398,401, + 379,360,361,371,363,589,370,362,597,365,366,590,367,591,592,593, + 368,380,594,595,596,369,364,588,377,376,409,373,378,374,372,375 }, + "¡±¢²£³¤´¥µ¦¶§·¨¸©¹ªº«»¬¼®¾¯¿ÀàÁáÂâÃãÄäÅåÆæÇçÈèÉéÊêËëÌìÍíÎîÏïÐðÑñÒòÓóÔôÕõÖö×÷ØøÙùÚúÛûÜüÝýÞþßÿ", + "",0,0 +}; + +// GOST_19768-74 ST_SEV_358-88 ISO-IR-153 /subset of ISO-8859-5/ +CodePage TVCodePage::ISO_IR_153= +{ "Cyrillic ISO-IR-153", + 0x0153000E, + { 218,196,191,192,217,179,195,180,194,193,197,201,205,187,200,188, + 186,199,182,209,207,219,178,177,176,223,220,222,221,254,254,254, + 255,605,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,341,0x20,0x20, + 360,361,588,362,363,589,364,409,365,366,590,367,591,592,593,368, + 594,595,596,369,370,597,371,372,373,374,375,376,377,378,379,380, + 598,381,382,383,384,599,385,386,387,388,389,390,391,392,600,393, + 601,602,394,395,396,603,397,398,399,400,401,402,403,404,405,406, + 0x20,604,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20 }, + "ñ¡Ð°Ñ±Ò²Ó³Ô´ÕµÖ¶×·Ø¸Ù¹ÚºÛ»Ü¼Ý½Þ¾ß¿àÀáÁâÂãÃäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏ", + "",0,0 +}; + + +// Mac OS Cyrillic, cp10007 +CodePage TVCodePage::CP10007= +{ "Mac Cyr. CP 10007", + 10007, + { 360,361,588,362,363,589,364,409,365,366,590,367,591,592,593,368, + 594,595,596,369,370,597,371,372,373,374,375,376,377,378,379,380, + 431,248,155,156, 21, 7, 20,610,335,336,436,412,413,448,414,415, + 236,241,243,242,607,230,235,611,407,408,416,608,417,418,419,420, + 609,612,170,251,159,247,560,174,175,430,255,421,422,423,424,606, + 45,341,434,435, 96, 39,246,429,425,426,427,428,411,605,604,406, + 598,381,382,383,384,599,385,386,387,388,389,390,391,392,600,393, + 601,602,394,395,396,603,397,398,399,400,401,402,403,404,405,331 }, + "à€áâ‚ãƒä„å…æ†ç‡èˆé‰êŠë‹ìŒíîŽïðñ‘ò’ó“ô”õ•ö–÷—ø˜ù™úšû›üœýþžßŸ¬«¯®¹¸»º½¼¿¾ÌËÎÍÞÝÙØÛÚÀ·ÏÁ¶Æ", + "´µÄ",0,0 +}; + +// Mac OS Ukrainian +CodePage TVCodePage::CP100072= +{ "Mac OS Ukrainian", + 100072, + { 360,361,588,362,363,589,364,409,365,366,590,367,591,592,593,368, + 594,595,596,369,370,597,371,372,373,374,375,376,377,378,379,380, + 431,248,437,156, 21, 7, 20,610,335,336,436,412,413,448,414,415, + 236,241,243,242,607,230,438,611,407,408,416,608,417,418,419,420, + 609,612,170,251,159,247,560,174,175,430,255,421,422,423,424,606, + 45,341,434,435, 96, 39,246,429,425,426,427,428,411,605,604,406, + 598,381,382,383,384,599,385,386,387,388,389,390,391,392,600,393, + 601,602,394,395,396,603,397,398,399,400,401,402,403,404,405,331 }, + "à€áâ‚ãƒä„å…æ†ç‡èˆé‰êŠë‹ìŒíîŽïðñ‘ò’ó“ô”õ•ö–÷—ø˜ù™úšû›üœýþžßŸ¶¢¬«¯®À·¹¸»º½¼¿¾ÏÁÌËÎÍÙØÛÚÞÝ", + "§´µÄÆ",0,0 +}; + +// Osnovnoj Variant Russian +CodePage TVCodePage::OVR= +{ "Osnovnoj Variant Russian", + 885951, + { 218,196,191,192,217,179,195,180,194,193,197,201,205,187,200,188, // grf + 186,199,182,209,207,219,178,177,176,223,220,222,221,254,254,254, // grf + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 360,361,588,362,363,589,364,409,365,366,590,367,591,592,593,368, + 594,595,596,369,370,597,371,372,373,374,375,376,377,378,379,380, + 598,381,382,383,384,599,385,386,387,388,389,390,391,392,600,393, + 601,602,394,395,396,603,397,398,399,400,401,402,403,404,405,406, + 605,604,340, 96,340, 96, 26, 27, 25, 24,246,241,411,331,0x20,0x20 }, + "аѱҲӳԴյֶ׷ظٹںۻܼݽ޾߿àÀáÁâÂãÃäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏñð", + "",0,0 +}; + +// Alternativnyj Variant Russian +CodePage TVCodePage::AVR= +{ "Alternativnyj Variant RU", + 885952, + { 360,361,588,362,363,589,364,409,365,366,590,367,591,592,593,368, + 594,595,596,369,370,597,371,372,373,374,375,376,377,378,379,380, + 598,381,382,383,384,599,385,386,387,388,389,390,391,392,600,393, + 218,196,191,192,217,179,195,180,194,193,197,201,205,187,200,188, // grfs + 186,199,182,209,207,219,178,177,176,223,220,222,221,254,254,254, // grfs + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 601,602,394,395,396,603,397,398,399,400,401,402,403,404,405,406, + 605,604,340, 96,340, 96, 26, 27, 25, 24,246,241,411,331,0x20,0x20 }, + " €¡¢‚£ƒ¤„¥…¦†§‡¨ˆ©‰ªŠ«‹¬Œ­®Ž¯àá‘â’ã“ä”å•æ–ç—è˜é™êšë›ìœíîžïŸñð", + "",0,0 +}; + +// U-code Russian /subset of ISO-8859-5 and GOST_19768-74/ +CodePage TVCodePage::U_CodeR= +{ "U-code Russian", + 885953, + { 218,196,191,192,217,179,195,180,194,193,197,201,205,187,200,188, // grf + 186,199,182,209,207,219,178,177,176,223,220,222,221,254,254,254, // grf + 255,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 360,361,588,362,363,589,364,409,365,366,590,367,591,592,593,368, + 594,595,596,369,370,597,371,372,373,374,375,376,377,378,379,380, + 598,381,382,383,384,599,385,386,387,388,389,390,391,392,600,393, + 601,602,394,395,396,603,397,398,399,400,401,402,403,404,405,406, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20 }, + "аѱҲӳԴյֶ׷ظٹںۻܼݽ޾߿àÀáÁâÂãÃäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏ", + "",0,0 +}; + +/***** 7 bits! ******/ +ushort TVCodePage::tbKOI7[]= +{ 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35,331, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, +405,598,381,397,384,599,396,383, +603,387,388,389,390,391,392,600, +393,406,601,602,394,395,385,382, +403,402,386,399,404,400,398,401, +379,360,361,371,363,589,370,362, +597,365,366,590,367,591,592,593, +368,380,594,595,596,369,364,588, +377,376,409,373,378,374,372,127 +}; + +CodePage TVCodePage::KOI_7= +{ + "ISO 5427 ISO-IR-37 KOI-7", + 0x0037000E, + { + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 218,196,191,192,217,179,195,180,194,193,197,201,205,187,200,188, + 186,199,182,209,207,219,178,177,176,223,220,222,221,254,254,254, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127 + }, + "@`AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz[{\\|]}^~á¡â¢ã£ä¤å¥æ¦ç§è¨é©êªë«ì¬í­î®ï¯ðÐñÑòÒóÓôÔõÕöÖ÷×øØùÙúÚ", + "_", + 128,TVCodePage::tbKOI7 +}; + +ushort TVCodePage::tbISOIR147[]= +{ 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, +364,360,361,371,363,589,370,362, +597,365,611,590,367,591,592,593, +368,417,594,595,596,369,588,419, +427,612,409,373,414,423,372, 95, +385,598,381,397,384,599,396,383, +603,387,609,389,390,391,392,600, +393,418,601,602,394,395,382,420, +428,606,386,399,415,424,398,127 }; + +CodePage TVCodePage::ISO_IR_147= +{ + "JUS_I.B1.003-MAC ISO-IR-147", + 0x0147000E, + { + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 218,196,191,192,217,179,195,180,194,193,197,201,205,187,200,188, + 186,199,182,209,207,219,178,177,176,223,220,222,221,254,254,254, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127 + }, + "`@aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ{[|\\}]~^á¡â¢ã£ä¤å¥æ¦ç§è¨é©êªë«ì¬í­î®ï¯ðÐñÑòÒóÓôÔõÕöÖ÷×øØùÙúÚ", + "", + 128,TVCodePage::tbISOIR147 +}; + +ushort TVCodePage::tbISOIR146[]= +{ 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, +364,360,361,371,363,589,370,362, +597,365,611,590,367,591,592,593, +368,417,594,595,596,369,588,419, +427,612,409,373,412,421,372, 95, +385,598,381,397,384,599,396,383, +603,387,609,389,390,391,392,600, +393,418,601,602,394,395,382,420, +428,606,386,399,413,422,398,127 }; + +CodePage TVCodePage::ISO_IR_146= +{ + "JUS_I.B1.003-SERB ISOIR146", + 0x0146000E, + { + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 218,196,191,192,217,179,195,180,194,193,197,201,205,187,200,188, + 186,199,182,209,207,219,178,177,176,223,220,222,221,254,254,254, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127 + }, + "`@aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ{[|\\}]~^á¡â¢ã£ä¤å¥æ¦ç§è¨é©êªë«ì¬í­î®ï¯ðÐñÑòÒóÓôÔõÕöÖ÷×øØùÙúÚ", + "", + 128,TVCodePage::tbISOIR146 +}; + +ushort TVCodePage::Low32CharsRemaped[]= +{ 197,196,191,192,217,179,195, 7,194,193,218,219,178,177,176,180, + 16, 17, 18,220,222,221,254, 23, 24, 25, 26, 27,223, 29, 30, 31}; + +// PC1250 Windows latin 2 code page +CodePage TVCodePage::stPC1250= +{ "CP 1250 Win Latin 2", + 1250, + { 0x20,0x20, 44,0x20,429,430,431,432,0x20,433,304, 60,270,305,306,273, + 0x20, 96, 39,434,435, 7, 45,341,0x20,436,297, 62,260,326,298,262, + 255,350,351,319,331,313,338, 21,345,336,309,174,170,341,335,316, + 248,241,349,317,340,230, 20,250,344,311,307,175,327,348,325,315, + 269,263,289,330,142,266,264,128,299,144,314,280,301,265,291,300, + 323,267,302,268,292,354,153,334,303,283,271,274,154,272,310,225, + 259,160,131,328,132,257,256,135,294,130,312,137,358,161,140,324, + 321,258,295,162,147,353,148,246,296,282,163,286,129,261,308,352 }, + "šŠœŒŸžŽ³£¹¥ºª¾¼¿¯àÀáÁâÂãÃäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏðÐñÑòÒóÓôÔõÕöÖøØùÙúÚûÛüÜýÝþÞ", + "µß", + 32,TVCodePage::Low32CharsRemaped +}; + +// PC1251 Russian Windows code page +CodePage TVCodePage::PC1251= +{ "CP 1251 Win Russian", + 1251, + { 412,414, 44,415,429,430,431,432,0x20,433,417, 60,419,423,421,427, + 413, 96, 39,434,435, 7, 45,341,0x20,436,418, 62,420,424,422,428, + 255,425,426,611,331,437,338, 21,605,336,407,174,170,341,335,416, + 248,241,610,607,438,230, 20,250,604,411,408,175,609,612,606,608, + 360,361,588,362,363,589,364,409,365,366,590,367,591,592,593,368, + 594,595,596,369,370,597,371,372,373,374,375,376,377,378,379,380, + 598,381,382,383,384,599,385,386,387,388,389,390,391,392,600,393, + 601,602,394,395,396,603,397,398,399,400,401,402,403,404,405,406 }, + "€ƒšŠœŒžŽŸ¢¡¼£´¥ºª¿¯²³¸¨¾½àÀáÁâÂãÃäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏðÐñÑòÒóÓôÔõÕöÖ÷×øØùÙúÚûÛüÜýÝþÞÿß", + "µ", + 32,Low32CharsRemaped +}; + +// PC1252 Windows latin 1 code page +CodePage TVCodePage::stPC1252= +{ "CP 1252 Win Latin 1", + 1252, + { 0x20,0x20, 44,159,429,430,431,432, 94,433,304, 60,440,0x20,306,0x20, + 0x20, 96, 39,434,435, 7, 45,341,126,436,297, 62,441,0x20,298,450, + 255,173,155,156,331,157,338, 21,345,336,166,174,170,341,335,339, + 248,241,253,347,340,230, 20,250,344,346,167,175,172,171,343,168, + 275,263,289,287,142,143,146,128,276,144,290,280,277,265,291,281, + 323,165,278,268,292,288,153,334,320,279,271,293,154,272,333,225, + 133,160,131,284,132,134,145,135,138,130,136,137,141,161,140,139, + 322,164,149,162,147,285,148,246,318,151,163,150,129,261,332,152 }, + "œŒšŠžŽÿŸàÀáÁâÂãÃäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏðÐñÑòÒóÓôÔõÕöÖøØùÙúÚûÛüÜýÝþÞ", + "ƒµß", + 32,Low32CharsRemaped +}; + +// PC1253 Windows greek code page +CodePage TVCodePage::stPC1253= +{ "CP 1253 Win Greek", + 1253, + { 0x20,0x20, 44,159,429,430,431,432,0x20,433,0x20, 60,0x20,0x20,0x20,0x20, + 0x20, 96, 39,434,435, 7, 45,341,0x20,436,0x20, 62,0x20,0x20,0x20,0x20, + 255,564,572,156,331,157,338, 21,345,336,0x20,174,170,341,335,341, + 248,241,253,347,340,230, 20,250,573,574,575,175,576,171,577,578, + 581,617,618,226,560,619,620,621,233,622,623,583,624,625,561,626, + 562,627,0x20,228,628,629,232,630,563,234,631,632,565,566,567,568, + 582,224,613,546,235,238,547,548,549,550,614,551,615,552,553,616, + 227,554,555,229,231,556,237,557,558,559,579,580,569,570,571,0x20 }, + "µÌáÁâÂãÃäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏðÐñÑòÓóÓôÔõÕöÖ÷×øØùÙܢݸ޹ߺü¼ý¾þ¿úÚûÛ", + "ƒÀà", + 32,Low32CharsRemaped +}; + +// PC1254 Windows +CodePage TVCodePage::stPC1254= +{ "CP 1254 Win Turkish", + 1254, + { 0x20,0x20, 44,159,429,430,431,432, 94,433,304, 60,440,0x20,0x20,0x20, + 0x20, 96, 39,434,435, 7, 45,341,126,436,297, 62,441,0x20,0x20,450, + 255,173,155,156,331,157,338, 21,345,336,166,174,170,341,335,339, + 248,241,253,347,340,230, 20,250,344,346,167,175,172,171,343,168, + 275,263,289,287,142,143,146,128,276,144,290,280,277,265,291,281, + 504,165,278,268,292,288,153,334,320,279,271,293,154,487,309,225, + 133,160,131,284,132,134,145,135,138,130,136,137,141,161,140,139, + 505,164,149,162,147,285,148,246,318,151,163,150,129,337,307,152 }, + "àÀáÁâÂãÃäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏðÐñÑòÒóÓôÔõÕöÖøØùÙúÚûÛüÜýÝþÞšŠœŒÿŸ", + "ƒµß", + 32,Low32CharsRemaped +}; + +// PC1257 Windows +CodePage TVCodePage::stPC1257= +{ "CP 1257 Win Baltic", + 1257, + { 0x20,0x20, 44,0x20,429,430,431,432,0x20,433,0x20, 60,0x20,345,350,344, + 0x20, 96, 39,434,435, 7, 45,341,0x20,436,0x20, 62,0x20,339,349,0x20, + 255,0x20,155,156,331,0x20,338, 21,320,336,516,174,170,341,335,146, + 248,241,253,347,340,230, 20,250,318,346,517,175,172,171,343,145, + 313,522,585,264,142,143,314,496,299,144,273,542,510,512,498,544, + 304,267,514,268,500,288,153,334,524,319,270,502,154,316,306,225, + 311,523,584,256,132,134,312,497,294,130,262,543,511,513,499,545, + 297,258,515,162,501,285,148,246,525,317,260,503,129,315,298,352 + }, + "¸¨ºª¿¯àÀáÁâÂãÃäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏðÐñÑòÒóÓôÔõÕöÖ÷×øØùÙúÚûÛüÜýÝþÞ", + "µß", + 32,Low32CharsRemaped +}; + +CodePage TVCodePage::ISO8859_7= +{ "ISO 8859-7 Greek", + 88597, + { 218,196,191,192,217,179,195,180,194,193,197,201,205,187,200,188, + 186,199,182,209,207,219,178,177,176,223,220,222,221,254,254,254, + 255, 96, 39,156, 32, 32,338, 21,345,336, 32,174,170,341, 32,341, + 248,241,253,347,340,564,572,250,573,574,575,175,576,171,577,578, + 581,617,618,226,560,619,620,621,233,622,623,583,624,625,561,626, + 562,627, 32,228,628,629,232,630,563,234,631,632,565,566,567,568, + 582,224,613,546,235,238,547,548,549,550,614,551,615,552,553,616, + 227,554,555,229,231,556,237,557,558,559,579,580,569,570,571, 32 }, + "ܶݸ޹ߺü¼ý¾þ¿úÚûÛáÁâÂãÃäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏðÐñÑòÓóÓôÔõÕöÖ÷×øØùÙ", + "àÀ",0,0 +}; + +// ISO 8859-9 (1989) Pure +CodePage TVCodePage::ISO8859_9= +{ "ISO 8859-9", + 88599, + { 218,196,191,192,217,179,195,180,194,193,197,201,205,187,200,188, + 186,199,182,209,207,219,178,177,176,223,220,222,221,254,254,254, + 255,173,155,156,331,157,338, 21,345,336,166,174,170,341,335,339, + 248,241,253,347,340,230, 20,250,344,346,167,175,172,171,343,168, + 275,263,289,287,142,143,146,128,276,144,290,280,277,265,291,281, + 504,165,278,268,292,288,153,334,320,279,271,293,154,487,309,225, + 133,160,131,284,132,134,145,135,138,130,136,137,141,161,140,139, + 505,164,149,162,147,285,148,246,318,151,163,150,129,337,307,152 }, + "àÀáÁâÂãÃäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏðÐñÑòÒóÓôÔõÕöÖøØùÙúÚûÛüÜýÝþÞ", + "µßÿ",0,0 +}; + +// ISO/IEC 8859-14:1998 +CodePage TVCodePage::ISO8859_14= +{ "ISO 8859-14", + 885914, + { 218,196,191,192,217,179,195,180,194,193,197,201,205,187,200,188, + 186,199,182,209,207,219,178,177,176,223,220,222,221,254,254,254, + 255,478,479,156,480,481,482, 21,526,336,530,483,528,341,335,450, + 484,485,586,486,488,489, 20,490,527,491,531,492,529,532,533,493, + 275,263,289,287,142,143,146,128,276,144,290,280,277,265,291,281, + 474,165,278,268,292,288,153,494,320,279,271,293,154,272,476,225, + 133,160,131,284,132,134,145,135,138,130,136,137,141,161,140,139, + 475,164,149,162,147,285,148,495,318,151,163,150,129,261,477,152 + }, + "¢¡¥¤«¦¸¨ºª¼¬±°³²µ´¹·¿»¾½àÀáÁâÂãÃäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏðÐñÑòÒóÓôÔõÕöÖ÷×øØùÙúÚûÛüÜýÝþÞÿ¯", + "ß",0,0 +}; + +// ISO/IEC 8859-15:1998 +CodePage TVCodePage::ISO8859_15= +{ "ISO 8859-15 Icelan.", + 885915, + { 218,196,191,192,217,179,195,180,194,193,197,201,205,187,200,188, + 186,199,182,209,207,219,178,177,176,223,220,222,221,254,254,254, + 255,173,155,156,0x20,157,304, 21,297,336,166,174,170,341,335,339, + 248,241,253,347,306,230, 20,250,298,346,167,175,440,441,450,168, + 275,263,289,287,142,143,146,128,276,144,290,280,277,265,291,281, + 323,165,278,268,292,288,153,334,320,279,271,293,154,272,333,225, + 133,160,131,284,132,134,145,135,138,130,136,137,141,161,140,139, + 322,164,149,162,147,285,148,246,318,151,163,150,129,261,332,152 }, + "àÀáÁâÂãÃäÄåÅæÆçÇèÈéÉêÊëËìÌíÍîÎïÏðÐñÑòÒóÓôÔõÕöÖøØùÙúÚûÛüÜýÝþÞ", + "µßÿ",0,0 +}; + +// That's a special polish code page +// This is PC437 changing: 134,141,143,144,145,146,149,152,156,158,160-167 +CodePage TVCodePage::stMazovia= +{ "Mazovia (polish)", + 1000000, + { 128,129,130,131,132,133,311,135,136,137,138,139,140,256,142,313, + 314,312,317,147,148,264,150,151,270,153,154,155,319,157,260,159, + 273,316,162,268,258,267,262,315,168,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 }, + "†•‘’œž˜¦ §¡¢£¤¥„Ž‡€š”™", + "‚ƒ…ˆ‰Š‹Œ“–—á",0,0 +}; + +/**[txh]******************************************************************** + + Description: + Protected member used to create the list of known code pages stored in +CodePages. + +***************************************************************************/ + +void TVCodePage::CreateCodePagesCol() +{ + CodePages=new TVCodePageCol(43,3); + + #define a(v) CodePages->insert(&v) + // Total: 47 + // Latin (27) + a(stPC437); + a(stPC775); + a(stPC850); + a(stPC852); + a(stPC857); + a(stPC860); + a(stPC861); + a(stPC863); + a(stPC865); + a(ISO8879_1); + a(ISO8859_1_Lat1); + a(ISO8859_1u_Lat1); + a(ISO8879_2); + a(ISO8859_2_Lat2); + a(ISO8859_2u_Lat2); + a(ISO8859_2e_Lat2); + a(ISO8859_2_Sun); + a(ISO8859_3); + a(ISO8859_4); + a(ISO8859_9); + a(ISO8859_14); + a(ISO8859_15); + a(stPC1250); + a(stPC1252); + a(stPC1254); + a(stPC1257); + a(stMazovia); + // Russian (16) + a(stPC855); + a(stPC866); + a(ISO8859_5); + a(KOI_8r); + a(KOI_8crl); + a(PC1251); + a(ISO_IR_111); + a(ISO_IR_153); + a(CP10007); + a(CP100072); + a(OVR); + a(AVR); + a(U_CodeR); + a(KOI_7); + a(ISO_IR_147); + a(ISO_IR_146); + // Greek (4) + a(stPC737); + a(stPC869); + a(stPC1253); + a(ISO8859_7); + #undef a +} + +/**[txh]******************************************************************** + + Description: + Initializes the code page system selecting the indicated code pages. This +is only used iternally. @x{::SetCodePage}. + +***************************************************************************/ + +TVCodePage::TVCodePage(int idApp, int idScr, int idInp) +{ + if (!CodePages) + CreateCodePagesCol(); + FillTables(idApp); + CreateOnTheFlyRemap(idApp,idScr); + curScrCP=defScrCP=idScr; + CreateOnTheFlyInpRemap(idInp,idApp); + curInpCP=defInpCP=idInp; + defAppCP=idApp; + TGKey::SetCodePage(idInp); + if (idApp!=curAppCP) + { + curAppCP=idApp; + RemapTVStrings(GetTranslate(curAppCP)); + } +} + +/**[txh]******************************************************************** + + Description: + Protected member used to create a one to one table to convert from one +code page to another. Used to create the input to application and application +to screen on the fly convertion tables. + +***************************************************************************/ + +void TVCodePage::CreateRemap(int idSource, int idDest, uchar *table) +{ + unsigned i; + // Table to convert a value into an internal code. + // That's what we need. + ushort *toCode=GetTranslate(idSource),*aux; + // Table to convert an internal value into a 0-255 value. + // That's what we have. If something is missing we will remap to a similar. + uchar *fromCode=new uchar[maxSymbolDefined]; + memset(fromCode,0,maxSymbolDefined*sizeof(uchar)); + CodePage *destCP=CodePageOfID(idDest); + aux=destCP->Font; + for (i=0; i<128; i++) + if (aux[i]LowRemapNum) + { + unsigned to=destCP->LowRemapNum; + aux=destCP->LowRemap; + for (; i='a' && i<='z') + { + toUpperTable[i]=i-32; + AlphaTable[i]=alphaChar | lowerChar; + } + else + toUpperTable[i]=i; + if (i>='A' && i<='Z') + { + toLowerTable[i]=i+32; + AlphaTable[i]=alphaChar | upperChar; + } + else + toLowerTable[i]=i; + if (i>='0' && i<='9') + AlphaTable[i]=digitChar; + } + // 2) For this code page + uchar *s=(uchar *)p->UpLow; + if (s) + for (; *s; s+=2) + { + toLowerTable[*(s+1)]=*s; + toUpperTable[*s]=*(s+1); + AlphaTable[*s]=alphaChar | lowerChar; + AlphaTable[*(s+1)]=alphaChar | upperChar; + } + s=(uchar *)p->MoreLetters; + if (s) + for (; *s; s++) + AlphaTable[*s]=alphaChar; + /* Dump tables + fputs("uchar TVCodePage::AlphaTable[256]=\n{\n",stderr); + for (i=0; i<256; i++) + { + fprintf(stderr,"0x%02X,",AlphaTable[i]); + if (!((i+1)&0xF)) fputc('\n',stderr); + } + fputs("};\nuchar TVCodePage::toUpperTable[256]=\n{\n",stderr); + for (i=0; i<256; i++) + { + fprintf(stderr,"0x%02X,",toUpperTable[i]); + if (!((i+1)&0xF)) fputc('\n',stderr); + } + fputs("};\nuchar TVCodePage::toLowerTable[256]=\n{\n",stderr); + for (i=0; i<256; i++) + { + fprintf(stderr,"0x%02X,",toLowerTable[i]); + if (!((i+1)&0xF)) fputc('\n',stderr); + } + fputs("};\n",stderr); */ +} + +/**[txh]******************************************************************** + + Description: + Deallocates memory used by TVCodePage. + +***************************************************************************/ + +TVCodePage::~TVCodePage() +{ + CLY_destroy(CodePages); + CodePages=NULL; +} + +/**[txh]******************************************************************** + + Description: + Converts a code page id into an index in the code page collection.@* + Important note: We should always default to 437 because:@* +1) That's the original encoding used by TV applications.@* +2) Some asiatic encodings, like code page 936 (simplified chinese, maybe +also 950 [traditional chinese], 932 [japanese Shift-JIS] and 949 [korean]), +behaves like 437 when we write to the video buffer.@* + + Return: The index of the code page with this id. If error the index for +PC 437 code page is returned. + +***************************************************************************/ + +ccIndex TVCodePage::IDToIndex(int id) +{ + if (!CodePages) return 0; + ccIndex c=CodePages->getCount(); + ccIndex i, i437=0; + for (i=0; iat(i)); + if (p->id==id) + return i; + if (p->id==PC437) + i437=i; + } + return i437; +} + +/**[txh]******************************************************************** + + Description: + Converts an index in the code page collection into a code page id. No +check of range is done. + + Return: The code page id for the indicated index. + +***************************************************************************/ + +int TVCodePage::IndexToID(ccIndex index) +{ + if (!CodePages) return 0; + CodePage *p=(CodePage *)(CodePages->at(index)); + return p->id; +} + +/**[txh]******************************************************************** + + Description: + Used to get a map to translate code page symbols into internal symbols for +the indicated code page id. + + Return: A pointer to a static buffer containing the translation values. Or +NULL if not initialized. The index 256 indicates 128 if only the upper 128 +values are really different from CP 437 or 256 if all the values are +different. In any case all the values are usable. + +***************************************************************************/ + +ushort *TVCodePage::GetTranslate(int id) +{ + if (!CodePages) + CreateCodePagesCol(); + CodePage *p=CodePageOfID(id); + memcpy(CPTable+128,p->Font,sizeof(short)*128); + CPTable[256]=128; + int i=0; + if (p->LowRemapNum) + { + CPTable[256]=0; + memcpy(CPTable,p->LowRemap,sizeof(short)*p->LowRemapNum); + i=p->LowRemapNum; + } + for (; i<128; i++) + CPTable[i]=i; + + return CPTable; +} + +/**[txh]******************************************************************** + + Description: + Fills a table with pairs Unicode/code in CP. The table is sorted and the +user must provide an array with at least 256 elements to fill. + +***************************************************************************/ + +void TVCodePage::GetUnicodesForCP(int id, stIntCodePairs *unicodes) +{ + ushort *internals=GetTranslate(id); + int i; + for (i=0; i<256; i++) + { + unicodes[i].unicode=UnicodeForInternalCode(internals[i]); + unicodes[i].code=i; + } + qsort(unicodes,256,sizeof(stIntCodePairs),compare); + /*for (i=0; i<256; i++) + printf("U+%04X => %d (0x%02X)\n",unicodes[i].unicode,unicodes[i].code,unicodes[i].code);*/ +} + +/**[txh]******************************************************************** + + Description: + Used to get a TStringCollection listing all the available code pages. +Useful to make the user choose one. This is a read-only value, don't modify +it. + + Return: The internal collection casted to TStringCollection. + +***************************************************************************/ + +TStringCollection *TVCodePage::GetList(void) +{ + return CodePages; +} + +/**[txh]******************************************************************** + + Description: + Remaps the desired character using the provided map. The original character +should be in CP437 encoding. @x{::GetTranslate}. + + Return: The remapped character. It can be a direct translation or the +closest found. + +***************************************************************************/ + +uchar TVCodePage::RemapChar(uchar c, ushort *map) +{ + if (c126 || v<32) + { + v=Similar[v]; + if (v>=32 && v<127) + return v; + for (i=map[256]; i<256; i++) + if (map[i]==v) + return i; + } + return v; +} + +/**[txh]******************************************************************** + + Description: + Remaps the @{o} string using the provided map and storing it in the +@{n} string. The string should be terminated by a 0. @x{::RemapChar}. + +***************************************************************************/ + +void TVCodePage::RemapString(uchar *n, uchar *o, ushort *map) +{ + int i; + for (i=0; o[i]; i++) + n[i]=RemapChar(o[i],map); +} + +/**[txh]******************************************************************** + + Description: + Remaps the @var{o} string using the provided map and storing it in the +@var{n} string. The number of items to remap is indicated with @var{len}. +@x{::RemapChar}. + +***************************************************************************/ + +void TVCodePage::RemapNString(uchar *n, uchar *o, ushort *map, int len) +{ + for (; len; --len) + n[len-1]=RemapChar(o[len-1],map); +} + +/**[txh]******************************************************************** + + Description: + Used to remap a buffer from any of the supported code pages into another. +The process doesn't have to be reversible.@p + Tabs, carriage returns, new lines and the null code aren't remapped. + +***************************************************************************/ + +void TVCodePage::RemapBufferGeneric(int sourID, int destID, uchar *buffer, unsigned len, + unsigned ops) +{ + unsigned i; + if (!CodePages) return; // Just in case + // Table to convert a value into an internal code + ushort *toCode=GetTranslate(sourID); + ushort *aux; + if (ops & rbgDontRemapLow32) + { + for (i=0; i<32; i++) + toCode[i]=i; + } + else + { + // Avoid conversions that will break the text: + toCode[0]=0; + toCode['\n']='\n'; + toCode['\r']='\r'; + toCode['\t']='\t'; + } + + // Table to convert an internal value into a 0-255 value + uchar *fromCode=new uchar[maxSymbolDefined]; + memset(fromCode,0,maxSymbolDefined*sizeof(uchar)); + + CodePage *destCP=CodePageOfID(destID); + + aux=destCP->Font; + for (i=0; i<128; i++) + if (aux[i]LowRemapNum) + { + unsigned to=destCP->LowRemapNum; + aux=destCP->LowRemap; + for (; iat(IDToIndex(id))); +} + +stIntCodePairs TVCodePage::InternalMap[]= +{ + { 0x0020, 32 }, + { 0x0021, 33 }, + { 0x0022, 34 }, + { 0x0023, 35 }, + { 0x0024, 36 }, + { 0x0025, 37 }, + { 0x0026, 38 }, + { 0x0027, 39 }, + { 0x0028, 40 }, + { 0x0029, 41 }, + { 0x002a, 42 }, + { 0x002b, 43 }, + { 0x002c, 44 }, + { 0x002d, 45 }, + { 0x002e, 46 }, + { 0x002f, 47 }, + { 0x0030, 48 }, + { 0x0031, 49 }, + { 0x0032, 50 }, + { 0x0033, 51 }, + { 0x0034, 52 }, + { 0x0035, 53 }, + { 0x0036, 54 }, + { 0x0037, 55 }, + { 0x0038, 56 }, + { 0x0039, 57 }, + { 0x003a, 58 }, + { 0x003b, 59 }, + { 0x003c, 60 }, + { 0x003d, 61 }, + { 0x003e, 62 }, + { 0x003f, 63 }, + { 0x0040, 64 }, + { 0x0041, 65 }, + { 0x0042, 66 }, + { 0x0043, 67 }, + { 0x0044, 68 }, + { 0x0045, 69 }, + { 0x0046, 70 }, + { 0x0047, 71 }, + { 0x0048, 72 }, + { 0x0049, 73 }, + { 0x004a, 74 }, + { 0x004b, 75 }, + { 0x004c, 76 }, + { 0x004d, 77 }, + { 0x004e, 78 }, + { 0x004f, 79 }, + { 0x0050, 80 }, + { 0x0051, 81 }, + { 0x0052, 82 }, + { 0x0053, 83 }, + { 0x0054, 84 }, + { 0x0055, 85 }, + { 0x0056, 86 }, + { 0x0057, 87 }, + { 0x0058, 88 }, + { 0x0059, 89 }, + { 0x005a, 90 }, + { 0x005b, 91 }, + { 0x005c, 92 }, + { 0x005d, 93 }, + { 0x005e, 94 }, + { 0x005f, 95 }, + { 0x0060, 96 }, + { 0x0061, 97 }, + { 0x0062, 98 }, + { 0x0063, 99 }, + { 0x0064, 100 }, + { 0x0065, 101 }, + { 0x0066, 102 }, + { 0x0067, 103 }, + { 0x0068, 104 }, + { 0x0069, 105 }, + { 0x006a, 106 }, + { 0x006b, 107 }, + { 0x006c, 108 }, + { 0x006d, 109 }, + { 0x006e, 110 }, + { 0x006f, 111 }, + { 0x0070, 112 }, + { 0x0071, 113 }, + { 0x0072, 114 }, + { 0x0073, 115 }, + { 0x0074, 116 }, + { 0x0075, 117 }, + { 0x0076, 118 }, + { 0x0077, 119 }, + { 0x0078, 120 }, + { 0x0079, 121 }, + { 0x007a, 122 }, + { 0x007b, 123 }, + { 0x007c, 124 }, + { 0x007d, 125 }, + { 0x007e, 126 }, + { 0x00a0, 255 }, + { 0x00a1, 173 }, + { 0x00a2, 155 }, + { 0x00a3, 156 }, + { 0x00a4, 331 }, + { 0x00a5, 157 }, + { 0x00a6, 338 }, + { 0x00a7, 21 }, + { 0x00a8, 345 }, + { 0x00a9, 336 }, + { 0x00aa, 166 }, + { 0x00ab, 174 }, + { 0x00ac, 170 }, + { 0x00ad, 341 }, + { 0x00ae, 335 }, + { 0x00af, 339 }, + { 0x00b0, 248 }, + { 0x00b1, 241 }, + { 0x00b2, 253 }, + { 0x00b3, 347 }, + { 0x00b4, 340 }, + { 0x00b5, 230 }, + { 0x00b6, 20 }, + { 0x00b7, 250 }, + { 0x00b8, 344 }, + { 0x00b9, 346 }, + { 0x00ba, 167 }, + { 0x00bb, 175 }, + { 0x00bc, 172 }, + { 0x00bd, 171 }, + { 0x00be, 343 }, + { 0x00bf, 168 }, + { 0x00c0, 275 }, + { 0x00c1, 263 }, + { 0x00c2, 289 }, + { 0x00c3, 287 }, + { 0x00c4, 142 }, + { 0x00c5, 143 }, + { 0x00c6, 146 }, + { 0x00c7, 128 }, + { 0x00c8, 276 }, + { 0x00c9, 144 }, + { 0x00ca, 290 }, + { 0x00cb, 280 }, + { 0x00cc, 277 }, + { 0x00cd, 265 }, + { 0x00ce, 291 }, + { 0x00cf, 281 }, + { 0x00d0, 323 }, + { 0x00d1, 165 }, + { 0x00d2, 278 }, + { 0x00d3, 268 }, + { 0x00d4, 292 }, + { 0x00d5, 288 }, + { 0x00d6, 153 }, + { 0x00d7, 334 }, + { 0x00d8, 320 }, + { 0x00d9, 279 }, + { 0x00da, 271 }, + { 0x00db, 293 }, + { 0x00dc, 154 }, + { 0x00dd, 272 }, + { 0x00de, 333 }, + { 0x00df, 225 }, + { 0x00e0, 133 }, + { 0x00e1, 160 }, + { 0x00e2, 131 }, + { 0x00e3, 284 }, + { 0x00e4, 132 }, + { 0x00e5, 134 }, + { 0x00e6, 145 }, + { 0x00e7, 135 }, + { 0x00e8, 138 }, + { 0x00e9, 130 }, + { 0x00ea, 136 }, + { 0x00eb, 137 }, + { 0x00ec, 141 }, + { 0x00ed, 161 }, + { 0x00ee, 140 }, + { 0x00ef, 139 }, + { 0x00f0, 322 }, + { 0x00f1, 164 }, + { 0x00f2, 149 }, + { 0x00f3, 162 }, + { 0x00f4, 147 }, + { 0x00f5, 285 }, + { 0x00f6, 148 }, + { 0x00f7, 246 }, + { 0x00f8, 318 }, + { 0x00f9, 151 }, + { 0x00fa, 163 }, + { 0x00fb, 150 }, + { 0x00fc, 129 }, + { 0x00fd, 261 }, + { 0x00fe, 332 }, + { 0x00ff, 152 }, + { 0x0100, 585 }, + { 0x0101, 584 }, + { 0x0102, 330 }, + { 0x0103, 328 }, + { 0x0104, 313 }, + { 0x0105, 311 }, + { 0x0106, 264 }, + { 0x0107, 256 }, + { 0x0108, 464 }, + { 0x0109, 465 }, + { 0x010a, 480 }, + { 0x010b, 481 }, + { 0x010c, 299 }, + { 0x010d, 294 }, + { 0x010e, 300 }, + { 0x010f, 324 }, + { 0x010f, 359 }, + { 0x0110, 323 }, + { 0x0111, 321 }, + { 0x0112, 496 }, + { 0x0113, 497 }, + { 0x0115, 329 }, + { 0x0116, 542 }, + { 0x0117, 543 }, + { 0x0118, 314 }, + { 0x0119, 312 }, + { 0x011a, 301 }, + { 0x011b, 358 }, + { 0x011c, 466 }, + { 0x011d, 467 }, + { 0x011e, 504 }, + { 0x011f, 505 }, + { 0x0120, 586 }, + { 0x0121, 486 }, + { 0x0122, 510 }, + { 0x0123, 511 }, + { 0x0124, 468 }, + { 0x0125, 469 }, + { 0x0126, 534 }, + { 0x0127, 535 }, + { 0x0128, 518 }, + { 0x0129, 519 }, + { 0x012a, 498 }, + { 0x012b, 499 }, + { 0x012c, 506 }, + { 0x012d, 507 }, + { 0x012e, 522 }, + { 0x012f, 523 }, + { 0x0130, 487 }, + { 0x0131, 337 }, + { 0x0134, 470 }, + { 0x0135, 471 }, + { 0x0136, 512 }, + { 0x0137, 513 }, + { 0x0138, 461 }, + { 0x0139, 266 }, + { 0x013a, 257 }, + { 0x013b, 544 }, + { 0x013c, 545 }, + { 0x013d, 327 }, + { 0x013d, 356 }, + { 0x013e, 325 }, + { 0x013e, 355 }, + { 0x0141, 319 }, + { 0x0142, 317 }, + { 0x0143, 267 }, + { 0x0144, 258 }, + { 0x0145, 514 }, + { 0x0146, 515 }, + { 0x0147, 302 }, + { 0x0148, 295 }, + { 0x014a, 462 }, + { 0x014b, 463 }, + { 0x014c, 500 }, + { 0x014d, 501 }, + { 0x0150, 354 }, + { 0x0151, 353 }, + { 0x0152, 440 }, + { 0x0153, 441 }, + { 0x0154, 269 }, + { 0x0155, 259 }, + { 0x0156, 516 }, + { 0x0157, 517 }, + { 0x0158, 303 }, + { 0x0159, 296 }, + { 0x015a, 270 }, + { 0x015b, 260 }, + { 0x015c, 472 }, + { 0x015d, 473 }, + { 0x015e, 309 }, + { 0x015f, 307 }, + { 0x0160, 304 }, + { 0x0161, 297 }, + { 0x0162, 310 }, + { 0x0163, 308 }, + { 0x0164, 305 }, + { 0x0165, 326 }, + { 0x0165, 357 }, + { 0x0166, 536 }, + { 0x0167, 537 }, + { 0x0168, 520 }, + { 0x0169, 521 }, + { 0x016a, 502 }, + { 0x016b, 503 }, + { 0x016c, 508 }, + { 0x016d, 509 }, + { 0x016e, 282 }, + { 0x016f, 283 }, + { 0x0170, 274 }, + { 0x0171, 286 }, + { 0x0172, 524 }, + { 0x0173, 525 }, + { 0x0174, 474 }, + { 0x0175, 475 }, + { 0x0176, 476 }, + { 0x0177, 477 }, + { 0x0178, 450 }, + { 0x0179, 273 }, + { 0x017a, 262 }, + { 0x017b, 316 }, + { 0x017c, 315 }, + { 0x017d, 306 }, + { 0x017e, 298 }, + { 0x0192, 159 }, + { 0x01a0, 538 }, + { 0x01a1, 539 }, + { 0x01af, 540 }, + { 0x01b0, 541 }, + { 0x02c7, 350 }, + { 0x02d8, 351 }, + { 0x02d9, 352 }, + { 0x02db, 349 }, + { 0x02dd, 348 }, + { 0x0385, 564 }, + { 0x0386, 572 }, + { 0x0388, 573 }, + { 0x0389, 574 }, + { 0x038a, 575 }, + { 0x038c, 576 }, + { 0x038e, 577 }, + { 0x038f, 578 }, + { 0x0390, 581 }, + { 0x0391, 617 }, + { 0x0392, 618 }, + { 0x0393, 226 }, + { 0x0394, 560 }, + { 0x0395, 619 }, + { 0x0396, 620 }, + { 0x0397, 621 }, + { 0x0398, 233 }, + { 0x0399, 622 }, + { 0x039a, 623 }, + { 0x039b, 583 }, + { 0x039c, 624 }, + { 0x039d, 625 }, + { 0x039e, 561 }, + { 0x039f, 626 }, + { 0x03a0, 562 }, + { 0x03a1, 627 }, + { 0x03a3, 228 }, + { 0x03a4, 628 }, + { 0x03a5, 629 }, + { 0x03a6, 232 }, + { 0x03a7, 630 }, + { 0x03a8, 563 }, + { 0x03a9, 234 }, + { 0x03aa, 631 }, + { 0x03ab, 632 }, + { 0x03ac, 565 }, + { 0x03ad, 566 }, + { 0x03ae, 567 }, + { 0x03af, 568 }, + { 0x03b0, 582 }, + { 0x03b1, 224 }, + { 0x03b2, 613 }, + { 0x03b3, 546 }, + { 0x03b4, 235 }, + { 0x03b5, 238 }, + { 0x03b6, 547 }, + { 0x03b7, 548 }, + { 0x03b8, 549 }, + { 0x03b9, 550 }, + { 0x03ba, 614 }, + { 0x03bb, 551 }, + { 0x03bc, 615 }, + { 0x03bd, 552 }, + { 0x03be, 553 }, + { 0x03bf, 616 }, + { 0x03c0, 227 }, + { 0x03c1, 554 }, + { 0x03c2, 555 }, + { 0x03c3, 229 }, + { 0x03c4, 231 }, + { 0x03c5, 556 }, + { 0x03c6, 237 }, + { 0x03c7, 557 }, + { 0x03c8, 558 }, + { 0x03c9, 559 }, + { 0x03ca, 579 }, + { 0x03cb, 580 }, + { 0x03cc, 569 }, + { 0x03cd, 570 }, + { 0x03ce, 571 }, + { 0x0401, 605 }, + { 0x0402, 412 }, + { 0x0403, 414 }, + { 0x0404, 407 }, + { 0x0405, 612 }, + { 0x0406, 610 }, + { 0x0407, 416 }, + { 0x0408, 611 }, + { 0x0409, 417 }, + { 0x040a, 419 }, + { 0x040b, 421 }, + { 0x040c, 423 }, + { 0x040e, 425 }, + { 0x040f, 427 }, + { 0x0410, 360 }, + { 0x0411, 361 }, + { 0x0412, 588 }, + { 0x0413, 362 }, + { 0x0414, 363 }, + { 0x0415, 589 }, + { 0x0416, 364 }, + { 0x0417, 409 }, + { 0x0418, 365 }, + { 0x0419, 366 }, + { 0x041a, 590 }, + { 0x041b, 367 }, + { 0x041c, 591 }, + { 0x041d, 592 }, + { 0x041e, 593 }, + { 0x041f, 368 }, + { 0x0420, 594 }, + { 0x0421, 595 }, + { 0x0422, 596 }, + { 0x0423, 369 }, + { 0x0424, 370 }, + { 0x0425, 597 }, + { 0x0426, 371 }, + { 0x0427, 372 }, + { 0x0428, 373 }, + { 0x0429, 374 }, + { 0x042a, 375 }, + { 0x042b, 376 }, + { 0x042c, 377 }, + { 0x042d, 378 }, + { 0x042e, 379 }, + { 0x042f, 380 }, + { 0x0430, 598 }, + { 0x0431, 381 }, + { 0x0432, 382 }, + { 0x0433, 383 }, + { 0x0434, 384 }, + { 0x0435, 599 }, + { 0x0436, 385 }, + { 0x0437, 386 }, + { 0x0438, 387 }, + { 0x0439, 388 }, + { 0x043a, 389 }, + { 0x043b, 390 }, + { 0x043c, 391 }, + { 0x043d, 392 }, + { 0x043e, 600 }, + { 0x043f, 393 }, + { 0x0440, 601 }, + { 0x0441, 602 }, + { 0x0442, 394 }, + { 0x0443, 395 }, + { 0x0444, 396 }, + { 0x0445, 603 }, + { 0x0446, 397 }, + { 0x0447, 398 }, + { 0x0448, 399 }, + { 0x0449, 400 }, + { 0x044a, 401 }, + { 0x044b, 402 }, + { 0x044c, 403 }, + { 0x044d, 404 }, + { 0x044e, 405 }, + { 0x044f, 406 }, + { 0x0451, 604 }, + { 0x0452, 413 }, + { 0x0453, 415 }, + { 0x0454, 408 }, + { 0x0455, 606 }, + { 0x0456, 607 }, + { 0x0457, 608 }, + { 0x0458, 609 }, + { 0x0459, 418 }, + { 0x045a, 420 }, + { 0x045b, 422 }, + { 0x045c, 424 }, + { 0x045e, 426 }, + { 0x045f, 428 }, + { 0x0490, 437 }, + { 0x0491, 438 }, + { 0x1e02, 478 }, + { 0x1e03, 479 }, + { 0x1e0a, 482 }, + { 0x1e0b, 483 }, + { 0x1e1e, 484 }, + { 0x1e1f, 485 }, + { 0x1e40, 488 }, + { 0x1e41, 489 }, + { 0x1e56, 490 }, + { 0x1e57, 491 }, + { 0x1e60, 492 }, + { 0x1e61, 493 }, + { 0x1e6a, 494 }, + { 0x1e6b, 495 }, + { 0x1e80, 526 }, + { 0x1e81, 527 }, + { 0x1e82, 530 }, + { 0x1e83, 531 }, + { 0x1e84, 532 }, + { 0x1e85, 533 }, + { 0x1ef2, 528 }, + { 0x1ef3, 529 }, + { 0x2017, 342 }, + { 0x201c, 434 }, + { 0x201d, 435 }, + { 0x201e, 429 }, + { 0x2020, 431 }, + { 0x2021, 432 }, + { 0x2022, 7 }, + { 0x2024, 7 }, + { 0x2026, 430 }, + { 0x2027, 249 }, + { 0x2030, 433 }, + { 0x203c, 19 }, + { 0x207f, 252 }, + { 0x20a7, 158 }, + { 0x20ac, 587 }, + { 0x2116, 411 }, + { 0x2122, 436 }, + { 0x2190, 27 }, + { 0x2191, 24 }, + { 0x2192, 26 }, + { 0x2193, 25 }, + { 0x2194, 29 }, + { 0x2195, 18 }, + { 0x21a8, 23 }, + { 0x21b5, 449 }, + { 0x2219, 249 }, + { 0x221a, 251 }, + { 0x221e, 236 }, + { 0x221f, 28 }, + { 0x2229, 239 }, + { 0x2248, 247 }, + { 0x2260, 448 }, + { 0x2261, 240 }, + { 0x2264, 243 }, + { 0x2265, 242 }, + { 0x22c5, 7 }, + { 0x2302, 127 }, + { 0x2310, 169 }, + { 0x2320, 244 }, + { 0x2321, 245 }, + { 0x2409, 442 }, + { 0x240a, 445 }, + { 0x240b, 447 }, + { 0x240c, 443 }, + { 0x240d, 444 }, + { 0x2423, 32 }, // Should be fixed + { 0x2424, 446 }, + { 0x2500, 196 }, + { 0x2501, 205 }, // (*1) + { 0x2502, 179 }, + { 0x2503, 186 }, // (*1) + { 0x250c, 218 }, + { 0x250f, 201 }, // (*1) + { 0x2510, 191 }, + { 0x2513, 187 }, // (*1) + { 0x2514, 192 }, + { 0x2517, 200 }, // (*1) + { 0x2518, 217 }, + { 0x251b, 188 }, // (*1) + { 0x251c, 195 }, + { 0x2523, 204 }, // (*1) + { 0x2524, 180 }, + { 0x252b, 185 }, // (*1) + { 0x252c, 194 }, + { 0x2533, 203 }, // (*1) + { 0x2534, 193 }, + { 0x253b, 202 }, // (*1) + { 0x253c, 197 }, + { 0x254b, 206 }, // (*1) + { 0x2550, 205 }, + { 0x2551, 186 }, + { 0x2552, 213 }, + { 0x2553, 214 }, + { 0x2554, 201 }, + { 0x2555, 184 }, + { 0x2556, 183 }, + { 0x2557, 187 }, + { 0x2558, 212 }, + { 0x2559, 211 }, + { 0x255a, 200 }, + { 0x255b, 190 }, + { 0x255c, 189 }, + { 0x255d, 188 }, + { 0x255e, 198 }, + { 0x255f, 199 }, + { 0x2560, 204 }, + { 0x2561, 181 }, + { 0x2562, 182 }, + { 0x2563, 185 }, + { 0x2564, 209 }, + { 0x2565, 210 }, + { 0x2566, 203 }, + { 0x2567, 207 }, + { 0x2568, 208 }, + { 0x2569, 202 }, + { 0x256a, 216 }, + { 0x256b, 215 }, + { 0x256c, 206 }, + { 0x2574, 455 }, + { 0x2575, 452 }, + { 0x2576, 453 }, + { 0x2577, 454 }, + { 0x2578, 460 }, + { 0x2579, 457 }, + { 0x257a, 458 }, + { 0x257b, 459 }, + { 0x2580, 223 }, + { 0x2584, 220 }, + { 0x2588, 219 }, + { 0x258c, 221 }, + { 0x2590, 222 }, + { 0x2591, 176 }, + { 0x2592, 177 }, + { 0x2593, 178 }, + { 0x25a0, 254 }, + { 0x25ac, 22 }, + { 0x25b2, 30 }, + { 0x25b6, 16 }, + { 0x25bc, 31 }, + { 0x25c0, 17 }, + { 0x25c6, 4 }, + { 0x25cb, 9 }, + { 0x25d8, 8 }, + { 0x25d9, 10 }, + { 0x25e6, 8 }, + { 0x2609, 15 }, + { 0x263a, 1 }, + { 0x263b, 2 }, + { 0x263c, 15 }, + { 0x2640, 12 }, + { 0x2642, 11 }, + { 0x2660, 6 }, + { 0x2663, 5 }, + { 0x2665, 3 }, + { 0x2666, 4 }, + { 0x266a, 13 }, + { 0x266b, 14 }, + { 0x2764, 3 }, + { 0xf800, 451 }, // Approximation + { 0xf801, 451 }, + { 0xf803, 456 }, + { 0xf804, 456 }, // Approximation + { 0xfffd, 439 } +}; + +// Notes: +// (*1) Linux lat1 says this. I think this is wrong and in fact XFree86 10x20 +// font author interprets Unicode tables as me. +// The 205 symbol is Unicode 0x2550, of course it can be used as a default +// for 0x2501. 0x2550 is double line and 0x2501 is one line that is the +// double in width. The same is for all the other cases. + + +const int TVCodePage::providedUnicodes=sizeof(TVCodePage::InternalMap)/sizeof(stIntCodePairs); + +/**[txh]******************************************************************** + + Description: + Finds which unicode is represented by the specified internal code. +Currently that's an slow search because isn't used very much. + + Return: The first unicode found. + +***************************************************************************/ + +uint16 TVCodePage::UnicodeForInternalCode(uint16 value) +{ + int i; + for (i=0; icode : -1; +} + +/**[txh]******************************************************************** + + Description: + Creates a new code page from an arry containing the unicodes for each +symbol. Use an id over than 0x7FFF8000 to avoid collisions. This is used by +the Linux driver when the unicodes maps doesn't match with known cp. + +***************************************************************************/ + +void TVCodePage::CreateCPFromUnicode(CodePage *cp, int id, const char *name, + ushort *unicodes) +{ + // Create a code page + strcpy(cp->Name,name); + cp->id=id; + int i; + for (i=128; i<256; i++) + { + int v=unicodes[i]; + if (v==0xFFFF) + cp->Font[i-128]=0; + else + { + v=InternalCodeForUnicode(v); + cp->Font[i-128]=v==-1 ? 0 : v; + } + } + // Currently we lack an Unicode toupper/lower and isalpha mechanism + cp->UpLow=cp->MoreLetters=NULL; + cp->LowRemapNum=128; + cp->LowRemap=new ushort[128]; + for (i=0; i<128; i++) + { + int v=unicodes[i]; + if (v==0xFFFF) + cp->LowRemap[i]=0; + else + { + v=InternalCodeForUnicode(v); + cp->LowRemap[i]=v==-1 ? 0 : v; + } + } +} + +/**[txh]******************************************************************** + + Description: + Adds a custom code page to the list. You can create a new one from an +array containing the Unicodes for each symbol. @x{::CreateCPFromUnicode}. + + Return: The index of the new code page in the collection. + +***************************************************************************/ + +ccIndex TVCodePage::AddCodePage(CodePage *cp) +{ + if (!CodePages) // Drivers could need to add custom cps before init. + CreateCodePagesCol(); + return CodePages->insert(cp); +} + +/**[txh]******************************************************************** + + Description: + This is a helper for the TVFontCollection class the parameters of this +function could change in the future.@* + Basically it finds a replacement for a missing symbol in a font. It allows +using incomplete font. + + Return: The replacement or -1 if none known. + +***************************************************************************/ + +int TVCodePage::LookSimilarInRange(int code, int last) +{ + while (code>last && !(code>=' ' && code<='~')) + { + if (code<256) + code=Similar[code]; + else + code=Similar2[code-256]; + } + return code>last ? -1 : code; +} + diff --git a/tvision/classes/configfile.cc b/tvision/classes/configfile.cc new file mode 100644 index 0000000..4035e63 --- /dev/null +++ b/tvision/classes/configfile.cc @@ -0,0 +1,953 @@ +/**[txh]******************************************************************** + + Copyright 2002-2009 by Salvador Eduardo Tropea (SET) + This file is covered by the GPL license. + + Module: Config File + Include: TVConfigFile + Comments: + This module provides the TVConfigFile class. This class can load a +configuration file containing sections and variables. Each section have +a name which is indicated using brackets [Name]. As sections can be nested +and my text editor can indent using the braces as reference (also jump to +the start/end of a block and highlight the pair) the section's body must +be enclosed using braces. Sections can be nested conforming an structure +that resembles a file system. Inside a section you can define variables. A +variable name must be composed of a-zA-Z_0-9 characters. After the name, and +in the same line, an equal sign must be put. The value after the equal sign +can be a number (decimal, octal or hexadecimal as in C) or a string enclosed +using double quotes. You can use spaces around the equal sign and after the +value but you must finish a definition in one line. Comments are started +with a # symbol and ends at the end of the line.@p + The information from a configuration file is stored in memory as a tree. +You can search in the tree some key indicating it as a you indicate a path +and file name. Just think it as a particular file system, just use forward +slashes. + +***************************************************************************/ + +#define Uses_getline +#define Uses_stdio +#define Uses_ctype +#define Uses_string +#define Uses_stdlib +#define Uses_TVConfigFile +#define Uses_sys_stat +#define Uses_AllocLocal +#include + +// Currently I don't want to expose these things: +// Type of nodes +const char tBranch=0, tInteger=1, tString=2; + +const char *TVConfigFile::Errors[]= +{ + __("Can't open file"), // -1 + __("Comment inside section name"), // -2 + __("Unterminated section name"), // -3 + __("Empty section name"), // -4 + __("Syntax error"), // -5 + __("Missing open section {"), // -6 + __("Missing close section }"), // -7 + __("Missing equal sign"), // -8 + __("Missing value after equal"), // -9 + __("Unterminated string"), // -10 + __("Non branch in base"), // -11 + __("Trying to overwrite a value with a section"), // -12 + __("Trying to overwrite a section with a value") // -13 +}; + +/**[txh]******************************************************************** + + Description: + Initializes the class and reads the contents of the specified file to a +tree in memory. + +***************************************************************************/ + +TVConfigFile::TVConfigFile() +{ + tree.next=NULL; + sLine=0; + line=NULL; + ErrorStatus=0; +} + +/**[txh]******************************************************************** + + Description: + Searchs for the indicated key in the tree. Separate nested sections using +forward slashes. + + Return: not 0 if the key was found, the return value is in @{p} if +the key is an string. Otherwise @{p} is NULL and the value is in +@{n}. + +***************************************************************************/ + +int TVConfigFile::Search(const char *key, char *&p, long &n) +{ + if (!key) return 0; + p=NULL; + char *copy=newStr(key); + strtok(copy,"/"); + int ret=SearchInBranch(tree.next,copy,p,n); + delete[] copy; + return ret; +} + + +int TVConfigFile::EatSpaces() +{ + for (; *s && *s!='\n' && isspace(*s) && *s!='#'; s++); + return !*s || *s=='#'; +} + +int TVConfigFile::GetLine() +{ + ssize_t read=CLY_getline(&line,&sLine,f); + if (read==-1) return -1; + s=line; + ErrorLine++; + // Eat the EOL + if (read && line[read-1]=='\n') + { + line[read-1]=0; + return read-1; + } + return read; +} + +char *TVConfigFile::newStrL(const char *start, int len) +{ + char *ret=new char[len+1]; + memcpy(ret,start,len); + ret[len]=0; + return ret; +} + +TVConfigFileTreeNode *TVConfigFile::NewBranch(const char *name, int len) +{ + TVConfigFileTreeNode *aux=new TVConfigFileTreeNode; + aux->type=tBranch; + aux->content=NULL; + aux->next=NULL; + aux->name=newStrL(name,len); + return aux; +} + +int TVConfigFile::IsWordChar(int val) +{ + return isalnum(val) || val=='_'; +} + +char *TVConfigFile::GetString() +{ + char *start=++s; + int len; + for (len=1; *s && *s!='"'; len++, s++) + if (*s=='\\' && s[1]) s++; + if (*s!='"') + return 0; + s++; + char *ret=new char[len+1], *ori, *dest; + for (ori=start, dest=ret; *ori && *ori!='"'; ori++, dest++) + if (*ori=='\\') + { + ori++; + switch (*ori) + { + case 'n': + *dest='\n'; + break; + case 'r': + *dest='\r'; + break; + case 't': + *dest='\t'; + break; + default: + *dest=*ori; + } + } + else + *dest=*ori; + *dest=0; + return ret;//newStrL(start,s-start-1); +} + +long TVConfigFile::GetInteger() +{ + char *end; + long value; + value=strtol(s,&end,0); + s=end; + return value; +} + +int TVConfigFile::ReadBranch(TVConfigFileTreeNode *&base) +{ + int cant=0, ret; + char *start, *end; + TVConfigFileTreeNode *aux, *last=base; + + while (last && last->next) last=last->next; + + // Look for the open section character + do + { + if (!EatSpaces()) + { + if (*s!='{') return -6; + s++; + break; + } + } + while (GetLine()!=-1); + + do + { + if (EatSpaces()) continue; + do + { + if (*s=='[') + { + start=++s; + if (*s==']') return -4; + for (; *s && *s!=']' && *s!='#'; s++); + if (*s=='#') return -2; + if (!*s) return -3; + + aux=SearchOnlyInBranch(base,start,s-start); + if (aux) + { // We already have it + if (aux->type!=tBranch) return -12; + s++; + ret=ReadBranch(aux->content); + } + else + { // New one + aux=NewBranch(start,s-start); + aux->priority=fromFile; + //printf("New Branch 2: %s\n",aux->name); + if (base) + { + last->next=aux; + last=aux; + } + else + base=last=aux; + s++; + ret=ReadBranch(aux->content); + } + if (ret<0) return ret; + + cant+=ret; + EatSpaces(); + } + if (*s=='}') + { + s++; + return cant; + } + if (IsWordChar(*s)) + { + start=s; + for (; IsWordChar(*s); s++); + end=s; + if (EatSpaces() || *s!='=') return -8; + s++; + if (EatSpaces()) return -9; + int lenVar=s-start-1; + // Be sure we can get the value + char *string=NULL; + long integer=0; + if (*s=='"') + { + string=GetString(); + if (!string) return -10; + } + else if (isdigit(*s)) + { + integer=GetInteger(); + } + else + return -10; + // Is already there? + int newOne=0; + aux=SearchOnlyInBranch(base,start,lenVar); + if (aux) + { // We already have it + if (aux->type==tBranch) return -13; + if (aux->priority>fromFile) + aux=NULL; + else + if (aux->type==tString) delete[] aux->string; + } + else + { + aux=new TVConfigFileTreeNode; + newOne=1; + } + + if (aux) + { + if (string) + { + aux->string=string; + aux->type=tString; + } + else + { + aux->integer=integer; + aux->type=tInteger; + } + if (newOne) + aux->name=newStrL(start,end-start); + aux->next=NULL; + aux->priority=fromFile; + /*if (aux->type==tString) + printf("New String: %s=\"%s\"\n",aux->name,aux->string); + else + printf("New Integer: %s=%d\n",aux->name,aux->integer);*/ + if (newOne) + { + if (base) + { + last->next=aux; + last=aux; + } + else + base=last=aux; + } + cant++; + } + EatSpaces(); + } + else + if (*s && *s!='[' && *s!='#') + return -5; + } + while (*s && *s!='#'); + } + while (GetLine()!=-1); + return -7; +} + +int TVConfigFile::ReadBase(TVConfigFileTreeNode *&base) +{ + int cant=0, ret; + char *start; + TVConfigFileTreeNode *aux, *last=base; + + while (last && last->next) last=last->next; + + while (GetLine()!=-1) + { + if (EatSpaces()) continue; + do + { + if (*s=='[') + { + start=++s; + if (*s==']') return -4; + for (; *s && *s!=']' && *s!='#'; s++); + if (*s=='#') return -2; + if (!*s) return -3; + aux=SearchOnlyInBranch(base,start,s-start); + if (aux) + { // We already have it + if (aux->type!=tBranch) return -11; + s++; + ret=ReadBranch(aux->content); + } + else + { // New one + aux=NewBranch(start,s-start); + aux->priority=fromFile; + //printf("New Branch 1: %s\n",aux->name); + if (base) + { + last->next=aux; + last=aux; + } + else + base=last=aux; + s++; + ret=ReadBranch(aux->content); + } + if (ret<0) return ret; + cant+=ret; + EatSpaces(); + } + if (*s && *s!='#' && *s!='[') + return -5; + } + while (*s && *s!='#'); + } + return cant; +} + +TVConfigFileTreeNode *TVConfigFile::SearchOnlyInBranch(TVConfigFileTreeNode *b, + char *name, int len) +{ + if (!b) return NULL; + AllocLocalStr(key,len+1); + memcpy(key,name,len); + key[len]=0; + return SearchOnlyInBranch(b,key); +} + +TVConfigFileTreeNode *TVConfigFile::SearchOnlyInBranch(TVConfigFileTreeNode *b, + char *name) +{ + if (!b) return NULL; + while (b) + { + if (strcmp(b->name,name)==0) + return b; + b=b->next; + } + return NULL; +} + +int TVConfigFile::SearchInBranch(TVConfigFileTreeNode *b, char *key, char *&p, long &n) +{ + if (!key || !b) return 0; + while (b) + { + if (strcmp(b->name,key)==0) + { + switch (b->type) + { + case tBranch: + return SearchInBranch(b->content,strtok(NULL,"/"),p,n); + case tString: + p=b->string; + break; + case tInteger: + n=b->integer; + break; + } + return 1; + } + b=b->next; + } + return 0; +} + +int TVConfigFile::Read(const char *file) +{ + ErrorLine=0; + f=fopen(file,"rt"); + if (!f) + return -1; + int ret=ReadBase(tree.next); + + // Free the line + free(line); + line=NULL; + sLine=0; + + fclose(f); + return ret; +} + +int TVConfigFile::Add(const char *key, TVConfigFileTreeNode *node) +{ + int len=strlen(key); + AllocLocalStr(b,len+1); + strcpy(b,key); + + // Create/navigate the "directories" + TVConfigFileTreeNode *where=tree.next, **parent=&tree.next, *p; + char *val=strtok(b,"/"); + while (val) + { + p=SearchOnlyInBranch(where,val); + if (p) + { + parent=&p->content; + where=p->content; + } + else + { + TVConfigFileTreeNode *aux=NewBranch(val,len); + aux->priority=node->priority; + if (where) + {// At the end + TVConfigFileTreeNode *p=where; + while (p->next) p=p->next; + p->next=aux; + } + else + *parent=aux; + parent=&aux->content; + where=NULL; + } + val=strtok(NULL,"/"); + } + // Now put the value + p=SearchOnlyInBranch(where,node->name); + if (p) + { + if (p->type==tBranch) + { + ErrorStatus=-13; + return 0; + } + if (p->priority>node->priority) return 0; + if (p->type==tString) + delete[] p->string; + node->next=p->next; + memcpy(p,node,sizeof(TVConfigFileTreeNode)); + } + else + { + if (where) + {// At the end + TVConfigFileTreeNode *b=where; + while (b->next) b=b->next; + b->next=node; + } + else + *parent=node; + } + return 1; +} + +/**[txh]******************************************************************** + + Description: + Adds a new variable to the tree. The type of the variable is integer. The +@{name} variable is added to the section indicated by @{key}. +Possible priority values are justHint (25), fromFile (50) or fromApplication +(75). It is used to determine if a current value should be replaced by the +new value. The name is copied. + + Return: !=0 if the variable was added. + Example: TVConfigFile::AddInt("TV/X11","ScreenWidth",90, +TVConfigFile::fromFile) + +***************************************************************************/ + +int TVConfigFile::AddInt(const char *key, const char *name, long value, int priority) +{ + TVConfigFileTreeNode *node=new TVConfigFileTreeNode; + node->type=tInteger; + node->priority=priority; + node->integer=value; + node->name=newStr(name); + node->next=NULL; + if (!Add(key,node)) + { + DeleteArray(node->name); + delete node; + return 0; + } + return 1; +} + +/**[txh]******************************************************************** + + Description: + Adds a new variable to the tree. The type of the variable is string. The +@{name} variable is added to the section indicated by @{key}. +Possible priority values are justHint (25), fromFile (50) or fromApplication +(75). It is used to determine if a current value should be replaced by the +new value. The name and the content are copied. + + Return: !=0 if the variable was added. + Example: TVConfigFile::AddInt("TV/X11","ExtProgVideoMode","A_Program", +TVConfigFile::fromFile) + +***************************************************************************/ + +int TVConfigFile::AddString(const char *key, const char *name, + const char *value, int priority) +{ + TVConfigFileTreeNode *node=new TVConfigFileTreeNode; + node->type=tString; + node->priority=priority; + node->string=newStr(value); + node->name=newStr(name); + node->next=NULL; + if (!Add(key,node)) + { + DeleteArray(node->name); + DeleteArray(node->string); + delete node; + return 0; + } + return 1; +} + +void TVConfigFile::FreeList(TVConfigFileTreeNode *p) +{ + TVConfigFileTreeNode *start=p,*aux; + // First pass is for recursion + while (p) + { + if (p->type==tBranch) + FreeList(p->content); + p=p->next; + } + p=start; + // Second pass frees it + while (p) + { + aux=p->next; + if (p->type==tString) + delete[] p->string; + delete[] p->name; + delete p; + p=aux; + } +} + +void TVConfigFile::FreeTree() +{ + FreeList(tree.next); +} + +void TVConfigFile::PrintIndent(int indent, FILE *f) +{ + int i; + for (i=indent; i; --i) fputc(' ',f); +} + +void TVConfigFile::PrintBranch(TVConfigFileTreeNode *base, int indent, FILE *f) +{ + while (base) + { + switch (base->type) + { + case tBranch: + PrintIndent(indent,f); + fprintf(f,"[%s]\n",base->name); + PrintIndent(indent,f); + fputs("{\n",f); + PrintBranch(base->content,indent+1,f); + PrintIndent(indent,f); + fputs("}\n",f); + break; + case tString: + PrintIndent(indent,f); + fprintf(f,"%s=\"%s\"\n",base->name,base->string); + break; + case tInteger: + PrintIndent(indent,f); + fprintf(f,"%s=%ld\n",base->name,base->integer); + break; + } + base=base->next; + } +} + +/**[txh]******************************************************************** + + Description: + Prints the current tree to the specified file. It's main purpose is to +debug programs, but you can use it to generate valid configuration files +from data found in memory. + +***************************************************************************/ + +void TVConfigFile::Print(FILE *f) +{ + PrintBranch(tree.next,0,f); +} + +// Inline members just documented here. +/**[txh]** + Function: ~TVConfigFile + Prototype: ~TVConfigFile() + Description: + This is the destructor and just releases the tree that contains the +variables. +*********/ +/**[txh]** + Function: Load + Prototype: int Load(const char *file) + Description: Reads the specified configuration file. + Return: The read status, 0 means no error. The @{Errors} data member +contains descriptions for the errors. +*********/ + +/***************************************************************************** + That's a special case used to configure the library. +*****************************************************************************/ + +TVConfigFile *TVMainConfigFile::config=NULL; +const char *TVMainConfigFile::userConfigFile=NULL; +const char *configFileName="tvrc"; +#if CLY_HiddenDifferent +const char *configFileNameH=".tvrc"; +#endif + +/**[txh]******************************************************************** + + Class: TVMainConfigFile + Description: + This is the constructor for TVMainConfigFile. This class is a special case +of TVConfigFile used for the Turbo Vision configuration file. Note you can +store application specific information in the configuration file using a +section different than TV. + +***************************************************************************/ + +TVMainConfigFile::TVMainConfigFile() +{ + config=new TVConfigFile(); +} + +/**[txh]******************************************************************** + + Description: + Loads the configuration file. First we try using the application provided +name, then we search in the current directory, the path indicated by the +HOME environment variable, the path indicated by the HOMEDIR environment +variable, /etc and /dev/env/DJDIR/etc (%DJDIR%/etc). The default name for +the file is tvrc, if the OS uses a point in the name to make it a hidden file +the library also tries with .tvrc. + + Return: The error status. 0 is OK. + +***************************************************************************/ + +int TVMainConfigFile::Load() +{ + // Load the configuration file + char *name=NULL; + if (userConfigFile) + { + struct stat st; + if (stat(userConfigFile,&st)==0 && S_ISREG(st.st_mode)) + name=newStr(userConfigFile); + } + if (!name) + { + name=TestForFileIn("."); + if (!name) + { + char *home=getenv("HOME"); + if (home) + name=TestForFileIn(home); + if (!name) + { + home=getenv("HOMEDIR"); + if (home) + name=TestForFileIn(home); + if (!name) + { + name=TestForFileIn("/etc"); + if (!name) + {// DJGPP trick + name=TestForFileIn("/dev/env/DJDIR/etc"); + } + } + } + } + } + if (name) + { + //printf("Loading configuration from %s\n",name); + config->Load(name); + delete[] name; + } + //config->Print(stderr); + return config->ErrorStatus; +} + +/**[txh]******************************************************************** + + Description: + Destroys the global TVConfigFile that contains the configuration. + +***************************************************************************/ + +TVMainConfigFile::~TVMainConfigFile() +{ + delete config; + config=NULL; +} + +char *TVMainConfigFile::TestForFileIn(const char *where) +{ + AllocLocalStr(b,strlen(where)+strlen(configFileName)+3); + struct stat st; + + strcpy(b,where); + strcat(b,"/"); + strcat(b,configFileName); + if (stat(b,&st)==0 && S_ISREG(st.st_mode)) + return newStr(b); + + #if CLY_HiddenDifferent + strcpy(b,where); + strcat(b,"/"); + strcat(b,configFileNameH); + if (stat(b,&st)==0 && S_ISREG(st.st_mode)) + return newStr(b); + #endif + + return NULL; +} + +/**[txh]******************************************************************** + + Description: + Looks for the specified key in the TV section. If found the result is +stored in @{val}, but only if that's an integer. + + Return: True if the key exists, even when that's an string. + +***************************************************************************/ + +Boolean TVMainConfigFile::Search(const char *key, long &val) +{ + if (!config || !key) return False; + AllocLocalStr(b,strlen(key)+4); + strcpy(b,"TV/"); + strcat(b,key); + char *v; + return config->Search(b,v,val) ? True : False; +} + +/**[txh]******************************************************************** + + Description: + Looks for the specified @var{variable} in the TV section using the +specified @var{section} as subsection. If found the result is +stored in @{val}, but only if that's an integer. + + Return: True if the key exists, even when that's an string. + +***************************************************************************/ + +Boolean TVMainConfigFile::Search(const char *section, const char *variable, long &val) +{ + if (!config || !section || !variable) return False; + AllocLocalStr(b,strlen(section)+strlen(variable)+5); + strcpy(b,"TV/"); + strcat(b,section); + strcat(b,"/"); + strcat(b,variable); + char *v; + return config->Search(b,v,val) ? True : False; +} + +/**[txh]******************************************************************** + + Description: + Looks for the specified key in the TV section. If found the result is +returned but only if that's a string. + + Return: The string or NULL. + +***************************************************************************/ + +char *TVMainConfigFile::Search(const char *key) +{ + if (!config || !key) return NULL; + AllocLocalStr(b,strlen(key)+4); + strcpy(b,"TV/"); + strcat(b,key); + long n; char *v=NULL; + config->Search(b,v,n); + return v; +} + +/**[txh]******************************************************************** + + Description: + Looks for the specified @var{variable} in the TV section using the +specified @var{section} as subsection. If found the result is returned but +only if that's a string. + + Return: The string or NULL. + +***************************************************************************/ + +char *TVMainConfigFile::Search(const char *section, const char *variable) +{ + if (!config || !section || !variable) return NULL; + AllocLocalStr(b,strlen(section)+strlen(variable)+5); + strcpy(b,"TV/"); + strcat(b,section); + strcat(b,"/"); + strcat(b,variable); + long n; char *v=NULL; + config->Search(b,v,n); + return v; +} + +/**[txh]******************************************************************** + + Description: + Adds a new variable of integer type to the TV subtree in the specified +@{section} and using the specified @{name}. The priority for this +variable is TVConfigFile::fromApplication. @x{TVConfigFile::AddInt}. + + Return: !=0 if added. + +***************************************************************************/ + +int TVMainConfigFile::Add(const char *section, const char *name, long value) +{ + int lSection=section ? strlen(section)+1 : 0; + AllocLocalStr(b,lSection+4); + strcpy(b,"TV"); + if (section) + { + b[2]='/'; + strcpy(b+3,section); + } + return config->AddInt(b,name,value,TVConfigFile::fromApplication); +} + +/**[txh]******************************************************************** + + Description: + Adds a new variable of string type to the TV subtree in the specified +@{section} and using the specified @{name}. The priority for this +variable is TVConfigFile::fromApplication. The string is copied. +@x{TVConfigFile::AddInt}. + + Return: !=0 if added. + +***************************************************************************/ + +int TVMainConfigFile::Add(const char *section, const char *name, + const char *value) +{ + int lSection=section ? strlen(section)+1 : 0; + AllocLocalStr(b,lSection+4); + strcpy(b,"TV"); + if (section) + { + b[2]='/'; + strcpy(b+3,section); + } + return config->AddString(b,name,value,TVConfigFile::fromApplication); +} + +// Inline members just documented here. +/**[txh]** + Function: Print + Prototype: void TVMainConfigFile::Print(FILE *f) + Class: TVMainConfigFile + Description: + Prints the current tree to the specified file. It's main purpose is to +debug programs, but you can use it to generate valid configuration files +from data found in memory. +*********/ +/**[txh]** + Function: SetUserConfigFile + Prototype: void TVMainConfigFile::SetUserConfigFile(const char *name) + Class: TVMainConfigFile + Description: Specifies a name and path for the configuration file. Use it +if your application needs special settings different than the rest of the +TV applications. +*********/ + diff --git a/tvision/classes/dos/dosdis.cc b/tvision/classes/dos/dosdis.cc new file mode 100644 index 0000000..7a38458 --- /dev/null +++ b/tvision/classes/dos/dosdis.cc @@ -0,0 +1,805 @@ +/**[txh]******************************************************************** + + DOS Display (TDisplayDOS) functions. + + Copyright (c) 1996-1998 by Robert H”hne. + Copyright (c) 1998-2002 by Salvador E. Tropea (SET) + Tweaked video modes by Christian Domp + + Module: DOS Display + Comments: + This module implements the low level DOS screen access.@p + + Todo:@* + * The palette map could be changed during suspend. Currently not + suported. But is a really bizarre case and is restored if VGA state saving + is used. + +***************************************************************************/ + +#include + +//#define Uses_stdio +#define Uses_stdlib +#define Uses_string +#define Uses_TScreen +#define Uses_TEvent +#define Uses_TFrame +#include + +// I delay the check to generate as much dependencies as possible +#ifdef TVCompf_djgpp + +#include +#include +#include +#include +#include +#include +#include +#include + +#define TSCREEN_DEFINE_REGISTERS +#include +#include + +// In early versions Robert experimented with pages now it isn't used but +// some simple future driver could do it. +#define GetPage() 0 + +// This could be needed for Windows XP Professional, not sure. +// Disabled until I get positive confirmation. +//#define XP_CURSOR_SHAPE_WORKAROUND 1 + +// x86 registers used for BIOS calls +__dpmi_regs TDisplayDOS::rDisplay; +// Numbers of lines of each character (height in pixels) +unsigned TDisplayDOS::charLines=16; +// Flag to indicate if the video mode should ask the mouse class to draw +// the cursor instead of letting the OS mouse driver do it. +char TDisplayDOS::emulateMouse=0; +char TDisplayDOS::colorsMap[17]; + +// Video BIOS services +#define SET_TEXT_MODE_CURSOR_SHAPE 0x01 +#define SET_CURSOR_POSITION 0x02 +#define GET_CURSOR_POSITION_AND_SIZE 0x03 +#define READ_ALL_PALETTE_REGISTERS_AND_OVERSCAN_REGISTER 0x1009 +#define SET_INDIVIDUAL_DAC_REGISTER 0x1010 +#define READ_INDIVIDUAL_DAC_REGISTER 0x1015 +#define ALTERNATE_FUNCTION_SELECT 0x12 +#define SELECT_VERTICAL_RESOLUTION 0x30 + +const int crtIndex=0x3B4,crtData=0x3B5; +const int mdaCursorLocationHigh=0x0E,mdaCursorLocationLow=0x0F; +const int mdaCursorStart=0x0A,mdaCursorEnd=0x0B; + +static inline +unsigned char InMDA(unsigned char i) +{ + outportb(crtIndex,i); + return inportb(crtData); +} + +static inline +void OutMDA(unsigned char i,unsigned char b) +{ + outportb(crtIndex,i); + outportb(crtData,b); +} + +void TDisplayDOS::SetCursorPos(unsigned x, unsigned y) +{ + if (dual_display || TScreenDOS::screenMode==7) + { + unsigned loc=y*80+x; + OutMDA(mdaCursorLocationHigh,loc>>8); + OutMDA(mdaCursorLocationLow ,loc & 0xFF); + } + else + { + DH=y; + DL=x; + BH=GetPage(); + AH=SET_CURSOR_POSITION; + videoInt(); + } +} + +void TDisplayDOS::GetCursorPos(unsigned &x, unsigned &y) +{ + if (dual_display) + { + unsigned pos=(InMDA(mdaCursorLocationHigh)<<8) | + InMDA(mdaCursorLocationLow); + y=pos/80; + x=pos%80; + } + else + { + AH=GET_CURSOR_POSITION_AND_SIZE; + BH=GetPage(); + videoInt(); + y=DH; + x=DL; + } +} + +void TDisplayDOS::GetCursorShape(unsigned &start, unsigned &end) +{ + #if XP_CURSOR_SHAPE_WORKAROUND + static int searchedXP=0, detectedXP; + #endif + + if (dual_display || TScreenDOS::screenMode==7) + { + start=InMDA(mdaCursorStart)*100/charLines; + end =InMDA(mdaCursorEnd)*100/charLines; + return; + } + + #if XP_CURSOR_SHAPE_WORKAROUND + if (!searchedXP) + { + searchedXP=1; + char *OS=getenv("OS"); + detectedXP=(OS && strcmp(OS,"Windows_NT")==0); + } + #endif + + AH=GET_CURSOR_POSITION_AND_SIZE; + BH=GetPage(); + videoInt(); + + if (CX==0x2000) + { + start=end=0; + return; + } + + #if XP_CURSOR_SHAPE_WORKAROUND + /* Andris reported: + "Noticed big nuisance under WinXP Pro: videoInt at + start returns 0x0F0F and as result there is no normal + cursor in TVision applications later. This workarounds + the problem. AP. 26/09/2004)" */ + if (detectedXP && CX==0x0F0F) + CH--; + #endif + + start=CH*100/charLines; + end =CL*100/charLines; +} + +void TDisplayDOS::SetCursorShape(unsigned start, unsigned end) +{ + if (start>=end && getShowCursorEver()) + return; + + unsigned lStart=(start*charLines+50)/100; + unsigned lEnd=(end*charLines+50)/100; + + if (dual_display || TScreenDOS::screenMode==7) + { + if (start<=end) // cursor off + {// Is that really needed? + OutMDA(mdaCursorStart,0x01); + OutMDA(mdaCursorEnd,0x00); + } + else + { + OutMDA(mdaCursorStart,lStart); + OutMDA(mdaCursorEnd,lEnd); + } + return; + } + AH=SET_TEXT_MODE_CURSOR_SHAPE; + BH=GetPage(); + if (start>=end) + CX=0x2000; + else + { + CH=lStart; + CL=lEnd; + } + videoInt(); +} + +// This isn't correctly implemented, but is OK +void TDisplayDOS::ClearScreen(uchar , uchar) +{ + ScreenClear(); +} + +ushort TDisplayDOS::GetRows() +{ + return dual_display ? 25 : ScreenRows(); +} + +ushort TDisplayDOS::GetCols() +{ + return dual_display ? 80 : ScreenCols(); +} + +ushort TDisplayDOS::GetCrtMode() +{ + ushort mode=ScreenMode(); + if (mode==smCO80) + { + // SET: I changed it because was wrong. With STM I can set 108x34 (25% more + // resolution, same aspect) but it reports 3 + int res=getRows()+getCols()*100; + + switch (res) + { + case 8025: + break; + case 8028: + mode+=0x100; + break; + case 8035: + mode+=0x200; + break; + case 8040: + mode+=0x300; + break; + case 8043: + mode+=0x400; + break; + case 8050: + mode+=0x500; + break; + case 8030: + mode+=0x700; + break; + case 8034: + mode+=0x800; + break; + case 9030: + mode+=0x900; + break; + case 9034: + mode+=0xA00; + break; + case 9430: + mode+=0xB00; + break; + case 9434: + mode+=0xC00; + break; + case 8225: + mode+=0xD00; + break; + default: // We can reproduce it but isn't mode 3 so if the user_mode + // is 3 we MUST do a mode change. + mode+=0xFF00; + } + } + return mode; +} + + +/***************************************************************************** + Helper routines +*****************************************************************************/ + +void TDisplayDOS::setVideoModeInt() +{ + // Windows NT workaround, looks like is something that happends in my + // machine but happends. + // I tested Windows NT 4.0 spanish, spanish+SP3 and english running in a + // TXProII motherboard with a M571 SYS integrated video chip using AMI + // BIOS and a K6 233 CPU. The fact is that NT clobbers the time after + // setting the video mode, the value that appears is around 512 hours and + // looks like that's enough to produce a "divide overflow" exception in the + // emulated DOS, it kills the djgpp application. + unsigned long v1=_farpeekl(_dos_ds,0x46C); + + videoInt(); + + unsigned long v2=_farpeekl(_dos_ds,0x46C); + if (v2-v1>65536) + { // Come on, switching video modes can't take 1 hour ;-))) + _farpokel(_dos_ds,0x46C,v1+5); + } +} + +int TDisplayDOS::getCharLines() +{ + AX=0x1130; + BL=0; + videoInt(); + return CL; + #if 0 + // Some parts of the code used it, but I switched to BIOS version. + // I guess here we can trust BIOS, we'll see. + outp(0x3D4,9); // CRTC 9 + return (inp(0x3D5) & 0x1F)+1; // lines per char + #endif +} + +/***************************************************************************** + VESA and user provided video modes routines +*****************************************************************************/ + +void TDisplayDOS::setTextMode(int mode) +{ + if (mode>=0x100) + { // It should be a VESA mode + AX=0x4F02; + BX=mode | 0x8000; // do not clear the screen + } + else + { + AX=(mode & 0xff) | 0x80; // do not clear the screen + } + setVideoModeInt(); + charLines=getCharLines(); +} + +/***************************************************************************** + Tweaked video modes routines +*****************************************************************************/ + +const int numTweakedModes=7; +const int tw80x30=0, tw80x34=1, tw90x30=2, tw90x34=3, tw94x30=4, tw94x34=5, + tw82x25=6; // that's a replacement for 80x25 but with 8 pixels fonts + +// Size of the available modes +static ushort width[] ={80,80,90,90,94,94,82}; +static ushort height[]={30,34,30,34,30,34,25}; + +/* How to interpret the data, 80x30 example: + 0x0c11, Enable writes to index 0-7 + 0x5f00, 0x5F+5 = 100 = total horizontal chars + 0x4f01, 0x4F+1 = 80 = displayed horizontal chars + 0x5002, 0x50 = 80 = start of horizontal blank + 0x8203, b7: enable access to 10 and 11 b5-b6: Horiz. delay = 0 + b0-b4 low bits of horiz blank end (2). + 0x5504, 0x55 = 85 = start of retrace. + 0x8105, b7: b5 of horiz blank end => 100010 = 34 (80+34-100=14) + 0x0b06, Vertical total (low 8 bits) + 0x3e07, b5: b9 VT, b0: b8 VT => Vertical total 1000001011=523 + b7: b9 VRS, b2: b8 VRS => 01 + b6: b9 VDE, b1: b8 VDE => 01 + b3: b8 VBS => 1 + 0x4f09, b0-4: 15+1=16 lines characters b5: b9 VBS b6: b9 LCR b7: No double scan + 0xea10, Vertical retrace start 0xEA => 0x1EA = 490 + 0x8c11, Disable access to 0-7, Vertical retrace ends when low bits are 0xC + 0xdf12, Vertical Display End 0xDF => 0x1DF = 479 (I think is 16*30=480 -1) + 0x2813, 0x28 = 40 => 40*2 = 80 characters per line + 0xe715, Vertical Blank Start 0xE7 => 0x1E7 = 487 + 0x0416 Vertical Blank End 4 +*/ +static unsigned short ttweaks[][16]= +{ + { /* 80x30 */ + 0x0c11,0x5f00,0x4f01,0x5002,0x8203,0x5504,0x8105,0x0b06, + 0x3e07,0x4f09,0xea10,0x8c11,0xdf12,0x2813,0xe715,0x0416 + }, + { /* 80x34 */ + 0x0c11,0x5f00,0x4f01,0x5002,0x8203,0x5504,0x8105,0x0b06, + 0x3e07,0x4d09,0xea10,0x8c11,0xdf12,0x2813,0xe715,0x0416 + }, + { /* 90x30 */ + 0x0c11,0x6d00,0x5901,0x5a02,0x9003,0x6004,0x8b05,0x0b06, + 0x3e07,0x4f09,0xea10,0x8c11,0xdf12,0x2d13,0xe715,0x0416 + }, + { /* 90x34 */ /* Corrected for 476 lines, SET */ + 0x0c11,0x6d00,0x5901,0x5a02,0x9003,0x6004,0x8b05,0x0b06, + 0x3e07,0x4d09,0xea10,0x8c11,0xdb12,0x2d13,0xe715,0x0416 + }, + { /* 94x30 */ + 0x0c11,0x6c00,0x5d01,0x5e02,0x8f03,0x6204,0x8e05,0x0b06, + 0x3e07,0x4f09,0xea10,0x8c11,0xdf12,0x2f13,0xe715,0x0416 + }, + { /* 94x34 */ /* Corrected for 476 lines, SET */ + 0x0c11,0x6c00,0x5d01,0x5e02,0x8f03,0x6204,0x8e05,0x0b06, + 0x3e07,0x4d09,0xea10,0x8c11,0xdb12,0x2f13,0xe715,0x0416 + }, + { /* 82x25 */ + 0x0c11,0x6100,0x5101,0x5202,0x8203,0x5704,0x8105,0xb406, + 0x1f07,0x4f09,0x9a10,0x8c11,0x8f12,0x2913,0x9715,0x0016 + } +}; + +int TDisplayDOS::setTweakedMode(int tmode) +{ + int i; + volatile int junk; + + if (tmode>=numTweakedModes) + return -1; + + AX=0x3 | 0x80; // do not clear the screen + setVideoModeInt(); + + if (height[tmode]==34) + { + TScreenDOS::SelectFont(14,True); // load 8x14 font for 34 line modes + charLines=14; + } + else + {// Tweaked uses BIOS and hence have the 8/9x16 fonts loaded so avoid a + // reload + TScreenDOS::SelectFont(16); + charLines=16; + } + + // wait for vertical retrace + while ((inportb(0x3da) & 8)!=0); + while ((inportb(0x3da) & 8)==0); + + disable(); + if (tmode==tw82x25) + outportb(0x3c2,0x63); // 400 lines, 25 MHz + else + outportb(0x3c2,0xe7); // 480 lines, 28 MHz + // set sequencer clocking mode + outportw(0x3c4,0x101); + // reset data flip-flop to address mode + junk=inportw(0x3da); + outportb(0x3c0,0x30); + // set mode control register + outportb(0x3c0,0x04); + outportb(0x3c0,0x33); + // set horizontal pixel pan + outportb(0x3c0,0x00); + for(i = 0; i < 16; i++) + outportw(0x3d4,ttweaks[tmode][i]); + // update BIOS data area + _farsetsel(_dos_ds); + _farnspokew(0x44a,width[tmode]); + _farnspokeb(0x484,height[tmode]-1); + // We must indicate the correct height. Some BIOSes make the cursor + // invisible if we forget it. + _farnspokew(0x485,charLines); + _farnspokew(0x44c,width[tmode]*height[tmode]*2); + enable(); + + return 0; +} + +/***************************************************************************** + Extended video modes routines (80x 28,35,40,43,50) +*****************************************************************************/ +/* + The following code is based on what conio.c does, Robert used it + to avoid clearing the screen. I modified it a lot and added the + propper fonts handling. + + Note we assumed the board is VGA and it will fail for EGA and MDA. +*/ + +// 0: 200, 1: 350, 2: 400 +const int scl200=0, scl350=1, scl400=2; + +/* Set screen scan lines and load appropriate font. + SCAN_LINES and FONT is the height. + SCAN_LINES is as required by Int 10h function 12h. */ +void TDisplayDOS::setExtendedMode(int mode) +{ + // Default mode is almost mode 0 + int scanLines=scl400; + charLines=16; + Boolean Force=True; + + switch (mode) + { + case 0: // 25 lines + // EGA: setScanLinesAndFont(scl350,14,1); + Force=False; + break; + case 1: // 28 lines VGA only + charLines=14; + break; + case 2: // 35 lines EGA or VGA + scanLines=scl350; + charLines=10; + break; + case 3: // 40 lines VGA only + charLines=10; + break; + case 4: // 43 lines EGA or VGA + scanLines=scl350; + charLines=8; + break; + case 5: // 50 lines VGA only + charLines=8; + break; + } + // Set 200/350/400 scan lines. + AH=ALTERNATE_FUNCTION_SELECT; + AL=scanLines; + BL=SELECT_VERTICAL_RESOLUTION; + videoInt(); + + // Scan lines setting only takes effect when video mode is set. + AX=0x83; + setVideoModeInt(); + + TScreenDOS::SelectFont(charLines,Force); +} +/****************************************************************************/ + +/**[txh]******************************************************************** + + Description: + Used to test if a mode that we don't know can be handled by the driver +or not. If the mode uses an unknown memory region we just assume that's +a graphics mode and revert to 80x25. It could be enhanced a lot specially to +support VESA video modes when implemented in a way that the video memory +isn't located at the usual address. + +***************************************************************************/ + +void TDisplayDOS::testForSupport() +{ + // Write a ! at 0,0 position in the video memory + // That's a guess, we don't know if that's a real text mode. + _farpokeb(_dos_ds,ScreenPrimary,'!'); + AX=0x200; // Set cursor position + BH=0; // Page 0 + DX=0; // X=Y=0 + videoInt(); + AH=0x0A; // Write character only at cursor position + AL=' '; // A space to overwrite the ! + BH=0; // Page 0 + CX=1; // Just once + videoInt(); + // Check if BIOS changed what we think is 0,0 coordinate + if (_farpeekb(_dos_ds,ScreenPrimary)!=' ') + {// Nope, BIOS can't do it. + // Here we assume this isn't a real text mode and revert to 80x25 + setTextMode(smCO80); + emulateMouse=0; + } + else + {// As this mode could be anything strange we can't assume the mouse driver + // can draw the mouse. That's common for VESA modes. + // So we draw the cursor `by hand'. + emulateMouse=1; + } +} + +/**[txh]******************************************************************** + + Description: + Sets a video mode from the video mode number. Video modes with the low +nibble equal 3 are used to encode extended and tweacked video modes. Note +that VESA 800x600x256 mode is 0x103 and here it is assumed to be extended +mode 1, that's 80x28. Also note that regular VGA 80x25 mode is the +"extended mode 0".@* + Any other value is assumed to be a user provided video mode and is +accepted only if we are sure that's really text mode and we know how to +handle it. + +***************************************************************************/ + +void TDisplayDOS::SetCrtMode(ushort mode) +{ + if (TMouse::present()) + TMouse::hide(); + + if (mode==smFont8x8) // Looks like Borland TV 2.0 defined it + mode=smCO80x50; + // Extended and tweaked modes are numbered Mode<<8 | smCO80 + // 0-6 are extended modes. + // 7-13 are tweaked modes. + if ((mode & 0xFF)==smCO80) + { + int hmode=mode>>8; + if (hmode>6 && hmode<14) + { + setTweakedMode(hmode-7); + emulateMouse=1; + } + else + { + setExtendedMode(hmode); + emulateMouse=0; + } + } + else + { + setTextMode(mode); + testForSupport(); + TScreenDOS::SelectFont(charLines); + } + + if (TMouse::present()) + { + THWMouseDOS::setEmulation(emulateMouse); + TMouse::setRange(getCols()-1,getRows()-1); + TMouse::show(); + } + if (paletteModified) + SetDisPaletteColors(0,16,ActualPalette); +} + + +void TDisplayDOS::SetCrtModeExt(char *command) +{ + // Should we hide the mouse here? [Added TV 2.0.0] + if (TMouse::present()) + TMouse::hide(); + + system(command); + testForSupport(); + charLines=getCharLines(); + TScreenDOS::SelectFont(charLines); + // Don't trust in the driver [Added TV 2.0.0] + emulateMouse=1; + + if (TMouse::present()) + { + THWMouseDOS::setEmulation(emulateMouse); + TMouse::setRange(getCols()-1,getRows()-1); + TMouse::show(); + } +} + +int TDisplayDOS::SetCrtModeRes(unsigned w, unsigned h, int fW, int fH) +{ + if (w==TScreen::screenWidth && h==TScreen::screenHeight) return 0; + // DOS can't do it so we just select the closest mode available + unsigned pos; + Boolean exact=searchClosestRes(dosModesRes,w,h,TDisplayDOSModesNum,pos); + SetCrtMode(dosModes[pos]); + return exact && dosModesCell[pos].x==(unsigned)fW && + dosModesCell[pos].y==(unsigned)fH ? 1 : 2; +} + +/**[txh]******************************************************************** + + Description: + Finds the main window title if we are running under W95 and windowed. + + Return: + A pointer to a newly allocated string (new[]). Or 0 if fail. by SET. + +***************************************************************************/ + +const char *TDisplayDOS::GetWindowTitle(void) +{ + // Winoldap Get Title. + AX=0x168E; + DX=2; + // Size of transfer buffer + unsigned long tbsize=_go32_info_block.size_of_transfer_buffer; + CX=tbsize>0xFFFF ? 0xFFFF : tbsize; // Can tbsize be > 64Kb? + // Address of tb + DI=__tb & 0x0f; // It should be 0 + ES=(__tb>>4) & 0xffff; + + __dpmi_int(0x2F,&r); + + if (AX!=1) + return 0; + + // Scan to get the length + _farsetsel(_dos_ds); + unsigned i; + for (i=0; i>4) & 0xffff; + // Copy to tb + strncpy(title,name,mxTitleSize); + title[mxTitleSize-1]=0; + dosmemput(title,mxTitleSize,__tb); + + __dpmi_int(0x2F,&r); + + return AX; +} + +void TDisplayDOS::getPaletteMap(char *map) +{ + AX=READ_ALL_PALETTE_REGISTERS_AND_OVERSCAN_REGISTER; + ES=__tb>>4; + DX=__tb & 0xF; + videoInt(); + dosmemget(__tb,17,map); +} + +void TDisplayDOS::setOnePaletteIndex(int index, TScreenColor *col) +{ + AX=SET_INDIVIDUAL_DAC_REGISTER; + BX=colorsMap[index]; + DH=col->R>>2; CH=col->G>>2; CL=col->B>>2; + videoInt(); +} + +void TDisplayDOS::getOnePaletteIndex(int index, TScreenColor *col) +{ + AX=READ_INDIVIDUAL_DAC_REGISTER; + BL=colorsMap[index]; + videoInt(); + col->R=DH<<2; + col->G=CH<<2; + col->B=CL<<2; +} + +int TDisplayDOS::SetDisPaletteColors(int from, int number, TScreenColor *colors) +{ + int ret=number; + while (number-- && from<16) + setOnePaletteIndex(from++,colors++); + return ret; +} + +void TDisplayDOS::GetDisPaletteColors(int from, int number, TScreenColor *colors) +{ + while (number-- && from<16) + getOnePaletteIndex(from++,colors++); +} + +void TDisplayDOS::Beep() +{ + sound(1000); + delay(100); + nosound(); +} + +void TDisplayDOS::Init() +{// Currently we assume it doesn't change. + getPaletteMap(colorsMap); + // Memorize original palette + GetDisPaletteColors(0,16,OriginalPalette); + // That's the current + memcpy(ActualPalette,OriginalPalette,sizeof(ActualPalette)); + + TDisplay::setCursorPos=SetCursorPos; + TDisplay::getCursorPos=GetCursorPos; + TDisplay::getCursorShape=GetCursorShape; + TDisplay::setCursorShape=SetCursorShape; + TDisplay::clearScreen=ClearScreen; + TDisplay::getRows=GetRows; + TDisplay::getCols=GetCols; + TDisplay::setCrtMode=SetCrtMode; + TDisplay::getCrtMode=GetCrtMode; + TDisplay::setCrtModeExt=SetCrtModeExt; + TDisplay::setCrtModeRes_p=SetCrtModeRes; + TDisplay::getWindowTitle=GetWindowTitle; + TDisplay::setWindowTitle=SetWindowTitle; + TDisplay::setDisPaletteColors=SetDisPaletteColors; + TDisplay::getDisPaletteColors=GetDisPaletteColors; + TDisplay::beep=Beep; +} + +TDisplayDOS::~TDisplayDOS() {} + +#else // DJGPP + +#include +#include + +#endif // else DJGPP + diff --git a/tvision/classes/dos/doskey.cc b/tvision/classes/dos/doskey.cc new file mode 100644 index 0000000..e9cac74 --- /dev/null +++ b/tvision/classes/dos/doskey.cc @@ -0,0 +1,543 @@ +/**[txh]******************************************************************** + + Keyboard handler for DOS. + Copyright (c) 1998-2004 by Salvador E. Tropea (SET) + + Description: + This module implements the low level keyboard routines for DOS. + The original comment about the first TGKey class I sent to Robert when was +the maintainer of TV is located at the end of this file. It have some +intersting information. + + Configuration variables: + BIOSKey + +***************************************************************************/ + +#include + +#define Uses_ctype +#define Uses_TEvent +#define Uses_TGKey +#define Uses_FullSingleKeySymbols +#define Uses_string +#define Uses_TScreen +#include + +// I delay the check to generate as much dependencies as possible +#ifdef TVCompf_djgpp + +#include +#include +#include +#include +#include +#define REGS __dpmi_regs +#define INTR(nr,r) __dpmi_int(nr,&r) + +#define DEF_REGS __dpmi_regs r +#define KEY_INTR() __dpmi_int(0x16,&r) +#define AH r.h.ah +#define AX r.x.ax + +#include + +#define GET_ENHANCED_KEYSTROKE 0x0010 +#define GET_EXTENDED_SHIFT_STATES 0x0012 +// Keyboard definitions: +#define KEYBOARD_STATUS_FLAGS_1 0x0417 +// Bitfields for keyboard status flags 1: +// Bit(s) Description (Table M010) +// 7 INSert active +// 6 Caps Lock active +// 5 Num Lock active +// 4 Scroll Lock active +// 3 either Alt pressed +// 2 either Ctrl pressed +// 1 Left Shift pressed +// 0 Right Shift pressed +#define KBD_POINTER_TO_NEXT_CHAR_IN_KBD_BUF 0x041A +#define KBD_POINTER_TO_FIRST_FREE_SLOT_IN_BUF 0x041C +// KM00400080 - KEYBOARD BUFFER START OFFSET FROM SEGMENT 40h (normally 1Eh) +#define KEYBOARD_BUFFER_START_OFFSET 0x0480 +// KM00400082 - KEYBOARD BUFFER END+1 OFFSET FROM SEGMENT 40h (normally 3Eh) +#define KEYBOARD_BUFFER_END_1_OFFSET 0x0482 + + +KeyType TGKeyDOS::rawCode; +int TGKeyDOS::Abstract; +char TGKeyDOS::ascii; +char TGKeyDOS::useFixKbdBuffer; +ushort TGKeyDOS::sFlags; +int TGKeyDOS::useBIOS=0; +int TGKeyDOS::translateKeyPad=1; +void (*TGKeyDOS::GetRaw)(void)=GetRawDirect; + +const uchar TGKeyDOS::kbWithASCII0[256]= +{ + kbPause,kbEsc,kb1,kb2,kb3,kb4,kb5,0, // 00-07 + kb7,kb8,kb9,kb0,0,kbEqual,kbBackSpace,kbTab, // 08-0F + kbQ,kbW,kbE,kbR,kbT,kbY,kbU,kbI, // 10-17 + kbO,kbP,kbOpenBrace,kbCloseBrace,kbEnter,0,kbA,kbS, // 18-1F + kbD,kbF,kbG,kbH,kbJ,kbK,kbL,kbColon, // 20-27 + kbQuote,kbGrave,0,kbBackSlash,kbZ,kbX,kbC,kbV, // 28-2F + kbB,kbN,kbM,kbComma,kbStop,kbSlash,0,kbAsterisk, // 30-37 + 0,kbSpace,0,kbF1,kbF2,kbF3,kbF4,kbF5, // 38-3F + kbF6,kbF7,kbF8,kbF9,kbF10,0,0,kbHome, // 40-47 + kbUp,kbPgUp,kbMinus,kbLeft,kb5,kbRight,kbPlus,kbEnd, // 48-4F + kbDown,kbPgDn,kbInsert,kbDelete,kbF1,kbF2,kbF3,kbF4, // 50-57 + kbF5,kbF6,kbF7,kbF8,kbF9,kbF10,kbF1,kbF2, // 58-5F + kbF3,kbF4,kbF5,kbF6,kbF7,kbF8,kbF9,kbF10, // 60-67 + kbF1,kbF2,kbF3,kbF4,kbF5,kbF6,kbF7,kbF8, // 68-6F + kbF9,kbF10,kbPrnScr,kbLeft,kbRight,kbEnd,kbPgDn,kbHome, // 70-77 + kb1,kb2,kb3,kb4,kb5,kb6,kb7,kb8, // 78-7F + kb9,kb0,kbMinus,kbEqual,kbPgUp,kbF11,kbF12,kbF11, // 80-87 + kbF12,kbF11,kbF12,kbF11,kbF12,kbUp,kbMinus,kb5, // 88-8F + kbPlus,kbDown,kbInsert,kbStop,kbTab,kbSlash,kbAsterisk,kbHome, // 90-97 + kbUp,kbPgUp,0,kbLeft,0,kbRight,0,kbEnd, // 98-9F + kbDown,kbPgDn,kbInsert,kbDelete,kbSlash,kbTab,kbEnter,kbMacro, // A0-A7 + // I don't know if the following will be used: + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0 +}; + +// This table uses just some values +const uchar TGKeyDOS::kbWithASCIIE0[256]= +{ + 0,0,0,0,0,0,0,0, // 00-07 + 0,0,0,0,0,0,0,0, // 08-0F + 0,0,0,0,0,0,0,0, // 10-17 + 0,0,0,0,0,0,0,0, // 18-1F + 0,0,0,0,0,0,0,0, // 20-27 + 0,0,0,0,0,0,0,0, // 28-2F + 0,0,0,0,0,0,0,0, // 30-37 + 0,0,0,0,0,0,0,0, // 38-3F + 0,0,0,0,0,0,0,kbHome, // 40-47 + kbUp,kbPgUp,0,kbLeft,0,kbRight,0,kbEnd, // 48-4F + kbDown,kbPgDn,kbInsert,kbDelete,0,0,0,0, // 50-57 + 0,0,0,0,0,0,0,0, // 58-5F + 0,0,0,0,0,0,0,0, // 60-67 + 0,0,0,0,0,0,0,0, // 68-6F + 0,0,0,kbLeft,kbRight,kbEnd,kbPgDn,kbHome, // 70-77 + 0,0,0,0,0,0,0,0, // 78-7F + 0,0,0,0,kbPgUp,0,0,0, // 80-87 + 0,0,0,0,0,kbUp,0,0, // 88-8F + 0,kbDown,kbInsert,kbDelete,0,0,0,0, // 90-97 + 0,0,0,0,0,0,0,0, // 98-9F + 0,0,0,0,0,0,0,0, // A0-A7 + 0,0,0,0,0,0,0,0, // A8-AF + // Here are keys from the 105 keys keyboards. + 0,0,0,0,0,0,kbWinLeft,kbWinRight, // B0-B7 + kbWinSel,0,0,0,0,0,0,0, // B8-BF + 0,0,kbWinLeft,kbWinRight,kbWinSel,0,0,0, // C0-C7 + 0,0,0,0,0,0,kbWinLeft,kbWinRight, // C8-CF + kbWinSel,0,0,0,0,0,0,0, // D0-D7 + 0,0,kbWinLeft,kbWinRight,kbWinSel,0,0,0, // D8-DF + 0,0,0,0,0,0,0,0, // E0-E7 + 0,0,0,0,0,0,0,0, // E8-EF + 0,0,0,0,0,0,0,0, // F0-F7 + 0,0,0,0,0,0,0,0 // F8-FF +}; + +unsigned TGKeyDOS::GetShiftStateBIOS(void) +{ + DEF_REGS; + AH=GET_EXTENDED_SHIFT_STATES; + KEY_INTR(); + return AX; +} + +unsigned TGKeyDOS::GetShiftStateDirect(void) +{ + _farsetsel(_dos_ds); + return _farnspeekw(KEYBOARD_STATUS_FLAGS_1); +} + +// All the info. from BIOS in one call +void TGKeyDOS::GetRawBIOS(void) +{ + DEF_REGS; + AH=GET_EXTENDED_SHIFT_STATES; + KEY_INTR(); + sFlags=AX; + AH=GET_ENHANCED_KEYSTROKE; + KEY_INTR(); + rawCode.full=AX; +} + +void TGKeyDOS::GetRawDirect(void) +{ + _farsetsel(_dos_ds); + sFlags=_farnspeekw(KEYBOARD_STATUS_FLAGS_1); + ushort keybuf_nextchar=_farnspeekw(KBD_POINTER_TO_NEXT_CHAR_IN_KBD_BUF); + rawCode.full=_farnspeekw(0x400+keybuf_nextchar); + keybuf_nextchar+=2; + if (useFixKbdBuffer) + { + if (keybuf_nextchar>=0x3e) + keybuf_nextchar=0x1e; + } + else + { + if (keybuf_nextchar>=_farnspeekw(KEYBOARD_BUFFER_END_1_OFFSET)) // if past the buffer... + keybuf_nextchar=_farnspeekw(KEYBOARD_BUFFER_START_OFFSET); // ...wrap to it's start + } + _farnspokew(KBD_POINTER_TO_NEXT_CHAR_IN_KBD_BUF,keybuf_nextchar); +} + + +// The intelligence is here +unsigned short TGKeyDOS::GKey(void) +{ + Abstract=0; + + GetRaw(); + // Compose the shift flags: + + if (sFlags & 3) + Abstract|=kbShiftCode; + if (sFlags & 4) + Abstract|=kbCtrlCode; + switch (AltSet) + { + case 0: // Normal thing, left is left, right is right + if (sFlags & 0x200) + Abstract|=kbAltLCode; + else + if (sFlags & 8) + Abstract|=kbAltRCode; + break; + case 1: // Reverse thing + if (sFlags & 0x200) + Abstract|=kbAltRCode; + else + if (sFlags & 8) + Abstract|=kbAltLCode; + break; + default: // Compatibility + if (sFlags & 0x208) + Abstract|=kbAltLCode; + } + + // Translate the rest + if (rawCode.b.scan==0) + { + if (rawCode.b.ascii==0) + { // Very singular 00/00 + Abstract|=kbPause; + ascii=0; + } + else + { // Generated by Alt-key pad or a TSR + ascii=rawCode.b.ascii; + Abstract|=kbUnkNown; + } + } + else + if (rawCode.b.ascii==0 || rawCode.b.ascii==0xF0) + { // Alt keys and other strange things + Abstract|=kbWithASCII0[rawCode.b.scan]; + ascii=0;//rawCode.b.scan; That's good bur annoying, so now I return 0 + } + else + if (rawCode.b.ascii==0xE0) + { + Abstract|=kbWithASCIIE0[rawCode.b.scan]; + ascii=0;//rawCode.b.scan; + } + else + { // That's the rest, they are translated by the ASCII because depends + // on the keyboard layout. + ascii=rawCode.b.ascii; +#if 0 + // Making that I lose: + // ^H == BackSpace, ^I == Tab, ^J == ^Enter, ^M == Enter, ^[ == Esc + if (rawCode.b.ascii<128) + Abstract|=kbByASCII[rawCode.b.ascii]; +#else + // As ^J and ^[ are very used by me I preffer that: + if (rawCode.b.ascii<128) + { + unsigned char val=kbByASCII[rawCode.b.ascii]; + if (val<128) + { + // I think the following is a bug in the BIOS: Numlock OFF then + // key pad 6 is right, OK, but if you press shift+6 you get the + // ASCII of 6!!!! + if (translateKeyPad && rawCode.b.ascii>='0' && + rawCode.b.ascii<='9' && (Abstract & kbShiftCode)) + Abstract|=kbWithASCIIE0[rawCode.b.scan]; + else + Abstract|=val; + } + else + { + val&=0x7F; + #define KC(a,c) case a: if (sFlags & 4) Abstract|=val; \ + else Abstract|=c; break; + switch (val) + { + KC(kbH,kbBackSpace) + KC(kbI,kbTab) + KC(kbM,kbEnter) + // Here I assume that ESC, ENTER and pENTER doesn't change from + // keyboard to keyboard + case kbOpenBrace: + if (rawCode.b.scan==1) + Abstract|=kbEsc; + else + Abstract|=val; + break; + case kbJ: + if (rawCode.b.scan==0x1C || rawCode.b.scan==0xE0) + Abstract|=kbEnter; + else + Abstract|=val; + break; + } + #undef KC + } + } +#endif + } + return rawCode.full; +} + +int TGKeyDOS::KbHitBIOS(void) +{ + return bioskey(1); +} + +int TGKeyDOS::KbHitDirect(void) +{ + return (_farpeekw(_dos_ds,KBD_POINTER_TO_NEXT_CHAR_IN_KBD_BUF) + !=_farpeekw(_dos_ds,KBD_POINTER_TO_FIRST_FREE_SLOT_IN_BUF)); +} + +void TGKeyDOS::ClearBIOS(void) +{ + while (kbhit()) + GKey(); + // the bios has no function for clearing the key buffer + // But you can loop until is empty ;-) +} + +void TGKeyDOS::ClearDirect(void) +{ + if (useFixKbdBuffer) + _farpokel(_dos_ds,KBD_POINTER_TO_NEXT_CHAR_IN_KBD_BUF,0x001E001EUL); + else + { + _farsetsel(_dos_ds); + ulong keybuf_start=_farnspeekw(KEYBOARD_BUFFER_START_OFFSET); + _farnspokel(KBD_POINTER_TO_NEXT_CHAR_IN_KBD_BUF,(keybuf_start<<16)+keybuf_start); + } +} + +void TGKeyDOS::FillTEvent(TEvent &e) +{ + GKey(); + e.keyDown.charScan.charCode=ascii; + e.keyDown.charScan.scanCode=rawCode.b.scan; + e.keyDown.raw_scanCode=rawCode.b.scan; + e.keyDown.keyCode=Abstract; + e.keyDown.shiftState=sFlags; + e.what=evKeyDown; +} + +void TGKeyDOS::SetKbdMapping(int version) +{ + if (version==dosUseBIOS) + { + useBIOS=1; + TGKey::kbhit=KbHitBIOS; + TGKey::getShiftState=GetShiftStateBIOS; + TGKey::clear=ClearBIOS; + GetRaw=GetRawBIOS; + return; + } + else if (version==dosUseDirect) + { + useBIOS=0; + TGKey::kbhit=KbHitDirect; + TGKey::getShiftState=GetShiftStateDirect; + TGKey::clear=ClearDirect; + GetRaw=GetRawDirect; + return; + } + else if (version==dosTranslateKeypad) + { + translateKeyPad=1; + } + else if (version==dosNormalKeypad) + { + translateKeyPad=0; + } + Mode=version; +} + +int TGKeyDOS::GetKbdMapping(int version) +{ + if (version==dosUseBIOS) + { + return useBIOS; + } + else if (version==dosUseDirect) + { + return !useBIOS; + } + else if (version==dosTranslateKeypad) + { + return translateKeyPad; + } + else if (version==dosNormalKeypad) + { + return !translateKeyPad; + } + return 0; +} + +void TGKeyDOS::Init() +{ + AltSet=2; + TGKey::gkey=GKey; + TGKey::fillTEvent=FillTEvent; + TGKey::SetKbdMapping=SetKbdMapping; + TGKey::GetKbdMapping=GetKbdMapping; + // Default to direct mode + long useBIOS=0; + TScreen::optSearch("BIOSKey",useBIOS); + SetKbdMapping(useBIOS ? dosUseBIOS : dosUseDirect); + // SET: Original code assumed the circular buffer starts at offset 0x1E and + // ends at offset 0x3D. But some utilities to grow the buffer exists. + // Egon Eckert contributed a patch to fix it. + // As it was incorporated between 2.0.3 RC1 and 2.0.3 I added an option to + // rollback without recompiling. + long aux=0; + TScreen::optSearch("FixKbdBuffer",aux); + useFixKbdBuffer=aux!=0; +} + +//---------------- TEST +#ifdef GKEY +#include + +void InterpretAbstract(void) +{ + int key=TGKey::Abstract & kbKeyMask; + printf("Abstract: kb%s",TGKey::KeyNames[key]); + if (TGKey::Abstract & kbShiftCode) + printf(" SHIFT"); + if (TGKey::Abstract & kbCtrlCode) + printf(" CTRL"); + if (TGKey::Abstract & kbAltRCode) + printf(" ALT-R"); + if (TGKey::Abstract & kbAltLCode) + printf(" ALT-L"); +} + +#include +#include +/* ungetch() is available only on DJGPP +static void PasarAC(int Sig) +{ + Sig=0; +}*/ +#undef kbhit +void CtrlCOff(void) +{ + //signal(SIGINT,PasarAC); + signal(SIGINT,SIG_IGN); +} + +int count=0; + +int main(int argc, char *argv[]) +{ + unsigned short key=0; + TGKey::useBIOS=0; + CtrlCOff(); + // Setup the mode where the alt left/right are different + TGKey::SetAltSettings(0); + do + { + while (!TGKey::kbhit());// {count++; if ((count%1000)==0) printf(".");} + TEvent e; + TGKey::fillTEvent(e); + if (e.what!=evNothing) + { + key = TGKey::Abstract; + printf("Shiftstate: %04x RawCode: %04x ASCII: %X SCAN: %04X\r\n", + TGKey::sFlags,key,key & 0xff,e.keyDown.raw_scanCode); + InterpretAbstract(); + printf(" ASCII: %c\r\n",TGKey::ascii); + } + } while (key!=kbEsc); +} +#endif + +#else // TVCompf_djgpp + +#include + +#endif // else TVCompf_djgpp + +/* + That's a gkey function that is supposed to: + +1) Solve all the problems about multiple translations. That's because it +generates a unique code for each key. The format is: + +bit 10 9 8 7 6-0 +Left-Alt Right-Alt Ctrl Shift Code + + Additionally there are a char value to carry the ASCII. + I'm detecting left and right alt but perhaps isn't good. The idea of +detecting it is that Left Alt could be used for the menu and Right Alt +(called Alt Gr in some keyboards) can be used for macros. + But I think it will confuse to some people, what do you think? + +2) Solve the keyboard layout problems. This routines uses a methode that +works OK with M$ keyb TSR. Keyb is relative smart and translates the Alt-X +codes, that's needed because the Alt keys are ASCII 0 and we need the scan +to differenciate one from the others. Keyb translates it. + I tried with keyb gr and worked perfect. + The main idea is just use ASCII for the things is possible and scans for +the rest, keyb takes care about the thing that can't be detected using +ASCIIs. + +3) Solve the problem of the numeric pad. BIOS makes the work. + + The code is very fast because uses a few comparissons and look-up tables, +we don't need long switchs. The only exception is done to avoid the loose +of ^H,^I,^J,^M and ^[. For that I suppose some things and guess about what +key was. + +Important! +i) Some constants have crazy names, take a look I used the first +name that came to my mind. +ii) Some ^symbol assigments aren't well mapped by keyb so they are very +specific cases that I think doesn't mather. + + Now, from the side of the editor: + + This methode generates 2048 key combinations, only a part can be really +triggered because a lot are like !, is impossible to get other thing that +Shift-! because you MUST press shift to get it, additionally Shift-1 doesn't +exist because you'll get Shift-!. That is logic because not all keyboards +have the relation Shift-1==!. So only some combinations can be used for +commands, the rest must mean: Insert a character with the ASCII provided. + For the rest I think the system can be used. + +Note: I did a TSR to detect 19 key combinations that BIOS doesn't report, +takes only 400 bytes of memory. +*/ diff --git a/tvision/classes/dos/dosmouse.cc b/tvision/classes/dos/dosmouse.cc new file mode 100644 index 0000000..79f7257 --- /dev/null +++ b/tvision/classes/dos/dosmouse.cc @@ -0,0 +1,521 @@ +/**[txh]******************************************************************** + + Copyright (c) 2001-2002 by Salvador E. Tropea + Based on code Copyright 1996-1998 by Robert H”hne. + + Description: + DOS mouse drivers. Completly reworked by Salvador E. Tropea. + Based on concepts by Jose Angel Sanchez Caso (JASC) and code by Robert +H”hne. + Important: + 1) The registerHandler member can only register TEventQueue::mouseInt. + 2) The code lock for TEventQueue::mouseInt and CLY_Ticks is fuzzy, I + incressed the locked area to 1 Kb but it should adjusted. + + The DOS/PollMouse configuration option forces mouse polling. + +***************************************************************************/ + +#include + +#ifdef TVCompf_djgpp + #include +#endif +#define Uses_string +#define Uses_stdlib +#define Uses_stdio +#define Uses_TEvent +#define Uses_TEventQueue +#define Uses_TScreen +#include + +// I delay the check to generate as much dependencies as possible +#ifdef TVCompf_djgpp + +#include +#include +#include +#include + +#include + +#define REGS __dpmi_regs +#define INTR(nr,r) __dpmi_int(nr,&r) +#define AX r.x.ax +#define BX r.x.bx +#define CX r.x.cx +#define DX r.x.dx +#define ES r.x.es +#define LD(x) _go32_dpmi_lock_data((void *)&x,sizeof(x)) +//#define SHOW_COUNT() ((short)(_farpeekw(mouse_buffer_selector,118))) + +// MS-Mouse services: [Thanks to Ralf Brown] +#define RESET_DRIVER_AND_READ_STATUS 0x0000 +// MS-Mouse v1.0+ services +#define SHOW_MOUSE_CURSOR 0x0001 +#define HIDE_MOUSE_CURSOR 0x0002 +#define RETURN_POSITION_AND_BUTTON_STATUS 0x0003 +#define POSITION_MOUSE_CURSOR 0x0004 +#define DEFINE_HORIZONTAL_CURSOR_RANGE 0x0007 +#define DEFINE_VERTICAL_CURSOR_RANGE 0x0008 +// MS-Mouse v3.0+ services +#define EXCHANGE_INTERRUPT_SUBROUTINES 0x0014 +// MS-Mouse v6.0+ services +#define RETURN_DRIVER_STORAGE_REQUIREMENTS 0x0015 +#define SAVE_DRIVER_STATE 0x0016 +#define RESTORE_DRIVER_STATE 0x0017 +#define SET_ALTERNATE_MOUSE_USER_HANDLER 0x0018 +#define RETURN_USER_ALTERNATE_INTERRUPT_VECTOR 0x0019 + +char THWMouseDOS::useMouseHandler=1; +char THWMouseDOS::emulateMouse=0; +uchar THWMouseDOS::myButtonCount; +ulong THWMouseDOS::screenBase=0xB8000; +ushort THWMouseDOS::mouseChar; +int THWMouseDOS::lastX=0, + THWMouseDOS::lastY=0; +int THWMouseDOS::cols; +MouseEventType + THWMouseDOS::intEvent; +int THWMouseDOS::bufferSegment; +int THWMouseDOS::bufferSelector; +int THWMouseDOS::bufferSize; +int THWMouseDOS::bufferAllocated=0; +int THWMouseDOS::myBufferSegment; +int THWMouseDOS::myBufferSelector; +int THWMouseDOS::myBufferSize; +int THWMouseDOS::myBufferAllocated=0; + +// Information for the Real Mode CallBack (RMCB) +static _go32_dpmi_seginfo mouseIntInfo; +// x86 registers values stored by the RMCB +static _go32_dpmi_registers mouseIntRegs; + +/***************************************************************************** + Functions in this area are called asynchronically on interrupts using an + RMCB. For this reason they must be locked avoiding swap outs of their pages. + The functions are delimited by two empty functions that just mark the range. +*****************************************************************************/ + +static volatile +void StartOfLockedFunctions() +{ +} + +volatile +void THWMouseDOS::getMouseChar() +{ + mouseChar=_farpeekw(_dos_ds,screenBase+(lastY*cols+lastX)*2); +} + +volatile +void THWMouseDOS::setMouseChar() +{ + unsigned short c=mouseChar^0x7F00; + _farpokew(_dos_ds,screenBase+(lastY*cols+lastX)*2,c); +} + +volatile +void THWMouseDOS::resetMouseChar() +{ + _farpokew(_dos_ds,screenBase+(lastY*cols+lastX)*2,mouseChar); +} + +volatile +void THWMouseDOS::showMouseChar() +{ + if (!visible) return; + getMouseChar(); + setMouseChar(); +} + +int THWMouseDOS::DrawMouseEmulate(int x, int y) +{ + if (x!=lastX || y!=lastY) + { + if (visible) + { + drawCounter++; + resetMouseChar(); + } + lastX=x; + lastY=y; + showMouseChar(); + return 1; + } + return 0; +} + +int THWMouseDOS::getRMCB_InfoDraw(int &buttonPress) +{ + int x,y; + + intEvent.doubleClick=False; + intEvent.buttons =mouseIntRegs.h.bl; + x=intEvent.where.x =(mouseIntRegs.x.cx>>3) & 0xFF; + y=intEvent.where.y =(mouseIntRegs.x.dx>>3) & 0xFF; + buttonPress =mouseIntRegs.x.ax & 0x1e; + return drawMouse(x,y); +} + +static volatile +void EndOfLockedFunctions() +{ +} + +/***************************************************************************** + End of locked functions +*****************************************************************************/ + +int THWMouseDOS::DrawMouseDummy(int x, int y) +{ + if (x!=lastX || y!=lastY) + { + lastX=x; + lastY=y; + return 1; + } + return 0; +} + +void THWMouseDOS::setEmulation(int emulate) +{ + emulateMouse=emulate; + if (emulate) + { + THWMouse::Show=ShowEmulate; + THWMouse::Hide=HideEmulate; + THWMouse::drawMouse=DrawMouseEmulate; + } + else + { + THWMouse::Show=ShowDrv; + THWMouse::Hide=HideDrv; + THWMouse::drawMouse=DrawMouseDummy; + } +} + +#if 1 +// SET: I think we should really test it, Robert is using a call of the v3.0+ +// to set the mouse handler and one from v6.0+ to restore, why not using the +// same for both? My doubt is that the v6.0+ is for *alternate* handler and +// supports upto 3 different. +// Todo: it never checks the return value!!! +/*void THWMouseDOS::RegisterHandler(unsigned mask, void (*func)()) +{ + REGS r; + static int oldes=0; + static int olddx=0; + + if (func==NULL) + { // INT 33 - MS MOUSE v6.0+ - SET ALTERNATE MOUSE USER HANDLER + DX=olddx; + ES=oldes; + AX=SET_ALTERNATE_MOUSE_USER_HANDLER; + CX=mask; + INTR(0x33,r); + return; + } + else + { // INT 33 - MS MOUSE v3.0+ - EXCHANGE INTERRUPT SUBROUTINES + DX=mouseIntInfo.rm_offset; + ES=mouseIntInfo.rm_segment; + AX=EXCHANGE_INTERRUPT_SUBROUTINES; + CX=mask; + INTR(0x33,r); + oldes=ES; + olddx=DX; + } +}*/ +void THWMouseDOS::RegisterHandler(unsigned mask, void (*func)()) +{ + REGS r; + static int oldes=0; + static int olddx=0; + + if (func==NULL) + { // INT 33 - MS MOUSE v6.0+ - SET ALTERNATE MOUSE USER HANDLER + DX=olddx; ES=oldes; + AX=SET_ALTERNATE_MOUSE_USER_HANDLER; + CX=mask; + INTR(0x33,r); + return; + } + else + {// INT 33 - MS MOUSE v6.0+ - RETURN USER ALTERNATE INTERRUPT VECTOR + AX=RETURN_USER_ALTERNATE_INTERRUPT_VECTOR; + CX=mask; + INTR(0x33,r); + oldes=BX; + olddx=DX; + // INT 33 - MS MOUSE v6.0+ - SET ALTERNATE MOUSE USER HANDLER + DX=mouseIntInfo.rm_offset; + ES=mouseIntInfo.rm_segment; + AX=SET_ALTERNATE_MOUSE_USER_HANDLER; + CX=mask; + INTR(0x33,r); + } +} + +#else +// SET: I moved it here to keep the old routine and clean the currently used. +// I don't know why Robert dropped it. The main drawback is that you kill +// any old mouse handler. Looks like v1.0 didn't implement a way to get the +// current handler, not strange since that's a Microsoft spec. So it kills +// the mouse of the debuggy. I think it was the reason. +void THWMouseDOS::RegisterHandler( unsigned mask, void (*func)() ) +{ + REGS r; + if (func == NULL) + { // MS MOUSE v1.0+ - DEFINE INTERRUPT SUBROUTINE PARAMETERS + DX=ES=0; + AX=0x000C; + CX=mask; + INTR(0x33,r); + return; + } + else + { // MS MOUSE v1.0+ - DEFINE INTERRUPT SUBROUTINE PARAMETERS + DX=mouseIntInfo.rm_offset; + ES=mouseIntInfo.rm_segment; + AX=0x000C; + CX=mask; + INTR(0x33,r); + } +} +#endif + +void THWMouseDOS::biosRestoreState() +{ + REGS r; + if (bufferAllocated) + { + AX=RESTORE_DRIVER_STATE; + BX=bufferSize; + ES=bufferSegment; + DX=0; + INTR(0x33,r); + } +} + +int THWMouseDOS::biosRestoreMyState() +{ + REGS r; + if (myBufferAllocated) + { + AX=RESTORE_DRIVER_STATE; + BX=myBufferSize; + ES=myBufferSegment; + DX=0; + INTR(0x33,r); + return 1; + } + return 0; +} + +void THWMouseDOS::biosSaveState() +{ + REGS r; + if (!bufferAllocated) + { + AX=RETURN_DRIVER_STORAGE_REQUIREMENTS; + INTR(0x33,r); + bufferSize=BX; + bufferSegment=__dpmi_allocate_dos_memory((bufferSize+15)>>4, + &bufferSelector); + if (bufferSegment!=-1) + bufferAllocated = 1; + } + if (bufferAllocated) + { + AX=SAVE_DRIVER_STATE; + BX=bufferSize; + ES=bufferSegment; + DX=0; + INTR(0x33,r); + } +} + +void THWMouseDOS::biosSaveMyState() +{ + REGS r; + if (!myBufferAllocated) + { + AX=RETURN_DRIVER_STORAGE_REQUIREMENTS; + INTR(0x33,r); + myBufferSize=BX; + myBufferSegment=__dpmi_allocate_dos_memory((myBufferSize+15)>>4, + &myBufferSelector); + if (myBufferSegment!=-1) + myBufferAllocated = 1; + } + if (myBufferAllocated) + { + AX=SAVE_DRIVER_STATE; + BX=myBufferSize; + ES=myBufferSegment; + DX=0; + INTR(0x33,r); + } +} + +void THWMouseDOS::Resume() +{ + REGS r; + biosSaveState(); + buttonCount=myButtonCount; + if (!biosRestoreMyState()) + {// Default to x=y=0 + AX=POSITION_MOUSE_CURSOR; + CX=0; + DX=0; + INTR(0x33,r); + } +} + +void THWMouseDOS::Suspend() +{ + biosSaveMyState(); + biosRestoreState(); +} + +void THWMouseDOS::DeInit() +{ + if (handlerInstalled==True) + { + registerHandler(0xFFFF,0); + _go32_dpmi_free_real_mode_callback(&mouseIntInfo); + } +} + +THWMouseDOS::~THWMouseDOS() +{ +} + +void THWMouseDOS::ShowDrv() +{ + REGS r; + visible=1; + AX=SHOW_MOUSE_CURSOR; + INTR(0x33,r); +} + +void THWMouseDOS::HideDrv() +{ + REGS r; + visible=0; + AX=HIDE_MOUSE_CURSOR; + INTR(0x33,r); +} + +void THWMouseDOS::ShowEmulate() +{ + visible=1; + showMouseChar(); +} + +void THWMouseDOS::HideEmulate() +{ + visible=0; + resetMouseChar(); +} + +void THWMouseDOS::SetRange(ushort rx, ushort ry) +{ + REGS r; + // Used internally to draw the mouse + cols=(int)rx+1; + // Communicate it to the driver. Needed for video modes where the driver + // fails to know the screen size. + DX=rx<<3; + CX=0; + AX=DEFINE_HORIZONTAL_CURSOR_RANGE; + INTR(0x33,r); + DX=ry<<3; + CX=0; + AX=DEFINE_VERTICAL_CURSOR_RANGE; + INTR(0x33,r); +} + +void THWMouseDOS::GetEvent(MouseEventType &me) +{ + REGS r; + int x,y; + + AX=RETURN_POSITION_AND_BUTTON_STATUS; + INTR(0x33,r); + me.buttons=BX & 0x00ff; + x=me.where.x=(CX >> 3) & 0xFF; + y=me.where.y=(DX >> 3) & 0xFF; + me.doubleClick=False; + drawMouse(x,y); +} + +void THWMouseDOS::Init() +{ + char *OS=getenv("OS"); + // SET: NT reacts crashing when we use the mouse handler, don't know why + // and personally don't care, so just disable the handler. + if (OS && strcmp(OS,"Windows_NT")==0) + useMouseHandler=0; + + // Look in the user options + long pollMouse=1; + TScreen::optSearch("PollMouse",pollMouse); + if (pollMouse) + useMouseHandler=0; + + REGS r; + AX=RESET_DRIVER_AND_READ_STATUS; + INTR(0x33,r); + if (!AX) + return; + myButtonCount=buttonCount=BX & 0x00ff; + + // Ok mouse is present, set the driver functions + setEmulation(emulateMouse); + THWMouse::setRange=SetRange; + THWMouse::GetEvent=GetEvent; + THWMouse::registerHandler=RegisterHandler; + THWMouse::Suspend=Suspend; + THWMouse::Resume=Resume; + + screenBase=ScreenPrimary; + if (handlerInstalled==False && useMouseHandler) + {// Lock variables + LD(mouseIntRegs); + LD(intEvent); + LD(mouseChar); + LD(lastX); + LD(lastY); + LD(visible); + //LD(emulateMouse); + LD(drawCounter); + LD(cols); + LD(screenBase); + LD(TEventQueue::eventCount); + LD(TEventQueue::curMouse); + LD(TEventQueue::eventQueue); + LD(TEventQueue::mouseIntFlag); + LD(TEventQueue::eventQTail); + _go32_dpmi_lock_data(TEventQueue::eventQueue,eventQSize*sizeof(TEvent)); + // Lock functions + _go32_dpmi_lock_code((void*)StartOfLockedFunctions, + (int)EndOfLockedFunctions-(int)StartOfLockedFunctions); + _go32_dpmi_lock_code((void *)TEventQueue::mouseInt,1024); + _go32_dpmi_lock_code((void *)CLY_Ticks,1024); + // Setup the RMCB + mouseIntInfo.pm_offset=(int)TEventQueue::mouseInt; + _go32_dpmi_allocate_real_mode_callback_retf(&mouseIntInfo,&mouseIntRegs); + handlerInstalled=True; + } + if (handlerInstalled==True) + registerHandler(0xFFFF,TEventQueue::mouseInt); +} + +#else // DJGPP + +#include + +#endif // else DJGPP + diff --git a/tvision/classes/dos/dosscr.cc b/tvision/classes/dos/dosscr.cc new file mode 100644 index 0000000..f8e1f4e --- /dev/null +++ b/tvision/classes/dos/dosscr.cc @@ -0,0 +1,1004 @@ +/**[txh]******************************************************************** + + DOS Screen (TScreenDOS) functions. + + Copyright (c) 1998-2002 by Salvador E. Tropea (SET) + Contains code Copyright (c) 1996-1998 by Robert H”hne. + + Some code for handling 8x10 fonts is adapted from djgpp libc: + Copyright (C) 1995-1999 DJ Delorie + + Description: + This module implements the low level DOS screen access. + + Configuration variables: + ScreenWidth + ScreenHeight + ScreenPalette + AppCP + ScrCP + InpCP + LoadSecondaryFont + ExtProgVideoMode + VideoMode + VGABIOSState 0 use registers, 1 use BIOS (default) + SaveVGAState 0 don't try to save/restore VGA chip state, + 1 try to save it using the strategy indicated by + VGABIOSState (default) + +***************************************************************************/ + +#include + +#ifdef TVCompf_djgpp + #include +#endif + +#define Uses_string +#define Uses_unistd +#define Uses_TScreen +#define Uses_TEvent +#define Uses_TGKey +#define Uses_TVOSClipboard +#define Uses_TVCodePage +#include + +// I delay the check to generate as much dependencies as possible +#ifdef TVCompf_djgpp + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define TSCREEN_DEFINE_REGISTERS +#include +#include +#include + +#define GET_DOS_VERSION 0x3000 +#define GET_GLOBAL_CODE_PAGE_TABLE 0x6601 +#define CHARGEN_SET_BLOCK_SPECIFIER 0x1103 +#define CHARGEN_LOAD_USER_SPECIFIED_PATTERNS 0x1110 +#define GET_FONT_INFORMATION 0x1130 +// 0x11xx services (Sets the BIOS Rom) +#define FONT_8x8 0x12 +#define FONT_8x14 0x11 +#define FONT_8x16 0x14 +// GET_FONT_INFORMATION values +#define GET_FONT_8x8 0x03 +#define GET_FONT_8x14 0x02 +#define GET_FONT_8x16 0x06 + +int TScreenDOS::wasBlink=0; +int TScreenDOS::slowScreen=0; +uchar TScreenDOS::primaryFontSet=0, + TScreenDOS::secondaryFontSet=0, + TScreenDOS::fontsSuspended=0; +int TScreenDOS::origCPScr, + TScreenDOS::origCPApp, + TScreenDOS::origCPInp; +int TScreenDOS::fontSeg=-1; +TScreenFont256 TScreenDOS::appFonts[2]={{0,0,NULL},{0,0,NULL}}; + +const unsigned mdaBaseAddress=0xB0000; + +// Extern support functions +extern void SaveScreen(); +extern void SaveScreenReleaseMemory(); +extern void RestoreScreen(); +extern void ScreenUpdate(); +extern ushort user_mode; +extern char useBIOS_VGA_State; +extern char saveVGA_State; + +void setBlinkState(); +void setIntenseState(); +int getBlinkState(); + +TScreen *TV_DOSDriverCheck() +{ + TScreenDOS *drv=new TScreenDOS(); + if (!TScreen::initialized) + { + delete drv; + return 0; + } + return drv; +} + +TScreenDOS::TScreenDOS() +{ + // Currently initialization never fails + initialized=1; + if (dCB) dCB(); + + TDisplayDOS::Init(); + + TScreen::Resume=Resume; + TScreen::Suspend=Suspend; + TScreen::setCrtData=setCrtData; + TScreen::clearScreen=clearScreen; + TScreen::getCharacter=getCharacter; + TScreen::getCharacters=getCharacters; + TScreen::setCharacter=setCharacter; + TScreen::setCharacters=setCharacters; + TScreen::System_p=System; + TScreen::getFontGeometry=GetFontGeometry; + TScreen::setFont_p=SetFont; + TScreen::restoreFonts=RestoreFonts; + + TVDOSClipboard::Init(); + THWMouseDOS::Init(); + TGKeyDOS::Init(); + + long aux; + if (optSearch("VGABIOSState",aux)) + useBIOS_VGA_State=aux; + if (optSearch("SaveVGAState",aux)) + saveVGA_State=aux; + + // Set the code page + int dosCodePage=437; // United States code page, for all versions before 3.3 + // get DOS version number, in the form of a normal number + AX=GET_DOS_VERSION; + dosInt(); + unsigned ver=AH | ((AL & 0xff)<<8); + if (ver>=0x31E) + { + AX=GET_GLOBAL_CODE_PAGE_TABLE; + dosInt(); + dosCodePage=BX; + } + // Look for user settings + optSearch("AppCP",forcedAppCP); + optSearch("ScrCP",forcedScrCP); + optSearch("InpCP",forcedInpCP); + // User settings have more priority than detected settings + codePage=new TVCodePage(forcedAppCP!=-1 ? forcedAppCP : dosCodePage, + forcedScrCP!=-1 ? forcedScrCP : dosCodePage, + forcedInpCP!=-1 ? forcedInpCP : dosCodePage); + SetDefaultCodePages(dosCodePage,dosCodePage,dosCodePage); + + flags0=CodePageVar | CanSetPalette | CanReadPalette | CursorShapes | UseScreenSaver | + CanSetBFont | CanSetSBFont | CanSetVideoSize; + user_mode=startupMode=getCrtMode(); + SaveScreen(); + unsigned startScreenWidth=GetCols(), startScreenHeight=GetRows(); + + unsigned maxX=startScreenWidth, maxY=startScreenHeight; + if (optSearch("ScreenWidth",aux)) + maxX=aux; + if (optSearch("ScreenHeight",aux)) + maxY=aux; + if (frCB) + {// Give a chance to the call back. + primaryFontSet=1; + appFonts[0].h=0; + long aux=0; + if (optSearch("LoadSecondaryFont",aux) && aux) + { + secondaryFontSet=1; + appFonts[1].h=0; + } + } + char *ext=optSearch("ExtProgVideoMode"); + if (optSearch("VideoMode",aux)) + {// if frCB installed it will use the application font + setCrtMode((ushort)aux); + } + else if (ext) + { + setCrtModeExt(ext); + if (frCB) + SelectFont(charLines,False); // Try loading the application font + } + else if (maxX!=startScreenWidth || maxY!=startScreenHeight) + {// if frCB installed it will use the application font + setCrtModeRes(maxX,maxY); + } + else + { + if (frCB) + SelectFont(charLines,False); // Try loading the application font + } + // User requested palette + if (parseUserPalette()) + setPaletteColors(0,16,UserStartPalette); + + screenMode=getCrtMode(); + setCrtData(); + // We use the video memory as buffer, not a malloced buffer + screenBuffer=(uint16 *)-1; + suspended=0; +} + +void TScreenDOS::Resume() +{ + if (!dual_display) + { + GetDisPaletteColors(0,16,OriginalPalette); + SaveScreen(); + //if (screenMode == 0xffff) + // screenMode = getCrtMode(); + if (screenMode!=user_mode) + setCrtMode(screenMode); + if (wasBlink) + setBlinkState(); + else + setIntenseState(); + ResumeFonts(); + SetDisPaletteColors(0,16,ActualPalette); + } + else + { + THWMouseDOS::setEmulation(1); + } + setCrtData(); +} + +TScreenDOS::~TScreenDOS() +{ + suspend(); // First suspend + SaveScreenReleaseMemory(); // Now we can release the memory + ReleaseMemFonts(); + THWMouseDOS::DeInit(); +} + +void TScreenDOS::Suspend() +{ + if (!dual_display) + { + wasBlink=getBlinkState(); + SuspendFonts(); + RestoreScreen(); + SetDisPaletteColors(0,16,OriginalPalette); + } +} + +void TScreenDOS::setCrtData() +{ + if (dual_display) + { + screenMode =7; + screenWidth =80; + screenHeight=25; + cursorLines =0x0b0c; + } + else + { + screenMode =getCrtMode(); + screenWidth =getCols(); + screenHeight=getRows(); + hiResScreen =Boolean(screenHeight>25); + if (screenMode==7) + cursorLines=0x0b0c; // ? + else + cursorLines=getCursorType(); + setCursorType(0); + } +} + +void TScreenDOS::clearScreen() +{ + if (dual_display) + _mono_clear(); // djgpp's libc + else + TDisplay::clearScreen(screenWidth,screenHeight); +} + +ushort TScreenDOS::getCharacter(unsigned offset) +{ + return _farpeekw(_dos_ds,(dual_display ? mdaBaseAddress : ScreenPrimary)+offset*2); +} + +void TScreenDOS::getCharacters(unsigned offset,ushort *buf,unsigned count) +{ + if (slowScreen) + { + _farsetsel(_dos_ds); + int ofs=(dual_display ? mdaBaseAddress : ScreenPrimary)+offset*2; + while (count--) + { + *buf++=_farnspeekw(ofs); + ofs+=2; + } + } + else + { + movedata(_dos_ds,(dual_display ? mdaBaseAddress : ScreenPrimary)+offset*2, + _my_ds(),(int)buf,count*2); + } +} + +void TScreenDOS::setCharacter(unsigned offset,ushort value) +{ + _farpokew(_dos_ds,(dual_display ? mdaBaseAddress : ScreenPrimary)+offset*2,value); +} + +void TScreenDOS::setCharacters(unsigned offset,ushort *values,unsigned count) +{ + if (slowScreen) + { + _farsetsel(_dos_ds); + int ofs = dual_display ? mdaBaseAddress : ScreenPrimary+offset*2; + while (count--) + { + _farnspokew(ofs,*values++); + ofs += 2; + } + } + else + { + movedata(_my_ds(),(int)values,_dos_ds, + (dual_display ? mdaBaseAddress : ScreenPrimary)+offset*2,count*2); + } +} + +int TScreenDOS::System(const char *command, pid_t *pidChild, int in, + int out, int err) +{ + // fork mechanism not available + if (pidChild) + *pidChild=0; + // If the caller asks for redirection replace the requested handles + if (in!=-1) + dup2(in,STDIN_FILENO); + if (out!=-1) + dup2(out,STDOUT_FILENO); + if (err!=-1) + dup2(err,STDERR_FILENO); + return system(command); +} + +/***************************************************************************** + Windows clipboard implementation using WinOldAp API. +*****************************************************************************/ + +#define USE_TB + +// Numbers for the errors +#define WINOLDAP_NoPresent 1 +#define WINOLDAP_ClpInUse 2 +#define WINOLDAP_TooBig 3 +#define WINOLDAP_Memory 4 +#define WINOLDAP_WinErr 5 + +#define WINOLDAP_Errors 5 + +#define IDENTIFY_WinOldAp_VERSION 0x1700 +#define OPEN_CLIPBOARD 0x1701 +#define EMPTY_CLIPBOARD 0x1702 +#define SET_CLIPBOARD_DATA 0x1703 +#define GET_CLIPBOARD_DATA_SIZE 0x1704 +#define GET_CLIPBOARD_DATA 0x1705 +#define CLOSE_CLIPBOARD 0x1708 + +// Strings for the errors +const char *TVDOSClipboard::dosNameError[]= +{ + NULL, + __("Windows not present"), + __("Clipboard in use by other application"), + __("Clipboard too big for the transfer buffer"), + __("Not enough memory"), + __("Windows reports error") +}; + +int TVDOSClipboard::isValid=0; +int TVDOSClipboard::Version; + +int TVDOSClipboard::Init(void) +{ + AX=IDENTIFY_WinOldAp_VERSION; + MultiplexInt(); + Version=AX; + isValid=AX!=IDENTIFY_WinOldAp_VERSION; + if (!isValid) + TVOSClipboard::error=WINOLDAP_NoPresent; + else + { + TVOSClipboard::copy=copy; + TVOSClipboard::paste=paste; + TVOSClipboard::available=1; // We have 1 clipboard + TVOSClipboard::name="Windows"; + TVOSClipboard::errors=WINOLDAP_Errors; + TVOSClipboard::nameErrors=dosNameError; + } + return isValid; +} + +int TVDOSClipboard::AllocateDOSMem(unsigned long size,unsigned long *BaseAddress) +{ + #ifdef USE_TB + unsigned long tbsize=_go32_info_block.size_of_transfer_buffer; + + if (size<=tbsize) + { + *BaseAddress=__tb; + return 1; + } + #endif + if (size>0x100000) + { + TVOSClipboard::error=WINOLDAP_TooBig; + return 0; + } + AH=0x48; + BX=(size>>4)+(size & 0xF ? 1 : 0); + MultiplexInt(); + if (r.x.flags & 1) + { + TVOSClipboard::error=WINOLDAP_TooBig; + return 0; + } + *BaseAddress=AX<<4; + return 1; +} + +void TVDOSClipboard::FreeDOSMem(unsigned long Address) +{ + #ifdef USE_TB + if (Address==__tb) + return; + #endif + AH=0x49; + ES=Address>>4; + TDisplayDOS::dosInt(); +} + +//#define DEBUG_CLIPBOARD +#ifdef DEBUG_CLIPBOARD + ushort messageBox( const char *msg, ushort aOptions ); + ushort messageBox( ushort aOptions, const char *fmt, ... ); + #define DBGMessage(a) messageBox(a,0x402) + #define DBGMessage2(a,b) messageBox(0x402,a,b) +#else + #define DBGMessage(a) + #define DBGMessage2(a,b) +#endif + +int TVDOSClipboard::copy(int id, const char *buffer, unsigned len) +{ + if (!isValid || id!=0) return 0; + + unsigned long dataoff; + char cleaner[32]; + int winLen; + int ret=1; + + AX=OPEN_CLIPBOARD; + MultiplexInt(); + if (AX==0) + { + DBGMessage("Error opening the clipboard"); + TVOSClipboard::error=WINOLDAP_ClpInUse; + return 0; + } + // Erase the current contents of the clipboard + AX=EMPTY_CLIPBOARD; + MultiplexInt(); + winLen=((len+1)+0x1F) & ~0x1F; + memset(cleaner,0,32); + if (AllocateDOSMem(winLen,&dataoff)) + { + dosmemput(buffer,len,dataoff); + dosmemput(cleaner,winLen-len,dataoff+len); + AX=SET_CLIPBOARD_DATA; + DX=7; // OEM text + BX=dataoff & 0x0f; + ES=(dataoff>>4) & 0xffff; + SI=winLen>>16; + CX=winLen & 0xffff; + MultiplexInt(); + FreeDOSMem(dataoff); + if (AX==0) + { + DBGMessage("Error copying to clipboard"); + TVOSClipboard::error=WINOLDAP_WinErr; + ret=0; + } + } + else + { + TVOSClipboard::error=WINOLDAP_Memory; + DBGMessage("Error allocating DOS memory"); + ret=0; + } + AX=CLOSE_CLIPBOARD; + MultiplexInt(); + return ret; +} + +char *TVDOSClipboard::paste(int id, unsigned &len) +{ + if (!isValid || id!=0) return NULL; + + char *p=NULL; + unsigned long BaseAddress; + unsigned long size; + + AX=OPEN_CLIPBOARD; + MultiplexInt(); + if (AX==0) + { + DBGMessage("Error at open clipboard"); + TVOSClipboard::error=WINOLDAP_ClpInUse; + return NULL; + } + AX=GET_CLIPBOARD_DATA_SIZE; + DX=1; + MultiplexInt(); + size=AX+(DX<<16); + DBGMessage2("Size of clipboard %d",size); + if (size) + { + if (AllocateDOSMem(size,&BaseAddress)) + { + p=new char[size]; + if (p) + { + DX=7; + BX=BaseAddress & 0x0f; + ES=(BaseAddress>>4) & 0xffff; + AX=GET_CLIPBOARD_DATA; + MultiplexInt(); + dosmemget(BaseAddress,size,p); + len=strlen(p); + DBGMessage2("Got %d bytes in string",len); + } + else + TVOSClipboard::error=WINOLDAP_Memory; + FreeDOSMem(BaseAddress); + } + else + { + TVOSClipboard::error=WINOLDAP_Memory; + DBGMessage("Error allocating DOS memory"); + } + } + else + { + p=new char[1]; + *p=0; + len=0; + } + AX=CLOSE_CLIPBOARD; + MultiplexInt(); + return p; +} + +/***************************************************************************** + Fonts routines +*****************************************************************************/ + +int TScreenDOS::GetFontGeometry(unsigned &w, unsigned &h) +{ + w=8; + h=charLines; + return 1; +} + +/**[txh]******************************************************************** + + Description: + That selects what fonts are used for no/intense foreground colors.@p + The bits of the call are a little tweaked because it's EGA compatible:@* +---VGA---@* + 0,1,4 block selected by characters with attribute bit 3 clear@* + 2,3,5 block selected by characters with attribute bit 3 set@* + +***************************************************************************/ + +void TScreenDOS::SetDualCharacter(int b1, int b2) +{ + int value; + // No intense foreground font + value=b1 & 0x3; + if (b1 & 0x4) + value|=0x10; + // intense foreground font + value|=(b2 & 0x3)<<2; + if (b2 & 0x4) + value|=0x20; + + AX=CHARGEN_SET_BLOCK_SPECIFIER; + BL=value; + videoInt(); +} + +void TScreenDOS::SetFontBIOS(int which, unsigned height, uchar *data, + int modeRecalculate) +{ + dosmemput(data,256*height,__tb); + ES=__tb>>4; /* pass pointer to our font in ES:BP */ + BP=__tb & 0xF; + DX=0; /* 1st char: ASCII 0 */ + CX=256; /* 256 chars */ + BH=height; /* points per char */ + BL=which; /* block */ + AX=CHARGEN_LOAD_USER_SPECIFIED_PATTERNS; + if (!modeRecalculate) + AL&=0xF; /* force full mode recalculate, service 0x1100 */ + videoInt(); +} + +void TScreenDOS::ReleaseMemFonts() +{ + if (appFonts[0].data) + { + free(appFonts[0].data); + appFonts[0].data=NULL; + } + if (appFonts[1].data) + { + free(appFonts[1].data); + appFonts[1].data=NULL; + } +} + +int TScreenDOS::MemorizeFont(int which, TScreenFont256 *font) +{ + // Keep a copy of the user font + appFonts[which].w=font->w; + appFonts[which].h=font->h; + if (appFonts[which].data) + free(appFonts[which].data); + unsigned size=font->h*256; + appFonts[which].data=(uchar *)malloc(size); + if (!appFonts[which].data) + return 0; + memcpy(appFonts[which].data,font->data,size); + return 1; +} + +void TScreenDOS::SuspendFonts() +{ + if (fontsSuspended) + return; + fontsSuspended=1; + if (!primaryFontSet && !secondaryFontSet) + return; // Nothing to do + DisableDualFont(); + SelectRomFont(charLines,0,0); +} + +void TScreenDOS::ResumeFonts() +{ + if (!fontsSuspended) + return; + fontsSuspended=0; + if (!primaryFontSet && !secondaryFontSet) + return; // Nothing to do + if (primaryFontSet) + SetFontBIOS(0,charLines,appFonts[0].data,0); + if (secondaryFontSet) + { + SetFontBIOS(1,charLines,appFonts[1].data,0); + EnableDualFont(); + } +} + +int TScreenDOS::SetFont(int changeP, TScreenFont256 *fontP, + int changeS, TScreenFont256 *fontS, + int fontCP, int appCP) +{ + if (!changeP && !changeS) return 1; + // Check for restore fonts + if (changeP && !fontP && ((!changeS && !secondaryFontSet) || (changeS && !fontS))) + { + DisableDualFont(); + SelectRomFont(charLines,0,0); + ReleaseMemFonts(); + secondaryFontSet=primaryFontSet=0; + if (fontCP!=-1) + { + if (appCP==-1) + TVCodePage::SetScreenCodePage(fontCP); + else + TVCodePage::SetCodePage(appCP,fontCP,-1); + } + return 1; + } + // Solve the sizes + unsigned wP=8,hP=charLines, + wS=8,hS=charLines; + int newP=changeP && fontP; + if (newP) + { + wP=fontP->w; + hP=fontP->h; + } + int newS=changeS && fontS; + if (newS) + { + wS=fontS->w; + hS=fontS->h; + } + if (wP!=wS || hP!=hS) return 0; + // Check if the size is in the range + if (wP!=8 || hP!=charLines) + return 0; + // Memorize the new fonts + if (newP && !MemorizeFont(0,fontP)) return 0; + if (newS && !MemorizeFont(1,fontS)) return 0; + + // Change the requested fonts + if (changeP) + { + if (!primaryFontSet) + TVCodePage::GetCodePages(origCPApp,origCPScr,origCPInp); + if (fontP) + { + SetFontBIOS(0,charLines,fontP->data,0); + primaryFontSet=1; + } + else + { + SelectRomFont(charLines,0,0); + primaryFontSet=0; + } + } + if (changeS) + { + if (fontS) + { + SetFontBIOS(1,charLines,fontS->data,0); + EnableDualFont(); + secondaryFontSet=1; + } + else + { + DisableDualFont(); + secondaryFontSet=0; + } + } + if (changeP && fontCP!=-1) + { + if (appCP==-1) + TVCodePage::SetScreenCodePage(fontCP); + else + TVCodePage::SetCodePage(appCP,fontCP,-1); + } + return 1; +} + +void TScreenDOS::RestoreFonts() +{ + if (!primaryFontSet && !secondaryFontSet) + return; // Protection + SetFont(1,NULL,1,NULL,origCPScr,origCPApp); +} + +/**[txh]******************************************************************** + + Description: + Selects a font of the desired size. Currently only 8x8, 8x10, 8x14 and +8x16 are supported but I did it in this way because nobody knows about the +future.@p + If noForce is != 0 then the routine doesn't set the fonts. This option +must be used when you know that BIOS already loaded the fonts. Using it +avoids an extra load. The derived classes takes the desition according to +the selected font, so if the user selected a font the load is forced.@p + If modeRecalculate is 1 the call to set the BIOS font is made using the +bit 4 on, that means the BIOS will recalculate some things like the number +of rows and cols in the screen. That's avoided when an external program +sets the mode because a recalculation can fail.@p + + Return: + non-zero if fails, zero if all ok. + +***************************************************************************/ + +int TScreenDOS::SelectRomFont(int height, int which, int modeRecalculate) +{ + //UseDefaultFontsNextTime=0; + switch (height) + { + case 8: + SetRomFonts(FONT_8x8,which,modeRecalculate); + break; + case 10: + if (Load8x10Font(which,modeRecalculate)) + return 1; + break; + case 14: + SetRomFonts(FONT_8x14,which,modeRecalculate); + break; + case 16: + SetRomFonts(FONT_8x16,which,modeRecalculate); + break; + default: + return 1; + } + return 0; +} + +void TScreenDOS::SetRomFonts(int sizeFont, int which, int modeRecalculate) +{ + if (!modeRecalculate) + sizeFont&=0xF; + BL=which; + AH=0x11; + AL=sizeFont; + videoInt(); +} + + +/**[txh]******************************************************************** + + Description: + Stretch a 8x8 font to the 8x10 character box. This is required to +use 80x40 mode on a VGA or 80x35 mode on an EGA, because the character +box is 10 lines high, and the ROM BIOS doesn't have an appropriate font. +So we create one from the 8x8 font by adding an extra blank line +from each side. + +***************************************************************************/ + +void TScreenDOS::MaybeCreate8x10Font(void) +{ + unsigned char *p; + unsigned long src, dest, i, j; + + if (fontSeg!=-1) + return; + int buf_pm_sel; + + /* Allocate buffer in conventional memory. */ + fontSeg=__dpmi_allocate_dos_memory(160,&buf_pm_sel); + + if (fontSeg==-1) + return; + + /* Get the pointer to the 8x8 font table. */ + p=(uchar *)malloc(2560); /* 256 chars X 8x10 pixels */ + if (p==(uchar *)0) + { + //errno=ENOMEM; + __dpmi_free_dos_memory(buf_pm_sel); + fontSeg=-1; + return; + } + BH=GET_FONT_8x8; + AX=GET_FONT_INFORMATION; + videoInt(); + src=(((unsigned)ES)<<4)+BP; + dest=((unsigned)fontSeg)<<4; + + /* Now copy the font to our table, stretching it to 8x10. */ + _farsetsel(_dos_ds); + for (i=0; i<256; i++) + { + /* Fill first extra scan line with zeroes. */ + _farnspokeb(dest++, 0); + + for (j=0; j<8; j++) + { + uchar val=_farnspeekb(src++); + _farnspokeb(dest++,val); + } + + /* Fill last extra scan line with zeroes. */ + _farnspokeb(dest++,0); + } +} + +/* Load the 8x10 font we created into character generator RAM. */ +int TScreenDOS::Load8x10Font(int which, int modeRecalculate) +{ + MaybeCreate8x10Font(); /* create if needed */ + if (fontSeg==-1) + return 1; + ES=fontSeg; /* pass pointer to our font in ES:BP */ + BP=0; + DX=0; /* 1st char: ASCII 0 */ + CX=256; /* 256 chars */ + BH=10; /* 10 points per char */ + BL=which; /* block */ + AX=CHARGEN_LOAD_USER_SPECIFIED_PATTERNS; + if (!modeRecalculate) + AL&=0xF; + videoInt(); + return 0; +} + +/**[txh]******************************************************************** + + Description: + Used after setting a video mode to load the user font or the BIOS font. +The force parameter indicates if we must load the BIOS font or if the font +was already loaded.@p + If a font was set the application this function tries to reuse it. If the +font doesn't match the size used by the video mode calls a call back +requesting a new font. If the routine fails to get a propper font the BIOS +font is restored. + +***************************************************************************/ + +void TScreenDOS::SelectFont(unsigned height, Boolean Force) +{ + int fontWasLoaded=primaryFontSet || secondaryFontSet; + + if (primaryFontSet && !fontsSuspended) + { + if (height==appFonts[0].h) + SetFontBIOS(0,height,appFonts[0].data,0); + else + { + int fontOk=0; + // The one provided by the application isn't suitable + if (frCB) + {// Try asking the application to provide a new one + TScreenFont256 *font=frCB(0,8,height); + if (font) + { + SetFontBIOS(0,height,font->data,0); + MemorizeFont(0,font); + fontOk=1; + DeleteArray(font->data); + delete font; + } + } + if (!fontOk) + { + if (Force) + SelectRomFont(height,0,1); + primaryFontSet=0; + } + } + } + else + { + if (Force) + SelectRomFont(height,0,1); + } + + if (!fontsSuspended && secondaryFontSet) + { + if (height==appFonts[1].h) + SetFontBIOS(1,height,appFonts[1].data,0); + else + { + int fontOk=0; + // The one provided by the application isn't suitable + if (frCB) + {// Try asking the application to provide a new one + TScreenFont256 *font=frCB(1,8,height); + if (font) + { + SetFontBIOS(1,height,font->data,0); + MemorizeFont(1,font); + fontOk=1; + DeleteArray(font->data); + delete font; + } + } + if (!fontOk) + { + DisableDualFont(); + secondaryFontSet=0; + } + } + } + + if (fontWasLoaded && !(primaryFontSet || secondaryFontSet)) + // Restore the original encoding if we forced ROM fonts + TVCodePage::SetCodePage(origCPApp,origCPScr,origCPInp); +} + + +#else // DJGPP + +#include +#include +#include + +#endif // else DJGPP + diff --git a/tvision/classes/dos/rhscreen.cc b/tvision/classes/dos/rhscreen.cc new file mode 100644 index 0000000..28159a9 --- /dev/null +++ b/tvision/classes/dos/rhscreen.cc @@ -0,0 +1,253 @@ +/* Copyright (C) 1996-1998 Robert H”hne, see COPYING.RH for details */ +/* This file is part of RHIDE. */ +/* Copyright 1998-2002 Salvador E. Tropea */ +#include + +#define Uses_TScreen +#include + +// I delay the check to generate as much dependencies as possible +#ifdef TVCompf_djgpp +#include +#include +#include +#include +#include +//#include +extern "C" void intensevideo(void); +extern "C" void blinkvideo(void); +#include +#include +#include +#include + +//#define DEBUG +#define TOSTDERR +#ifndef DEBUG +#define dbprintf(a...) +#else +# ifdef TOSTDERR +# define dbprintf(a...) fprintf(stderr,a) +# else +# define dbprintf(a...) printf(a) +# endif +#endif + +extern ushort user_mode; +int blink_use_bios = 0; + +static unsigned int user_cursor_x; +static unsigned int user_cursor_y; +static void *user_screen = NULL; +static int user_screen_size = 0; +static int user_screen_len; +static ushort user_cursor; +static int user_blink = 1; +void rh_save_vga_state(); +void rh_restore_vga_state(); + +int getBlinkState(void) +{ + int retval; + if (TScreen::screenMode == 7) return 1; + if (blink_use_bios) + { + retval = _farpeekb(_dos_ds,0x465) & 0x20; + } + else + { + inportb(0x3DA); + outportb(0x3C0,0x30); + retval = inportb(0x3C1) & 0x8; + } + return retval; +} + +void setBlinkState(void) +{ + if (TScreen::screenMode == 7) return; + if (getBlinkState()) return; + if (blink_use_bios) + { + blinkvideo(); + } + else + { + char val; + inportb(0x3DA); + outportb(0x3C0,0x30); + val=inportb(0x3C1); + outportb(0x3C0,val | 0x8); + } +} + +void setIntenseState(void) +{ + if (TScreen::screenMode == 7) return; + if (!getBlinkState()) return; + if (blink_use_bios) + { + intensevideo(); + } + else + { + char val; + inportb(0x3DA); + outportb(0x3C0,0x30); + val=inportb(0x3C1); + outportb(0x3C0,val & 0xF7); + } +} + +#define SCREEN_BASE (_farpeekb(_dos_ds, 0x449) == 7 ? 0xB0000 : 0xB8000) + +static +void ScreenUpdate() +{ + movedata(_my_ds(),(int)user_screen,_dos_ds,SCREEN_BASE,user_screen_len); +} + + +static +void ScreenRetrieve() +{ + movedata(_dos_ds,SCREEN_BASE,_my_ds(),(int)user_screen,user_screen_len); +} + +void rh_save_vesa(); +void rh_restore_vesa(); +int rh_is_vesa_mode(); +void rh_check_for_vesa(); +void rh_save_vga(); +void rh_restore_vga(); +int rh_is_vga_mode(); + +extern int rh_vesa_supported; +static int vesa_checked = 0; + +static int vesa_mode; +static int vga_mode; + +static unsigned char palette[3*256]; +int save_text_palette = 0; + +static +void save_palette() +{ + int i; + outportb(0x3c7,0); + for (i=0;i<256;i++) + { + palette[i*3+0] = inportb(0x3c9); + palette[i*3+1] = inportb(0x3c9); + palette[i*3+2] = inportb(0x3c9); + } +} + +static +void restore_palette() +{ + int i; + outportb(0x3c8,0); + for (i=0;i<256;i++) + { + outportb(0x3c9,palette[i*3+0]); + outportb(0x3c9,palette[i*3+1]); + outportb(0x3c9,palette[i*3+2]); + } +} + +void rh_SaveVideo(int cols,int rows) +{ + int screensize; + user_mode = 0; + vesa_mode = 0; + if (!vesa_checked) + { + rh_check_for_vesa(); + vesa_checked = 1; + } + if (rh_vesa_supported && (vesa_mode = rh_is_vesa_mode())) + { + dbprintf("Saving VESA mode %d\n",vesa_mode); + rh_save_vesa(); + } + else + if ((vga_mode = rh_is_vga_mode())) + { + dbprintf("Saving VGA mode %d\n",vga_mode); + rh_save_vga(); + } + else + { + dbprintf("Saving text mode\n"); + screensize = cols*rows*2; + TDisplay::getCursorPos(user_cursor_x,user_cursor_y); + user_cursor = TScreen::getCursorType(); + user_mode = TScreen::getCrtMode(); + user_blink = getBlinkState(); + if (user_mode != 7) + { + rh_save_vga_state(); + if (save_text_palette) + save_palette(); + } + if (screensize > user_screen_size) + { + user_screen = realloc(user_screen,screensize); + user_screen_size = screensize; + } + user_screen_len = screensize; + ScreenRetrieve(); + } +} + +// SET: Added to release the memory of this module. +void rh_SaveVideoReleaseMemory(void) +{ + free(user_screen); +} + + +void rh_RestoreVideo() +{ + if (vesa_mode) + { + rh_restore_vesa(); + dbprintf("Restoring VESA mode\n"); + } + else + if (vga_mode) + { + rh_restore_vga(); + dbprintf("Restoring VGA mode\n"); + } + else + { + dbprintf("Restoring text mode\n"); + if (user_mode != 7) + rh_restore_vga_state(); + /*TFont::UseDefaultFontsNextTime=1;*/ + if (TScreen::screenMode != user_mode) + TDisplay::setCrtMode(user_mode); + /*else + TDisplay::RestoreDefaultFont();*/ + if (user_blink) + setBlinkState(); + else + setIntenseState(); + ScreenUpdate(); + TDisplay::setCursorType(user_cursor); + TDisplay::setCursorPos(user_cursor_x,user_cursor_y); + if (user_mode != 7 && save_text_palette) + restore_palette(); + if (user_mode != 7) + rh_restore_vga_state(); + } +} + +#else + +#include + +#endif diff --git a/tvision/classes/dos/screen.cc b/tvision/classes/dos/screen.cc new file mode 100644 index 0000000..2f92ae5 --- /dev/null +++ b/tvision/classes/dos/screen.cc @@ -0,0 +1,51 @@ +/* Copyright (C) 1996-1998 Robert H”hne, see COPYING.RH for details */ +/* This file is part of RHIDE. */ +/* Copyright 1998-2002 Salvador E. Tropea */ +#include + +#define Uses_stdlib +#define Uses_TScreen +#include + +// I delay the check to generate as much dependencies as possible +#ifdef TVCompf_djgpp +ushort user_mode; + +#define MODE_SET 1 // Use the routines from SET +#define MODE_RH 0 // Use the routines from RH + +int screen_saving = MODE_RH; + +void rh_SaveVideo(int,int); +void rh_SaveVideoReleaseMemory(void); +void rh_RestoreVideo(); +void set_SaveVideo(int,int); +void set_RestoreVideo(); + +void SaveScreen() +{ + if (screen_saving == MODE_SET) + set_SaveVideo(TDisplay::getCols(),TDisplay::getRows()); + else + if (screen_saving == MODE_RH) + rh_SaveVideo(TDisplay::getCols(),TDisplay::getRows()); +} + +// SET: Added to release the memory allocated here +void SaveScreenReleaseMemory(void) +{ + if (screen_saving == MODE_RH) + rh_SaveVideoReleaseMemory(); +} + +void RestoreScreen() +{ + if (screen_saving == MODE_SET) + set_RestoreVideo(); + else + if (screen_saving == MODE_RH) + rh_RestoreVideo(); +} +#endif + + diff --git a/tvision/classes/dos/sescreen.cc b/tvision/classes/dos/sescreen.cc new file mode 100644 index 0000000..4dd3195 --- /dev/null +++ b/tvision/classes/dos/sescreen.cc @@ -0,0 +1,1548 @@ +/* Copyright (C) 1996-1998 Robert H”hne, see COPYING.RH for details */ +/* This file is part of RHIDE. */ +/* Copyright 1999-2002 Salvador E. Tropea */ +#include + +/* This is needed, because get the correct textmode */ +#define Uses_TScreen +#include + +// I delay the check to generate as much dependencies as possible +#ifdef TVCompf_djgpp +/* This file is for saving/restoring the screen in graphics and/or + text modes. Many parts and most of the very good comments came + from SET. + + NOTE: by SET 1999-04: I think this code is broken and I check it latter + so I'm not fixing here the VESA stuff about using the __tb. +*/ +/* + Hi Robert: + +---------------------------------------------------------------------------- +Chapter 1) XMode v.s. Text modes: + + I'm sure that this weekend you arrive to the same conclution that me, or +may be not: + Your code works OK to restore Mode 3 -> X-Mode -> Mode 3 -> X-Mode, but +if I use a better text mode like 80x60 the code doesn't work, in fact works +only up to 80x50 or up to 132x25. + I'll try to explain you my conclutions: + + The VGA controler use a linear mode when is in text mode, in this linear +mode the first char in 0xB8000 is the first char in your memory (256Kb). + So if you set an 80x60 mode you'll use 80x60x2 bytes of the memory that's +9600 bytes and you are saving only 8192 bytes!!, so the result is that a part +of the screen isn't restored. + May be I wasn't clear when I said that you save 8192: In planar modes you +access to the position 0 in the video memory in plane 0 (or 1 depending on +if we start to number from 0 or 1), the position 0 in the plane 1 is the +position 65536 of the memory with respect to the linear mode, so saving +32Kb you save 0-8Kb 64Kb-72Kb 128Kb-136Kb and 192Kb-200Kb (ever taking the +linear as reference). + So in 132x60 (for example) you must save 0-15840 and you only save 0-8Kb. + I modified your code to make that, perhapes is better if you rewrite it from +the new knowledge. + Now, saving Cols*Rows*2 bytes of plane 0 (I called plane 1 in the code), +you'll save all but .... I saw that the plane 1 is wasted too!, so you must +save the same amount for plane 1. The plane 2 have the fonts, seems that +the BIOS uses half of the RAM (0-128Kb) for different text pages and the +rest for fonts, at least in my board the fonts are stored in plane 2, now +how much uses?, in my board there are fonts from 8x8 to 9x16, 9x16 means 32 +bytes per character so with 256 chars you'll use 8192. Finally plane 3 +remains untouched so we don't need to save it. + That's (80x25*2)*2+8192=16192 => ONLY 16Kb! (and not 64Kb = 32Kb+malloc +overhead like the previous version) and in the worst case 39872 and that's +just the same amount of memory wasted but saves the right thing. + Now the question is: Is that correct in other cards?. + + I don't know if you understood my code (the one that I sent you some weeks +ago), in my code I don't need to worry about if the mode is planar or linear, +I just setup a planar addressing mode, why you don't make that, is easier. If +you are worring about the flickering I can cure that. +----------------------------------------------------------------------------- +Chapter 2) 16 colors mode v.s. Text modes: + + Well that's almost the same as an X-mode but ... you are making some thing +very strange, I must admit that I tried for 4 hours until I get a working +routine but is the same as X-mode. + From what I can see you don't have any documentation about the VGA +registers, is that true?, I have a nice Norton Guide for it. + Anyways you are using the write mode 3, this mode is useful for tricks but +not for dumping memory, in mode 3 you need 2 operations by byte in memory, +you are making that with the ANDL, but if you use mode 0 you can do the same +just with a simple write, of course you must be sure that all the registers +involved will not mask your write. + In this file I'm using the same routine for: + + 320x200x16 + 640x200x16 + 640x350x16 + 640x480x16 + 320x240x256 + 320x400x256 + 360x480x256 + +----------------------------------------------------------------------------- +Chapter 3) Mode 0x13 v.s. Text modes: + + You think that this is the easier?, lamentably no. + This mode is not linear like text mode and is not planar as the 16 colors +modes and mode X, so what is?, the bits 0 and 1 of the address sets the plane +so two adjacent pixels addressed with 1 of difference are in different planes, +that's very good for programing, the mode is very easy to handle, but isn't +good for owr purposes. I don't have enough information but seems that the +constroler uses 1/4 of the pixels to show the screen, so if the user sets +the mode 0x13 and don't make any strange thing we only need to save: + + max(8192,Cols*Rows*2) + + 8192 is for the fonts, that's what the current program does, the problem is +that we are saving pixels that aren't needed and don't saving pixels that +we will touch. Until now I don't know how to address the missing pixels. + + Now pass to vga2.cc where I continue. + +*/ + +/* + Well that's the second part: + + As I can't address the right memory in the 0x13 mode I placed my old +methode again here, so now I save 16Kb for 80x25 and 39Kb (64Kb) for +132x60. + + Now I tested this file with: + +Card: Trident TGUI9440AGi +Text modes: +Mode Tx.Resol. Font Pixels +0x50 80x30 (8x16 640x480) +0x51 80x43 (8x11 640x473) +0x52 80x60 (8x8 640x480) +0x53 132x25 (8x14 1056x350) +0x54 132x30 (8x16 1056x480) +0x55 132x43 (8x11 1056x473) +0x56 132x60 (8x8 1056x480) +0x57 132x25 (9x14 1188x350) +0x58 132x30 (9x16 1188x480) +0x59 132x43 (9x11 1188x473) +0x5A 132x60 (9x8 1188x480) +0x108 80x60 (Vesa 1) +0x109 132x25 (Vesa 1) +0x10A 132x43 (Vesa 1) +0x10B 132x60 (Vesa 1) <--- Must be x50 but Trident ... +0x10C 132x60 (Vesa 1) + +To Graphic modes: + 320x200x16 (0x0D) + 640x200x16 (0x0E) + 640x350x16 (0x10) + 640x480x2 (0x11) Partially tested. + 640x480x16 (0x12) + 320x200x256 (0x13) + 320x240x256 X-Mode + 320x400x256 X-Mode + 360x480x256 X-Mode + +*/ + +/* + Well ... + +Chapter 4) VESA v.s. Text modes: + + Here I have some problems, the 16 color modes can be handled in the same +way, and as we never need to handle more that 132*60*2=15840 bytes per plane +we don't need any bank switch, so I used the same trick that in VGA to skip +a plane. May be is wrong assumption, but all the boards that I know have +32Kb, 64Kb and 128Kb windows. + The 256 color modes are harder, I can only guess here, in my board seems +to be like a mode 0x13 but ALL the pixels are visible (not 1/4), so saving +32Kb like you tried doesn't work for the 132*60 because this mode uses +15840 bytes in the first bank, so if you want to save the memory in a linear +way you must save 132*60*2*4=63360 and that can envolve a bank switch in some +cards, so I let your bank switch code, but for this case. + The routines seems to be OK for text modes, the vga.cc is not the best +for text modes so I guess that is OK to handle VESA text modes with this +routines and make a simple routine for non-VESA text modes (just the old +thing in TScreen). + Why you don't use packed structures?, that will never be taked out from +GCC and VESA is PC specific. + + I tried switching from 1024x768x256 and 1024x768x16 to 132x60 and works OK. + +*/ + +/* + + Here is a version with Allegro, works in my machine, I tested Vesa 1.x, +Vesa 2.0 banked, Vesa 2.0 linear and Trident and all seems to work OK. I] +guess because even in Vesa 2.0 linear the Vesa 1.x functions still +working. + +*/ + +/* + + That's the unified version, is supposed to work with all the modes ... ;-) + I joined the VGA routines, the VESA routines and routines to save the text +modes, as the BIOS don't have any routine to retrieve the fonts I'm not +restoring the original fonts but a fresh copy from the ROM. That can produce +problems in mode too much twisted where the fonts aren't 8x8, 8x14 or 8x16. + There are examples with Allegro, GRX20 and conio. + +I changed some things: + +1) In save_vesa(): + + if (WinBAttributes & 0x3) // exist and readable + { +>>>>>>>>> The condition is wrong you can get here if Win B exists and is +>>>>>>>>> write-only! + window_r = 1; + win_seg_r = WinBSegment; + // I assume here, that now winb is writable. Is that correct?? +>>>>>>>>> May be is correct but, why take the risk? + window_w = 0; + win_seg_w = WinASegment; + } + So I rewritted that. + +2) I don't like to use DOS memory but lamentably you'll include it in the +debugger so we can't use the transfer buffer :-(. + +3) In save_vesa(): + I added bank_increment (see in the function) because WinGranularity can +be different to WinSize. + +4) In restore_vesa(): + I putted out the call to service 2 (set mode) because restore_vesa_state +must be enough. + +5) The 16 colors VESA modes are using the same core routine that the VGA +modes now. + +*/ + +#include +#include +#include +#include +#include +#include + +#include +extern int user_mode; + +static void *buffer = NULL; +static int buffer_size = 0; +static int saved_size; +static int window_r; +static int window_w; +static int win_size; +static unsigned win_seg_r; +static unsigned win_seg_w; +static int bank_increment; +static int is_plane_mode = 0; +static int TextModeXres; +static int TextModeYres; + +/***************************************************************************** + +*************************** VESA BIOS ROUTINES ****************************** + +*****************************************************************************/ +/***************************************************************************** + + Function: int GetVesaModeInfo(int mode) + + Description: Gets the information of a VESA mode. + 0x4F01 service of VESA 1.x + + Parameters: + int mode: The mode to ask to BIOS. + + Return: + 0 fail. + 1 OK. + + Note: Uses 256 bytes of DOS memory. + +*****************************************************************************/ + +static int mode_info_segment = -1; +static int mode_info_selector; + +static int GetVesaModeInfo(int mode) +{ + __dpmi_regs r; + if (mode_info_segment == -1) + mode_info_segment = __dpmi_allocate_dos_memory(16,&mode_info_selector); + if (mode_info_segment == -1) + return 0; + r.x.ax = 0x4f01; + r.x.es = mode_info_segment; + r.x.di = 0; + r.x.cx = mode; + __dpmi_int(0x10,&r); + if (r.x.ax != 0x004f) + return 0; + return 1; +} + +/***************************************************************************** + + Function: void save_vesa_state() + + Description: Saves all the state of the VESA system to restore the mode + later. 0x4F04 Service. + + Note: Uses an unknown amount of DOS memory (2.5Kb aprox.) + +*****************************************************************************/ + +static int vesa_state_segment = -1; +static int vesa_state_selector; + +static void save_vesa_state() +{ + __dpmi_regs r; + if (vesa_state_segment == -1) + { + r.x.ax = 0x4f04; + r.h.dl = 0x00; + r.x.cx = 0x000f; + __dpmi_int(0x10,&r); + if (r.x.ax != 0x004f) return; + vesa_state_segment = + __dpmi_allocate_dos_memory(r.x.bx*4,&vesa_state_selector); + if (vesa_state_segment == -1) return; + } + r.x.ax = 0x4f04; + r.h.dl = 0x01; + r.x.es = vesa_state_segment; + r.x.bx = 0; + r.x.cx = 0x000f; + __dpmi_int(0x10,&r); +} + +/***************************************************************************** + + Function: void restore_vesa_state(int What) + + Description: Restores part or all of the saved information about the VESA + state. 0x4F04 Service. + + Parameters: + int What: What was saved, USE RESTORE_VESA_ALL EVER. + +*****************************************************************************/ + +static void restore_vesa_state(int What) +{ + __dpmi_regs r; + if (vesa_state_segment == -1) return; + r.x.ax = 0x4f04; + r.h.dl = 0x02; + r.x.es = vesa_state_segment; + r.x.bx = 0; + r.x.cx = What; + __dpmi_int(0x10,&r); +} + +/***************************************************************************** + + Function: void check_for_vesa() + + Description: Checks if VESA BIOS is present. + 0x4F00 Service. + + Notes: + 1) The result is stored in vesa_supported. + 2) Is called by the initialization routine. + 3) Uses 512 bytes of DOS memory, can be liberated. + +*****************************************************************************/ + +static int vesa_supported = 0; + +static void check_for_vesa() +{ + __dpmi_regs r; + + r.x.ax = 0x4f03; + __dpmi_int(0x10,&r); + + /* Not supported */ + if (r.h.al != 0x4f) return; + + vesa_supported = 1; +} + +/***************************************************************************** + + Function: int is_vesa_mode() + + Description: Checks if the current mode is VESA, if yes retrieves the + information about the mode. 0x4F03 Service. + Return: + 0 not, VESA or fail. + 1 VESA + +*****************************************************************************/ + +static int is_vesa_mode() +{ + __dpmi_regs r; + + r.x.ax = 0x4f03; + __dpmi_int(0x10,&r); + + /* Not supported or not successful */ + if (r.x.ax != 0x004f) return 0; + + /* Because GetVesaModeInfo forces a screen switch under W95, I check + the most common textmode here without calling that function */ + if (r.x.bx == 0x0003 || r.x.bx == 7) + return 0; + + if (!GetVesaModeInfo(r.x.bx)) + return 0; + + if (!(ModeAttributes & 1)) + // not supported + return 0; + + user_mode = r.x.bx; + + return 1; +} +/************************ END of VESA BIOS ROUTINES *************************/ + + + +/***************************************************************************** + +**************************** VGA BIOS ROUTINES ****************************** + +*****************************************************************************/ + +/***************************************************************************** + + Function: void save_vga_state() + + Description: Saves all the state of the VGA system to restore the mode + later. 0x1C01 Service. + + Note: Uses an unknown amount of DOS memory (2.5Kb aprox.) + +*****************************************************************************/ + +static int vga_state_segment = -1; +static int vga_state_selector; + +static +void save_vga_state() +{ + __dpmi_regs r; + if (vga_state_segment == -1) + { + r.x.ax = 0x1c00; + r.x.cx = 0x0007; + __dpmi_int(0x10,&r); + if (r.h.al != 0x1c) return; + vga_state_segment = + __dpmi_allocate_dos_memory(r.x.bx*4,&vga_state_selector); + if (vga_state_segment == -1) return; + } + r.x.ax = 0x1c01; + r.x.es = vga_state_segment; + r.x.bx = 0; + r.x.cx = 0x0007; + __dpmi_int(0x10,&r); +} + +/***************************************************************************** + + Function: void restore_vga_state(int What) + + Description: Restores part or all of the saved information about the VGA + state. 0x1C02 Service. + + Parameters: + int What: What was saved, USE RESTORE_VGA_ALL EVER. + +*****************************************************************************/ + +static void restore_vga_state(int What) +{ + __dpmi_regs r; + if (vga_state_segment == -1) return; + r.x.ax = 0x1c02; + r.x.es = vga_state_segment; + r.x.bx = 0; + r.x.cx = What; + __dpmi_int(0x10,&r); +} + +/***************************************************************************** + + Function: int is_vga_mode() + + Description: Check if the current mode is VGA and can be handled. + Return: + 0 fail + 1 OK + + Notes: + Define FULLBIOS to check directly trough BIOS instead of using the + BIOS Data Area (I guess is just the same). + + Supported modes: + + 320x200x16 (0x0D) + 640x200x16 (0x0E) + 640x350x16 (0x10) + 640x480x2 (0x11) Partially tested. + 640x480x16 (0x12) + 320x200x256 (0x13) + 320x240x256 X-Mode + 320x400x256 X-Mode + 360x480x256 X-Mode + Other X-Modes derivated from mode 0x13. + +*****************************************************************************/ + +static int is_vga_mode() +{ +#ifdef FULLBIOS + __dpmi_regs r; + + r.x.ax = 0x0f00; + __dpmi_int(0x10,&r); + + user_mode = r.h.al; +#else + user_mode = ScreenMode(); +#endif + + if (user_mode != 0x0d && + user_mode != 0x0e && + user_mode != 0x10 && + user_mode != 0x11 && + user_mode != 0x12 && + user_mode != 0x13 + ) return 0; + + if (user_mode == 0x12 || + user_mode == 0x0d || + user_mode == 0x0e || + user_mode == 0x10 + ) + { + is_plane_mode = 1; + } + else + { + unsigned char b; + outportb(VGA_SEQUENCER_PORT,VGA_MEMORY_MODE_REG); + b = inportb(VGA_SEQUENCER_DATA); + is_plane_mode = b & 0x08 ? 0 : 1; + } + + return 1; +} +/************************* END of VGA BIOS ROUTINES *************************/ + +/****************************** TXT BIOS ROUTINES ***************************/ + +/***************************************************************************** + + Function: int is_txt_mode() + + Description: Checks if the current mode is a text mode and can be handled. + Return: + 0 fail + 1 OK + + Notes: + Define FULLBIOS to check directly trough BIOS instead of using the + BIOS Data Area (I guess is just the same). + + Supported modes: + + 40x25 Color (0,1), Fonts 8x8, 8x14 and 8x16 + 80x25 Color (2,3), Fonts 8x8, 8x14 and 8x16 + 80x25 B&W (7) Hercules + 80x43 Color + 80x50 Color + Other modes derivated from mode 3 with fonts of 8, 14 and 16 scan lines. + +*****************************************************************************/ + +static int is_txt_mode() +{ +#ifdef FULLBIOS + __dpmi_regs r; + + r.x.ax = 0x0f00; + __dpmi_int(0x10,&r); + + user_mode = r.h.al; +#else + user_mode = TScreen::getCrtMode(); +#endif + + if ((user_mode & 0xff)<4 || user_mode==7) + { + if (user_mode==7) + win_seg_r=0xB0000; + else + win_seg_r=0xB8000; + } + else + return 0; + + return 1; +} +/*************************** End of TXT BIOS ROUTINES ***********************/ + +/***************************************************************************** + + Function: void SetAddressingMode() + + Description: Puts the VGA controler in Write Mode 0, Read Mode 0 and if + the mode isn't planar in planar mode. + + The 0 modes are the better to dump the video memory. + +*****************************************************************************/ + +static void SetAddressingMode() +{ + if (is_plane_mode) + { + outportb(VGA_GR_CTRL_PORT,VGA_MODE_REG); + /* set read mode 0 (and write mode 0) */ + outportb(VGA_GR_CTRL_DATA,inportb(VGA_GR_CTRL_DATA) & 0xF4); + } + else + { + // That's select write mode 0, read mode 0 and planar addressing + asm ("movw $0x604,%%ax \n\t" + "movw $0x3C4,%%dx \n\t" + "outw %%ax,%%dx \n\t" + "movb $0x40,%%ah \n\t" + "incb %%al \n\t" + "movw $0x3CE,%%dx \n\t" + "outw %%ax,%%dx \n\t" + "movb $5,%%ah \n\t" + "incb %%al \n\t" + "outw %%ax,%%dx" : : : "%edx", "%eax" ); + } +} + +/***************************************************************************** + + Function: int SavePlanar(int OffTarget) + + Description: Saves Cols*Rows*2 bytes of planes 0 and 1, and 8192 bytes + of the plane 3. + Parameters: + int OffTarget: Offset of the video window memory + Return: + The number of bytes used. + +*****************************************************************************/ + +static int SavePlanar(int OffTarget) +{ + int offset = 0; + int i,bs; + + // Ensure that the mode of addressing is OK + SetAddressingMode(); + + // Now save 3 planes, plane 4 is never touched by a normal text mode + for (i=0;i<3;i++) + { + /* read from plane 'i' */ + outportw(VGA_GR_CTRL_PORT,((i << 8) | VGA_RD_PLANE_SEL_REG)); + if (i==2) + bs=8192; + else + bs=TextModeXres*TextModeYres*2; + movedata(_dos_ds,OffTarget,_my_ds(),(int)buffer+offset,bs); + offset += bs; + } + + return offset; +} + +/***************************************************************************** + + Function: int RestorePlanar(int OffTarget) + + Description: Is the complementary to SavePlanar. + +*****************************************************************************/ + +static int RestorePlanar(int OffTarget) +{ + int offset = 0; + int i; + int bs; + + // Ensure that the mode of addressing is OK + SetAddressingMode(); + + // Let pass all bits + outportw(VGA_GR_CTRL_PORT,0xFF00 | VGA_BIT_MASK_REG); + // Just put the value, don't and,xor,etc. + outportw(VGA_GR_CTRL_PORT,VGA_ROT_FN_SEL_REG); + // Don't use reset masks + outportw(VGA_GR_CTRL_PORT,VGA_SET_RESET_ENB_REG); + outportw(VGA_GR_CTRL_PORT,VGA_SET_RESET_REG); + + unsigned long *_l = (unsigned long *)buffer; + for (i=0;i<3;i++) + { + /* enable plane 'i' for writing */ + outportw(VGA_SEQUENCER_PORT,(((1 << i) << 8) | VGA_WRT_PLANE_ENB_REG)); + + if (i==2) + bs=8192; + else + bs=TextModeXres*TextModeYres*2; + + movedata(_my_ds(),(int)_l,_dos_ds,OffTarget,bs); + _l += bs/4; + + offset+=bs; + } + + return offset; +} + +/***************************************************************************** + + Function: void save_vesa(void) + + Description: + Saves: + 1) The VESA registers. + 2) The BIOS data. + 3) The palette. + 4) Depending on the mode: + a) Text modes: (XRes*YRes*2) * 4. + b) 256 colors modes: XRes*YRes*2. + c) 16 colors modes: XRes*YRes*2 from planes 1 and 2 and 8192 from + plane 3. + where XRes and YRes are the resolution of the text mode. + +*****************************************************************************/ + +static void save_vesa() +{ + int offset = 0; + int bank = 0; + __dpmi_regs r; + save_vesa_state(); + + // Window selection and address +#if 0 + // About, that hmmmm... isn't a good idea + if (WinBAttributes & 0x3) /* exist and readable */ + { + window_r = 1; + win_seg_r = WinBSegment; + /* I assume here, that now winb is writable. Is that correct?? */ + window_w = 0; + win_seg_w = WinASegment; + } + else + { + window_w = window_r = 0; + win_seg_r = win_seg_w = WinASegment; + } +#else + // That's more reliable + if ((WinBAttributes & 0x3)==0x3) + { // If B exists and can be readed use B to read + window_r = 1; + win_seg_r = WinBSegment; + } + else + { // Else use A, one of the 2 must be readable + window_r = 0; + win_seg_r = WinASegment; + } + if ((WinAAttributes & 0x5)==0x5) + { // If A exists and can be writed use A to write + window_w = 0; + win_seg_w = WinASegment; + } + else + { // Else use B, one of the 2 must be writable + window_w = 0; + win_seg_w = WinBSegment; + } +#endif + win_seg_r <<= 4; + win_seg_w <<= 4; + + + // Window size + win_size = WinSize * 1024; + + // Normally granularity is == to win size but .... + // I assume that are multiples, for example, + // WinSize=128, WinGranularity=64 + bank_increment = win_size / (WinGranularity*1024); + + // Size to save, that's isn't a fixed value: + if ((ModeAttributes & 0x10) && (NumberOfPlanes > 1)) + { + saved_size = + (TextModeXres*TextModeYres*2) // The amount of memory destroyed in plane 1 + *2 // I don't know why but the same for plane 2 + +8192 // The fonts in plane 3, is that the worst case? + // there are 9x16 fonts, so I guess that's 32 bytes per + // character then 32*256=8192 + ; + } + else + { + if (ModeAttributes & 0x10) + saved_size = (TextModeXres*TextModeYres*2) * 4; + else + // Here I don't save the fonts used memory, what do you think? + saved_size = TextModeXres*TextModeYres*2; + } + + // Just an adjust for the methode used + if (saved_size < win_size) + win_size = saved_size; + + // Memory allocation + if (saved_size > buffer_size) + { + buffer = realloc(buffer,saved_size); + buffer_size = saved_size; + } + + // Loop switching bank until we get all the memory needed + while (offset < saved_size) + { + if (ModeAttributes & 0x10) // test for graphic mode + { // Here the assumptions are: + // 1) A text mode doesn't need a bank change. + // 2) A 16 colors mode can be restored from one bank. + + // Switch the right bank + r.x.ax = 0x4f05; + r.x.bx = window_r; + r.x.dx = bank; + __dpmi_int(0x10,&r); + + if (NumberOfPlanes > 1) + { // 16 colors modes, Here I asume that all is in 1 bank + is_plane_mode=1; + offset+=SavePlanar(win_seg_r); + } + } + // Here is for text and 256 colors modes: + if (NumberOfPlanes == 1) + { + movedata(_dos_ds,win_seg_r,_my_ds(),(int)buffer+offset,win_size); + offset += win_size; + } + // next bank if needed ... I don't think that this will happend + bank+=bank_increment; + } +} + +/***************************************************************************** + + Function: restore_vesa() + + Description: Is the reverse of save_vesa(). + +*****************************************************************************/ + +static void restore_vesa() +{ + int offset = 0; + int bank = 0; + __dpmi_regs r; + +#ifdef FORCE_SET_VIDEO_MODE + // Restore the mode?, why?, In my card the restore_vesa_state is enough + r.x.ax = 0x4f02; + r.x.bx = user_mode | 0x8000; + __dpmi_int(0x10,&r); +#endif + + restore_vesa_state(RESTORE_VESA_ALL); + + while (offset < saved_size) + { + if (ModeAttributes & 0x10) // test for graphic mode + { + r.x.ax = 0x4f05; + r.x.bx = window_w; + r.x.dx = bank; + __dpmi_int(0x10,&r); + + if (NumberOfPlanes > 1) + { // Here I asume that all is in 1 bank + is_plane_mode=1; + offset+=RestorePlanar(win_seg_w); + } + } + if (NumberOfPlanes == 1) + { + movedata(_my_ds(),(int)buffer+offset,_dos_ds,win_seg_w,win_size); + offset += win_size; + } + bank+=bank_increment; + } + + /* restore again, because of the change of the registers and the bank */ + restore_vesa_state(RESTORE_VESA_ALL); +} + +static void save_vga() +{ + save_vga_state(); + // Fixed for VGA graphic modes, there are a methode to know the true but ... + win_seg_r = 0xa0000; + + // Amount to save, that's isn't a fixed value: + saved_size = + (TextModeXres*TextModeYres*2) // The amount of memory destroyed in plane 1 + *2 // I don't know why but the same for plane 2 + +8192 // The fonts in plane 3, is that the worst case? + // there are 9x16 fonts, so I guess that's 32 bytes per + // character then 32*256=8192 + ; + + // Allocate memory + if (saved_size > buffer_size) + { + buffer = realloc(buffer,saved_size); + buffer_size = saved_size; + } + + // Save the planes + SavePlanar(win_seg_r); + +#if 0 + // Don't needed if we'll enter in text mode just after that + /* restore the registers */ + restore_vga_state(); +#endif +} + +static void restore_vga() +{ +#ifdef FORCE_SET_VIDEO_MODE + __dpmi_regs r; + r.x.ax = (user_mode & 0x7f) | 0x80; + __dpmi_int(0x10,&r); +#endif + restore_vga_state(RESTORE_VGA_ALL); + + // Put the data in the correct planes + RestorePlanar(win_seg_r); + + // Restore again because we touched a lot of things + restore_vga_state(RESTORE_VGA_ALL); +} + + +static void save_txt() +{ + if (user_mode != 7) + save_vga_state(); + + // Amount to save, that's isn't a fixed value: + saved_size = TextModeXres*TextModeYres*2; + + // Allocate memory + if (saved_size > buffer_size) + { + buffer = realloc(buffer,saved_size); + buffer_size = saved_size; + } + + movedata(_dos_ds,win_seg_r,_my_ds(),(int)buffer,saved_size); +} + +static void restore_txt() +{ + __dpmi_regs r; +#ifdef FORCE_SET_VIDEO_MODE +#if 0 + r.x.ax = (user_mode & 0x7f) | 0x80; + __dpmi_int(0x10,&r); +#else + TScreen::setCrtMode(user_mode); +#endif +#endif + if (user_mode != 7) + { + restore_vga_state(RESTORE_VGA_ALL); + + unsigned char height; + _dosmemgetb(0x485,1,&height); + + r.h.ah=0x11; + r.x.bx=0; + switch (height) + { + case 8: + r.h.al=0x02; + break; + case 14: + r.h.al=0x01; + break; + default: + r.h.al=0x04; + } + __dpmi_int(0x10,&r); + + restore_vga_state(RESTORE_VGA_ALL); + } + + movedata(_my_ds(),(int)buffer,_dos_ds,win_seg_r,saved_size); +} + + +/************************* Unified STUFF ************************************/ + +/***************************************************************************** + + Function: void InitSaveSystem(void) + + Description: Initialize all the needed things, must be called before all. + +*****************************************************************************/ + +static void InitSaveSystem(void) +{ + check_for_vesa(); +} + +#define VGA 0 +#define VESA 1 +#define TXTM 2 +#define NONE 255 + +static int type_saved; + +/***************************************************************************** + + Function: void SaveVideo(int text_x,int text_y) + + Description: Saves all the information to restore the actual video state. + Arguments: + text_x: The colums, which the app will overwrite in text mode + text_y: The rows, which the app will overwrite in text mode + +*****************************************************************************/ + +static int inited = 0; +static void InitSaveSystem(void); + +void set_SaveVideo(int text_x,int text_y) +{ + TextModeXres = text_x; + TextModeYres = text_y; + type_saved=NONE; + if (!inited) + { + InitSaveSystem(); + inited = 1; + } + if (vesa_supported) + if (is_vesa_mode()) + { + save_vesa(); + type_saved=VESA; + return; + } + if (is_vga_mode()) + { + save_vga(); + type_saved=VGA; + return; + } + if (is_txt_mode()) + { + save_txt(); + type_saved=TXTM; + } + // Now what can I do ...? +} + +/***************************************************************************** + + Function: void RestoreVideo(void) + + Description: Restores the saved video state. + +*****************************************************************************/ + +void set_RestoreVideo(void) +{ + switch (type_saved) + { + case TXTM: + restore_txt(); + break; + case VGA: + restore_vga(); + break; + case VESA: + restore_vesa(); + break; + } +} + +/********************** end of Unified STUFF ********************************/ + +#ifdef TEST + +// Here you can choose the methode to test + +//#define ALLEGRO +#define GRX20 +//#define TEXTMODES +#define USE_TV + + +#include +#include +#include + +#ifdef USE_TV + +#define Uses_TScreen +#if 1 +#define Uses_TEditorApp +#include + +class IDE : public TEditorApp +{ +public: + IDE() : TProgInit( &IDE::initStatusLine, + &IDE::initMenuBar, + &IDE::initDeskTop), + TEditorApp() + {} + void Suspend() { suspend(); } + void Resume() { resume(); redraw(); } +}; + +IDE *app; + +#define INIT() app = new IDE(); SUSPEND() +#define SUSPEND() app->Suspend() +#define RESUME() app->Resume() +char *ExpandFileNameToThePointWhereTheProgramWasLoaded(char *x) +{ + return x; +} + +#else +#include + +#define INIT() SUSPEND() +#define SUSPEND() TScreen::suspend() +#define RESUME() TScreen::resume() +#endif + +#else // USE_TV + +int user_mode; + +/* + This routine sets the video text mode and gets the size because I need + it to know how much memory is touched by the text mode. +*/ +void SetTextMode(int mode) +{ + if (mode>=0x100) + asm("int $0x10" : : "a"(0x4F02), "b"(mode | 0x8000)); + else + textmode(mode | 0x80); +#if 0 // now defined to Screen... + TextModeXres=ScreenCols(); + TextModeYres=ScreenRows(); +#endif +} + +/* + This routine simply clears the screen and puts some thing, I'm using + that because I'm to lazy to reproduce your changes in libtv.a +*/ +void Redraw() +{ + _farfill_l(_dos_ds,0xB8000,(TextModeXres*TextModeYres*2)/4,0x07000700); + printf("That's the screen that should be redrawed by TVision (%d,%d)\n", + TextModeXres,TextModeYres); +} + + +#define MODE 0x10C +#define INIT() SetTextMode(MODE); Redraw() +#define RESUME() SaveVideo(ScrennCols(),ScreenRows()); SetTextMode(MODE); Redraw() +#define SUSPEND() RestoreVideo() + +#endif // USE_TV + +#ifdef ALLEGRO +#include "allegro.h" + +/**************************** ALLEGRO STUFF *********************************/ +int xoff, yoff; +int mode = DRAW_MODE_SOLID; +#define NUM_PATTERNS 8 +#define TIME_SPEED 2 +BITMAP *pattern[NUM_PATTERNS]; +long tm = 0; /* counter, incremented once a second */ +int _tm = 0; + +void do_it(char *msg, int clip_flag, void (*func)()) +{ + int x1, y1, x2, y2; + + set_clip(screen, 0, 0, 0, 0); + clear(screen); + //message(msg); + + if (clip_flag) { + do { + x1 = (rand() & 255) + 32; + x2 = (rand() & 255) + 32; + } while (abs(x1-x2) < 30); + do { + y1 = (rand() & 127) + 40; + y2 = (rand() & 127) + 40; + } while (abs(y1-y2) < 20); + set_clip(screen, xoff+x1, yoff+y1, xoff+x2, yoff+y2); + } + + drawing_mode(mode, pattern[rand()%NUM_PATTERNS], 0, 0); + + (*func)(); + + solid_mode(); +} + +int next() +{ + if (keypressed()) { + clear_keybuf(); + return TRUE; + } + + if (mouse_b) { + do { + } while (mouse_b); + return TRUE; + } + + return FALSE; +} + +void putpix_demo() +{ + int c = 0; + int x, y; + long ct; + + tm = 0; _tm = 0; + ct = 0; + + while (!next()) { + + x = (rand() & 511) + 32; + y = (rand() & 255) + 40; + putpixel(screen, xoff+x, yoff+y, c); + + if (mode >= DRAW_MODE_COPY_PATTERN) + drawing_mode(mode, pattern[rand()%NUM_PATTERNS], 0, 0); + + if (++c >= 16) + c = 0; + + if (ct >= 0) { + if (tm >= TIME_SPEED) { + ct = -1; + } + else + ct++; + } + } +} + +void line_demo() +{ + int c = 0; + int x1, y1, x2, y2; + long ct; + + tm = 0; _tm = 0; + ct = 0; + + while (!next()) { + + x1 = (rand() & 511) + 32; + x2 = (rand() & 511) + 32; + y1 = (rand() & 255) + 40; + y2 = (rand() & 255) + 40; + line(screen, xoff+x1, yoff+y1, xoff+x2, yoff+y2, c); + + if (mode >= DRAW_MODE_COPY_PATTERN) + drawing_mode(mode, pattern[rand()%NUM_PATTERNS], 0, 0); + + if (++c >= 16) + c = 0; + + if (ct >= 0) { + if (tm >= TIME_SPEED) { + ct = -1; + } + else + ct++; + } + } +} + +void Next() +{ + while (next()==FALSE); +} +/******************************* END of ALLEGRO STUFF **********************/ + +int main() +{ + int i; + + allegro_init(); + + INIT(); + getch(); + + install_keyboard(); + install_timer(); + initialise_joystick(); + install_mouse(); + set_gfx_mode(GFX_VGA, 320, 200, 0, 0); + set_pallete(desktop_pallete); + show_mouse(NULL); + + int card,w,h; + + if (!gfx_mode_select(&card, &w, &h)) + { + allegro_exit(); + printf("Aborting\n\n"); + exit(1); + } + + show_mouse(NULL); + if (set_gfx_mode( card, w, h, 0, 0)) + { + allegro_exit(); + printf("Error setting graphics mode\n%s\n\n", allegro_error); + exit(1); + } + set_pallete(desktop_pallete); + do_it("timing putpixel", FALSE, putpix_demo); + Next(); + RESUME(); + Next(); + SUSPEND(); + Next(); + RESUME(); + Next(); + SUSPEND(); + do_it("timing line", FALSE, line_demo); + Next(); + RESUME(); + Next(); + SUSPEND(); + Next(); + RESUME(); + Next(); + SUSPEND(); + Next(); + RESUME(); + Next(); + SUSPEND(); + Next(); + textmode(3); + allegro_exit(); + return 0; +} +#endif // ALLEGRO + +#ifdef GRX20 +/******************************* GRX20 STUFF *******************************/ +#include + +int main() +{ + int i; + char Buf[4]; + INIT(); + getch(); + GrSetMode(GR_width_height_color_graphics,640,480,16); + //GrSetMode(GR_width_height_color_graphics,320,200,256); + GrClearScreen(GrBlack()); + Buf[0]=32; + Buf[1]=33; + Buf[2]=34; + Buf[3]=35; + _dosmemputb(Buf,4,0xA0000); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + for (i=0;i<16;i++) + { + GrFilledBox(i*21,0,i*21+20,15,i); + } + GrFilledEllipse(300,200,50,50,GrAllocColor(0,0,255)); + GrPlot(3,92,32); + GrPlot(3,108,32); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + RESUME(); + getch(); + SUSPEND(); + GrEllipseArc(300,200,50,50,10,10,GR_ARC_STYLE_CLOSE2,GrWhite()); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + GrClearScreen(GrBlack()); + GrFilledEllipse(300,200,50,50,GrAllocColor(0,0,255)); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + GrEllipseArc(300,200,50,50,10,10,GR_ARC_STYLE_CLOSE2,GrWhite()); + GrFilledEllipse(300,200,50,50,GrAllocColor(0,0,255)); + GrFilledEllipse(300,200,50,50,GrWhite()); + getch(); + RESUME(); + getch(); + SUSPEND(); + GrTextXY(0,0,"This is a sample text",GrWhite(),GrNOCOLOR); + //GrEllipseArc(300,80,50,50,10,10,GR_ARC_STYLE_CLOSE2,GrWhite()); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + textmode(3); + return 0; +} +#endif // GRX20 + +#ifdef TEXTMODES + +#define TxtMode(var) asm("int $0x10": : "a"(var)) + +int main() +{ + int i; + char Buf[4]; + INIT(); + TxtMode(3); + textattr(0x7A); + cprintf("Screen to restore, 80x25 color\n"); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + RESUME(); + getch(); + SUSPEND(); + TxtMode(0); + textattr(0x8A); + cprintf("Screen to restore, 40x25 color\n"); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + RESUME(); + getch(); + SUSPEND(); + TxtMode(3); + _set_screen_lines(50); + textattr(0x7B); + gotoxy(10,10); + cprintf("Screen to restore, 80x50 color\n"); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + RESUME(); + getch(); + SUSPEND(); + _set_screen_lines(43); + textattr(0x7C); + gotoxy(30,30); + cprintf("Screen to restore, 80x43 color\n"); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + RESUME(); + getch(); + SUSPEND(); + textmode(7); + gotoxy(30,10); + highvideo(); + cprintf("Screen to restore, 80x25 b&w\n"); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + textmode(3); + return 0; +} +#endif // TEXTMODES + +#endif + +#endif // DJGPP diff --git a/tvision/classes/dos/vesa.cc b/tvision/classes/dos/vesa.cc new file mode 100644 index 0000000..5bcc13f --- /dev/null +++ b/tvision/classes/dos/vesa.cc @@ -0,0 +1,589 @@ +/**[txh]******************************************************************** + + Description: + That's the Robert's version of the VESA video modes handling routines.@* + Some stuff modified by me (SET): + +* Support for S3 text mode way to report planes. +* Removed the need to allocate DOS memory for the VESA structures, that's +bad because we reduce the available memory and because at least one VESA +2.0 TSR for S3 boards have the bad idea to return more bytes than what the +spec says overwriting memory. I know it from the FreeBE/AF project. So now +I changed it to use the transfer buffer and copy it to malloced memory. +BTW: this change saved 172 bytes of code and added 20 bytes of data. + +***************************************************************************/ + +/* Copyright (C) 1996-1998 Robert H”hne, this file is part of RHTVision and + is under the GPL license */ +#include + +#ifdef TVCompf_djgpp +/* + This file is used to save/restore the graphics screen when a + VESA mode is set. + I have tested it with all the modes, which are available on my + et4000 card. They work when the graphic mode is set by the + libgrx20 library. After testing with the VESA 1 modes from + the ALLEGRO library I saw, that they NOT work correct, but + I don't know why. + +0x0100 640 x 400 x 256 +0x0101 640 x 480 x 256 +0x0102 800 x 600 x 16 +0x0103 800 x 600 x 256 +0x0104 1024 x 768 x 16 +0x0105 1024 x 768 x 256 +0x0106 1280 x 1024 x 16 + +The function save_vesa assumes, that is_vesa_mode called before and +was successfull. There is no other check for validity. +And the function restore_vesa assumes that save_vesa was called +before. +*/ + +#include +#include +#include +#include +#include + +// SET: I found this value is board dependant and Robert taked a value that +// works with most of the boards. +int rh_vesa_size=256*1024; + +typedef unsigned short ushort; + +extern int user_mode; + +static void *buffer = NULL; +static int buffer_size = 0; +static int saved_size; +static int window_r; +static int window_w; +static int win_size; +static unsigned win_seg_r; +static unsigned win_seg_w; + +// SET: I changed the stuff related to this structure, see in the header +// comments of vesa.cc file. +// Robert originally taked it from the vesa.h of GRX library, I changed some +// comments to match the "VESA Super VGA Standard VS911022-14" text. And +// changed to ushort type. +/* This is for g++ 2.7.2 and below */ +#pragma pack(1) +typedef struct { + ushort modeAttributes CLY_Packed;//mode attributes +#define ModeAttributes infoBk.modeAttributes + char winAAttributes CLY_Packed;// Window A attributes + char winBAttributes CLY_Packed;// Window B attributes +#define WinAAttributes infoBk.winAAttributes +#define WinBAttributes infoBk.winBAttributes + ushort winGranularity CLY_Packed;// Window granularity +#define WinGranularity infoBk.winGranularity + ushort winSize CLY_Packed;// Window size +#define WinSize infoBk.winSize + ushort winASegment CLY_Packed;// Window A start segment + ushort winBSegment CLY_Packed;// Window B start segment +#define WinASegment infoBk.winASegment +#define WinBSegment infoBk.winBSegment + void (*WinFuncPtr)() CLY_Packed;// Pointer to window function + ushort BytesPerScanLine CLY_Packed;// Bytes per scan line + +// ==== extended and optional information ==== Mandatory since VESA 1.2 + + ushort XResolution CLY_Packed;// Horizontal resolution + ushort YResolution CLY_Packed;// Vertical resolution + char XCharSize CLY_Packed;// Character cell width + char YCharSize CLY_Packed;// Character cell height + char numberOfPlanes CLY_Packed;// Number of memory planes +#define NumberOfPlanes infoBk.numberOfPlanes +/* + char BitsPerPixel CLY_Packed;// Bits per pixel + char NumberOfBanks CLY_Packed;// Number of banks + char MemoryModel CLY_Packed;// Memory model type + char BankSize CLY_Packed;// Bank size in K + char NumImagePages CLY_Packed;// Number of image pages + char reserved[1] CLY_Packed;// Reserved for page function + +// ==== VESA 1.2 and later ==== + + char RedMaskSize CLY_Packed;// Size of direct color red mask in bits + char RedMaskPos CLY_Packed;// Bit position of LSB of red mask + char GreenMaskSize CLY_Packed;// Idem green + char GreenMaskPos CLY_Packed; + char BlueMaskSize CLY_Packed;// Idem blue + char BlueMaskPos CLY_Packed; + char ReservedMaskSize CLY_Packed;// Idem reserved bits + char ReservedMaskPos CLY_Packed; + char DirectScreenMode CLY_Packed;// Direct Color mode attributes + char reserved2[216] CLY_Packed; +*/ +} VESAmodeInfoBlock; +#pragma pack() +// This block is globally accessed with the macros. +static VESAmodeInfoBlock infoBk; + + +static +int GetVesaModeInfo(int mode) +{ + __dpmi_regs r; + r.x.ax = 0x4f01; + r.x.es = __tb>>4; // SET: changed to use tb. + r.x.di = __tb & 0xF; + r.x.cx = mode; + __dpmi_int(0x10,&r); + if (r.x.ax!=0x004f) + return 0; + dosmemget(__tb,sizeof(infoBk),&infoBk); + return 1; +} + +static int vesa_state_segment = -1; +static int vesa_state_selector; + +static +void save_vesa_state() +{ + __dpmi_regs r; + if (vesa_state_segment == -1) + { + r.x.ax = 0x4f04; + r.h.dl = 0x00; + r.x.cx = 0x000f; + __dpmi_int(0x10,&r); + if (r.x.ax != 0x004f) return; + vesa_state_segment = + __dpmi_allocate_dos_memory(r.x.bx*4,&vesa_state_selector); + if (vesa_state_segment == -1) return; + } + r.x.ax = 0x4f04; + r.h.dl = 0x01; + r.x.es = vesa_state_segment; + r.x.bx = 0; + r.x.cx = 0x000f; + __dpmi_int(0x10,&r); +} + +static +void restore_vesa_state() +{ + __dpmi_regs r; + if (vesa_state_segment == -1) return; + r.x.ax = 0x4f04; + r.h.dl = 0x02; + r.x.es = vesa_state_segment; + r.x.bx = 0; + r.x.cx = 0x000f; + __dpmi_int(0x10,&r); +} + +int rh_vesa_supported = 0; + +void rh_check_for_vesa() +{ + __dpmi_regs r; + + r.x.ax = 0x4f03; + __dpmi_int(0x10,&r); + + /* Not supported */ + if (r.h.al != 0x4f) return; + + rh_vesa_supported = 1; +} + +int rh_is_vesa_mode() +{ + __dpmi_regs r; + + r.x.ax = 0x4f03; + __dpmi_int(0x10,&r); + + /* Not supported or not successful */ + if (r.x.ax != 0x004f) return 0; + + /* Because GetVesaModeInfo forces a screen switch under W95, I check + the most common textmode here without calling that function */ + if (r.x.bx == 0x0003 || r.x.bx == 7) + return 0; + + if (!GetVesaModeInfo(r.x.bx)) + return 0; + + if (!(ModeAttributes & 1)) + // not supported + return 0; + + user_mode = r.x.bx; + + return 1; +} + +/* + * Sequencer port and frequently used register indices + */ +#define VGA_SEQUENCER_PORT 0x3c4 +#define VGA_SEQUENCER_DATA 0x3c5 + +#define VGA_WRT_PLANE_ENB_REG 2 + +/* + * color plane operations + */ +#define VGA_FUNC_SET 0 +#define VGA_FUNC_AND 8 +#define VGA_FUNC_OR 16 +#define VGA_FUNC_XOR 24 + +/* + * Graphics controller port and frequently used registers + */ +#define VGA_GR_CTRL_PORT 0x3ce +#define VGA_GR_CTRL_DATA 0x3cf + +#define VGA_SET_RESET_REG 0 +#define VGA_SET_RESET_ENB_REG 1 +#define VGA_COLOR_COMP_REG 2 +#define VGA_ROT_FN_SEL_REG 3 +#define VGA_RD_PLANE_SEL_REG 4 +#define VGA_MODE_REG 5 +#define VGA_MISC_REG 6 +#define VGA_COLOR_DONTC_REG 7 +#define VGA_BIT_MASK_REG 8 + +#include + +void rh_save_vesa() +{ + int offset = 0, off_in_page=0; + int seg = 0; + __dpmi_regs r; + save_vesa_state(); + + if (WinBAttributes & 0x3) /* exist and readable */ + { + window_r = 1; + win_seg_r = WinBSegment; + /* I assume here, that now winb is writable. Is that correct?? */ + window_w = 0; + win_seg_w = WinASegment; + } + else + { + window_w = window_r = 0; + win_seg_r = win_seg_w = WinASegment; + } + win_size = WinSize * 1024; + + win_seg_r <<= 4; + win_seg_w <<= 4; + + saved_size = rh_vesa_size; + + if (saved_size < win_size) + win_size = saved_size; + + if (saved_size > buffer_size) + { + buffer = realloc(buffer,saved_size); + buffer_size = saved_size; + } + + while (offset < saved_size) + { + if (ModeAttributes & 0x10) // graphic ? + { + r.x.ax = 0x4f05; + r.x.bx = window_r; + r.x.dx = seg; + __dpmi_int(0x10,&r); + + if (NumberOfPlanes > 1) + { + int i; + int bs = win_size / 4; + + /* now set to read mode 0 */ + outportw(VGA_GR_CTRL_PORT,((0x00 << 8) | VGA_MODE_REG)); + for (i=0;i<4;i++) + { + /* read from plane 'i' */ + outportw(VGA_GR_CTRL_PORT,((i << 8) | VGA_RD_PLANE_SEL_REG)); + + movedata(_dos_ds,win_seg_r+off_in_page,_my_ds(),(int)buffer+offset,bs); + offset += bs; + } + off_in_page+=bs; + if (off_in_page>=win_size) + { + off_in_page=0; + seg++; + } + } + } + // SET: Text modes are 1 plane but some BIOS like the S3 ones reports it + // as 4 planes because the fonts are located in the second pair of banks. + // S3 BIOSes are normally buggy so I guess that's just another bug by S3. + if (NumberOfPlanes==1 || !(ModeAttributes & 0x10)) + { + movedata(_dos_ds,win_seg_r,_my_ds(),(int)buffer+offset,win_size); + offset += win_size; + seg++; + } + } +// restore_vesa_state(); +} + +__inline__ void +_farnsandl(unsigned long offset, + unsigned long value) +{ + __asm__ __volatile__ (".byte 0x64\n" + " andl %k0,(%k1)" + : + : "ri" (value), "r" (offset)); +} + +__inline__ void +_farfill_l(unsigned short sel,unsigned long offset,unsigned long count, + unsigned long value) +{ + __asm__ __volatile__ ( + "pushw %%es\n" + "movw %w0,%%es\n" + "cld\n" + "rep\n" + "stosl\n" + "popw %%es" + : + : "rm" (sel), "a" (value), "D" (offset), "c" (count)); +} + +void rh_restore_vesa() +{ + int offset = 0, off_in_page = 0, off; + int seg = 0; + __dpmi_regs r; + r.x.ax = 0x4f02; + r.x.bx = user_mode | 0x8000; + __dpmi_int(0x10,&r); + restore_vesa_state(); + while (offset < saved_size) + { + if (ModeAttributes & 0x10) // graphic ?? + { + r.x.ax = 0x4f05; + r.x.bx = window_w; + r.x.dx = seg; + __dpmi_int(0x10,&r); + + r.x.ax = 0x4f05; + r.x.bx = window_r; + r.x.dx = seg; + __dpmi_int(0x10,&r); + + if (NumberOfPlanes > 1) + { + int i,j; + int bs = win_size / 4; + + outportw(VGA_GR_CTRL_PORT,(VGA_FUNC_SET << 8) | VGA_ROT_FN_SEL_REG); + /* enable all planes for writing */ + outportw(VGA_SEQUENCER_PORT,((0x0f << 8) | VGA_WRT_PLANE_ENB_REG)); + /* eanable all planes for set/reset */ + outportw(VGA_GR_CTRL_PORT,((0x00 << 8) | VGA_SET_RESET_ENB_REG)); + /* set all planes for reset */ + outportw(VGA_GR_CTRL_PORT,((0x00 << 8) | VGA_SET_RESET_REG)); +#if 0 + /* set write mode 3 */ + outportw(VGA_GR_CTRL_PORT,((8+3) << 8) | VGA_MODE_REG); +#endif + /* clear all */ + _farfill_l(_dos_ds,win_seg_w+off_in_page,bs/4,0xffffffffL); + unsigned long *_l = (unsigned long *)(((char *)buffer)+offset); + for (i=0;i<4;i++) + { +#if 1 + /* enable plane 'i' for writing */ + outportw(VGA_SEQUENCER_PORT,(((1 << i) << 8) | VGA_WRT_PLANE_ENB_REG)); +#endif + /* eanable plane 'i' for set/reset */ + outportw(VGA_GR_CTRL_PORT,(((1 << i) << 8) | VGA_SET_RESET_ENB_REG)); + /* enable plane 'i' for set */ + outportw(VGA_GR_CTRL_PORT,(((1 << i) << 8) | VGA_SET_RESET_REG)); +#if 0 + /* set write mode 3 */ + outportw(VGA_GR_CTRL_PORT,((8+3) << 8) | VGA_MODE_REG); +#endif + _farsetsel(_dos_ds); + off=win_seg_w+off_in_page; + for (j=0;j=win_size) + { + off_in_page=0; + seg++; + } + } + } + if (NumberOfPlanes==1 || !(ModeAttributes & 0x10)) + { + movedata(_my_ds(),(int)buffer+offset,_dos_ds,win_seg_w,win_size); + offset += win_size; + seg++; + } + } + /* restore again, because of the change of the registers and the bank */ + restore_vesa_state(); +} + +#ifdef TEST + +//#define USE_TV + +#include +#include +#include +#include + +#ifdef USE_TV + +#define getch() + +#define Uses_TScreen +#if 1 +#define Uses_TEditorApp +#include + +class IDE : public TEditorApp +{ +public: + IDE() : TProgInit( &IDE::initStatusLine, + &IDE::initMenuBar, + &IDE::initDeskTop), + TEditorApp() + {} + void Suspend() { suspend(); } + void Resume() { resume(); Redraw(); } +}; + +IDE *app; + +#define INIT() app = new IDE(); SUSPEND() +#define SUSPEND() app->Suspend() +#define RESUME() app->Resume() +char *ExpandFileNameToThePointWhereTheProgramWasLoaded(char *x) +{ + return x; +} + +#else +#include + +#define INIT() SUSPEND() +#define SUSPEND() TScreen::suspend() +#define RESUME() TScreen::resume() +#endif + +#else + +#define INIT() textmode(3) +#define RESUME() if (!rh_is_vesa_mode()) { printf("Isn't VESA\n"); exit(1); }; rh_save_vesa(); textmode(0x3) +#define SUSPEND() rh_restore_vesa() + +#endif +int user_mode; + +int main(int argc, char *argv[]) +{ + int i; + char *end; +#ifdef USE_TV + extern int screen_saving; + screen_saving = 1; +#endif + if (argc!=2) + { + printf("Error: you must pass to the program the amount of memory to save\n"); + return 1; + } + rh_vesa_size=strtol(argv[1],&end,0); + INIT(); + printf("We are in text mode\n"); + getch(); + GrSetMode(GR_width_height_color_graphics,640,480,256); + GrSetMode(GR_width_height_color_graphics,1024,768,256); + GrClearScreen(GrBlack()); + for (i=0;i<16;i++) + { + GrFilledBox(i*21,0,i*21+20,15,i); + } + GrFilledEllipse(GrMaxX()-100,GrMaxY()-100,50,50,GrAllocColor(0,0,255)); + getch(); + RESUME(); + printf("Now we are in text mode again but the graphic mode was saved\n"); + getch(); + SUSPEND(); + getch(); + RESUME(); + printf("Was restored OK?\n"); + getch(); +/* SUSPEND(); + getch(); + for (i=0;i<16;i++) + { + GrFilledBox(i*21,0,i*21+20,15,i); + } + GrFilledEllipse(300,200,50,50,GrAllocColor(0,0,255)); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + RESUME(); + getch(); + SUSPEND(); + GrEllipseArc(300,200,50,50,10,10,GR_ARC_STYLE_CLOSE2,GrWhite()); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + GrClearScreen(GrBlack()); + GrFilledEllipse(300,200,50,50,GrAllocColor(0,0,255)); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + GrEllipseArc(300,200,50,50,10,10,GR_ARC_STYLE_CLOSE2,GrWhite()); + GrFilledEllipse(300,200,50,50,GrAllocColor(0,0,255)); + GrFilledEllipse(300,200,50,50,GrWhite()); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + GrTextXY(0,0,"This is a sample text",GrWhite(),GrNOCOLOR); + RESUME(); + getch(); + SUSPEND(); + getch(); + textmode(3);*/ + return 0; +} +#endif + +#endif // DJGPP + diff --git a/tvision/classes/dos/vga.cc b/tvision/classes/dos/vga.cc new file mode 100644 index 0000000..2c3a4a6 --- /dev/null +++ b/tvision/classes/dos/vga.cc @@ -0,0 +1,449 @@ +/* Copyright (C) 1996-1998 Robert H”hne, see COPYING.RH for details */ +/* This file is part of RHIDE. */ +#include +#include "vgastate.h" + +#ifdef TVCompf_djgpp + +/* + This file is used to save/restore the graphics screen when a + VGA mode is set. + I have tested it with all the modes, which are available on my + et4000 card. + + 320x200x16 + 640x200x16 + 640x350x16 + 640x480x16 + 320x200x256 + 320x240x256 + 320x400x256 + 360x480x256 + +The function save_vga assumes, that is_vga_mode called before and +was successfull. There is no other check for validity. +And the function restore_vga assumes that save_vga was called +before. +*/ + +#include +#include +#include +#include +#include + +#define SIZE 0x8000 + +extern int user_mode; + +static void *buffer = NULL; +static int buffer_size = 0; +static int saved_size; +static int win_size; +static unsigned win_seg; +static int is_plane_mode = 0; +static int mode_x; + +// For BIOS save state +static int vga_state_segment = -1; +static int vga_state_selector; +// For low level save state +static void *vgaState=0; + +char useBIOS_VGA_State=1; +char saveVGA_State=0; + +void rh_save_vga_state() +{ + if (!saveVGA_State) return; + if (useBIOS_VGA_State) + {// SET: It fails for some Matrox boards. + __dpmi_regs r; + if (vga_state_segment == -1) + { + r.x.ax = 0x1c00; + r.x.cx = 0x0007; + __dpmi_int(0x10,&r); + if (r.h.al != 0x1c) return; + vga_state_segment = + __dpmi_allocate_dos_memory(r.x.bx*4,&vga_state_selector); + if (vga_state_segment == -1) return; + } + r.x.ax = 0x1c01; + r.x.es = vga_state_segment; + r.x.bx = 0; + r.x.cx = 0x0007; + __dpmi_int(0x10,&r); + } + else + { + if (!vgaState) + vgaState=malloc(VGAStateGetBufferSize()); + VGAStateSave(vgaState); + } +} + +void rh_restore_vga_state() +{ + if (!saveVGA_State) return; + if (useBIOS_VGA_State) + {// SET: It fails for some Matrox boards. + __dpmi_regs r; + if (vga_state_segment == -1) return; + r.x.ax = 0x1c02; + r.x.es = vga_state_segment; + r.x.bx = 0; + r.x.cx = 0x0007; + __dpmi_int(0x10,&r); + } + else + VGAStateLoad(vgaState); +} + +/* + * Sequencer port and frequently used register indices + */ +#define VGA_SEQUENCER_PORT 0x3c4 +#define VGA_SEQUENCER_DATA 0x3c5 + +#define VGA_WRT_PLANE_ENB_REG 2 +#define VGA_MEMORY_MODE_REG 4 + +/* + * color plane operations + */ +#define VGA_FUNC_SET 0 +#define VGA_FUNC_AND 8 +#define VGA_FUNC_OR 16 +#define VGA_FUNC_XOR 24 + +/* + * Graphics controller port and frequently used registers + */ +#define VGA_GR_CTRL_PORT 0x3ce +#define VGA_GR_CTRL_DATA 0x3cf + +#define VGA_SET_RESET_REG 0 +#define VGA_SET_RESET_ENB_REG 1 +#define VGA_COLOR_COMP_REG 2 +#define VGA_ROT_FN_SEL_REG 3 +#define VGA_RD_PLANE_SEL_REG 4 +#define VGA_MODE_REG 5 +#define VGA_MISC_REG 6 +#define VGA_COLOR_DONTC_REG 7 +#define VGA_BIT_MASK_REG 8 + +#include + +int rh_is_vga_mode() +{ + __dpmi_regs r; + + r.x.ax = 0x0f00; + __dpmi_int(0x10,&r); + + if (r.h.al != 0x12 && + r.h.al != 0x13 && + r.h.al != 0x0d && + r.h.al != 0x0e && + r.h.al != 0x10 + ) return 0; + + user_mode = r.h.al; + + mode_x = 0; + + if (user_mode == 0x12 || + user_mode == 0x0d || + user_mode == 0x0e || + user_mode == 0x10 + ) + is_plane_mode = 1; + else + { + unsigned char b; + outportb(VGA_SEQUENCER_PORT,VGA_MEMORY_MODE_REG); + b = inportb(VGA_SEQUENCER_DATA); + is_plane_mode = b & 0x08 ? 0 : 1; + mode_x = is_plane_mode; + } + + return 1; +} + +void rh_save_vga() +{ + int offset = 0; + rh_save_vga_state(); + win_seg = 0xa0000; + + win_size = 64 * 1024; + + saved_size = SIZE; + + if (saved_size < win_size) + win_size = saved_size; + + if (saved_size > buffer_size) + { + buffer = realloc(buffer,saved_size); + buffer_size = saved_size; + } + + while (offset < saved_size) + { + if (is_plane_mode) + { + int i; + int bs = win_size / 4; + + int modereg; + outportb(VGA_GR_CTRL_PORT,VGA_MODE_REG); + modereg = inportb(VGA_GR_CTRL_DATA) & 0xf0; + /* now set to read mode 0 */ + outportw(VGA_GR_CTRL_PORT,(modereg << 8) | VGA_MODE_REG); + for (i=0;i<4;i++) + { + /* read from plane 'plane' */ + outportw(VGA_GR_CTRL_PORT,((i << 8) | VGA_RD_PLANE_SEL_REG)); + + movedata(_dos_ds,win_seg,_my_ds(),(int)buffer+offset,bs); + offset += bs; + } + +#if 0 + /* restore the registers */ + rh_restore_vga_state(); +#endif + } + else + { + movedata(_dos_ds,win_seg,_my_ds(),(int)buffer+offset,win_size); + offset += win_size; + } + } +} + +__inline__ void +_farnsandl(unsigned long offset, + unsigned long value) +{ + __asm__ __volatile__ (".byte 0x64\n" + " andl %k0,(%k1)" + : + : "ri" (value), "r" (offset)); +} + +__inline__ void +_farfill_l(unsigned short sel,unsigned long offset,unsigned long count, + unsigned long value) +{ + __asm__ __volatile__ ( + "pushw %%es\n" + "movw %w0,%%es\n" + "cld\n" + "rep\n" + "stosl\n" + "popw %%es" + : + : "rm" (sel), "a" (value), "D" (offset), "c" (count)); +} + +void rh_restore_vga() +{ + int offset = 0; + __dpmi_regs r; + r.x.ax = (user_mode & 0x7f) | 0x80; + __dpmi_int(0x10,&r); + rh_restore_vga_state(); + + while (offset < saved_size) + { + if (is_plane_mode) + { + int i,j; + int bs = win_size / 4; + + outportw(VGA_GR_CTRL_PORT,(VGA_FUNC_SET << 8) | VGA_ROT_FN_SEL_REG); + /* enable all planes for writing */ + outportw(VGA_SEQUENCER_PORT,((0x0f << 8) | VGA_WRT_PLANE_ENB_REG)); + /* eanable all planes for set/reset */ + outportw(VGA_GR_CTRL_PORT,((0x00 << 8) | VGA_SET_RESET_ENB_REG)); + /* set all planes for reset */ + outportw(VGA_GR_CTRL_PORT,((0x00 << 8) | VGA_SET_RESET_REG)); +#if 0 + /* set write mode 3 */ + outportw(VGA_GR_CTRL_PORT,((8+3) << 8) | VGA_MODE_REG); +#endif + /* clear all */ + if (!mode_x) + { + _farfill_l(_dos_ds,win_seg,bs/4,0xffffffffL); + } + unsigned long *_l = (unsigned long *)buffer; + for (i=0;i<4;i++) + { +#if 1 + /* enable plane 'i' for writing */ + outportw(VGA_SEQUENCER_PORT,(((1 << i) << 8) | VGA_WRT_PLANE_ENB_REG)); +#endif + if (!mode_x) + { + /* eanable plane 'i' for set/reset */ + outportw(VGA_GR_CTRL_PORT,(((1 << i) << 8) | VGA_SET_RESET_ENB_REG)); + /* enable plane 'i' for set */ + outportw(VGA_GR_CTRL_PORT,(((1 << i) << 8) | VGA_SET_RESET_REG)); + } +#if 0 + /* set write mode 3 */ + outportw(VGA_GR_CTRL_PORT,((8+3) << 8) | VGA_MODE_REG); +#endif + if (mode_x) + { + movedata(_my_ds(),(int)_l,_dos_ds,win_seg,bs); + _l += bs/4; + } + else + { + _farsetsel(_dos_ds); + for (j=0;j +#include +#include +#include + +#ifdef USE_TV + +#define getch() + +#define Uses_TScreen +#if 1 +#define Uses_TEditorApp +#include + +class IDE : public TEditorApp +{ +public: + IDE() : TProgInit( &IDE::initStatusLine, + &IDE::initMenuBar, + &IDE::initDeskTop), + TEditorApp() + {} + void Suspend() { suspend(); } + void Resume() { resume(); Redraw(); } +}; + +IDE *app; + +#define INIT() app = new IDE(); SUSPEND() +#define SUSPEND() app->Suspend() +#define RESUME() app->Resume() +char *ExpandFileNameToThePointWhereTheProgramWasLoaded(char *x) +{ + return x; +} + +#else +#include + +#define INIT() SUSPEND() +#define SUSPEND() TScreen::suspend() +#define RESUME() TScreen::resume() +#endif + +#else + +#define INIT() textmode(3) +#define RESUME() rh_is_vga_mode(); rh_save_vga(); textmode(0x83) +#define SUSPEND() rh_restore_vga() + +#endif + +int main() +{ + int i; +#ifdef USE_TV + extern int screen_saving; + screen_saving = 1; +#endif + INIT(); + getch(); + GrSetMode(GR_width_height_color_graphics,360,480,256); + GrClearScreen(GrBlack()); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + for (i=0;i<16;i++) + { + GrFilledBox(i*21,0,i*21+20,15,i); + } + GrFilledEllipse(300,200,50,50,GrAllocColor(0,0,255)); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + RESUME(); + getch(); + SUSPEND(); + GrEllipseArc(300,200,50,50,10,10,GR_ARC_STYLE_CLOSE2,GrWhite()); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + GrClearScreen(GrBlack()); + GrFilledEllipse(300,200,50,50,GrAllocColor(0,0,255)); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + GrEllipseArc(300,200,50,50,10,10,GR_ARC_STYLE_CLOSE2,GrWhite()); + GrFilledEllipse(300,200,50,50,GrAllocColor(0,0,255)); + GrFilledEllipse(300,200,50,50,GrWhite()); + getch(); + RESUME(); + getch(); + SUSPEND(); + getch(); + GrTextXY(0,0,"This is a sample text",GrWhite(),GrNOCOLOR); + RESUME(); + getch(); + SUSPEND(); + getch(); + textmode(3); + return 0; +} +#endif + +#endif // DJGPP + diff --git a/tvision/classes/dos/vgaregs.c b/tvision/classes/dos/vgaregs.c new file mode 100644 index 0000000..ed70088 --- /dev/null +++ b/tvision/classes/dos/vgaregs.c @@ -0,0 +1,225 @@ +/* Copyright 2000 (c) by Salvador Eduardo Tropea + This code is part of the port of Turbo Vision to gcc, please see the rest + of the file for copying information. + */ +/* + This module provides the functions declared inline in vgaregs.h. + They are needed only if you compile without optimizations. +*/ +#include + +#define NO_INLINE +typedef unsigned char uchar; +typedef unsigned short ushort; +#include "vgaregs.h" + +#ifdef TVCompf_djgpp + +#ifdef SAFE_IO +/* C approach, safier than my assembler ;-) */ + +uchar ReadCRT(uchar index) +{ + outportb(CRTControllerIndex,index); + return inportb(CRTControllerData); +} + +uchar ReadGRA(uchar index) +{ + outportb(GraphicsControllerIndex,index); + return inportb(GraphicsControllerData); +} + +uchar ReadSEQ(uchar index) +{ + outportb(SequencerIndex,index); + return inportb(SequencerData); +} + +void WriteCRT(uchar index, uchar value) +{ + outportb(CRTControllerIndex,index); + outportb(CRTControllerData,value); +} + + +void WriteGRA(uchar index, uchar value) +{ + outportb(GraphicsControllerIndex,index); + outportb(GraphicsControllerData,value); +} + +void WriteSEQ(uchar index, uchar value) +{ + outportb(SequencerIndex,index); + outportb(SequencerData,value); +} + +void WaitVRT() +{ + while (inportb(InputStatusRegister1) & 8); + while (!(inportb(InputStatusRegister1) & 8)); +} + +#else + +uchar ReadCRT(uchar index) +{ + int dummy; + uchar a RegEAX; + a=index; + asm volatile ( +" outb %%al,%%dx \n" +" incl %%edx \n" +" inb %%dx,%%al \n" + : "=a" (a), "=d" (dummy) : "a" (a), "d" (CRTController)); + return a; +} + + +uchar ReadGRA(uchar index) +{ + int dummy; + uchar a RegEAX; + a=index; + asm volatile ( +" outb %%al,%%dx \n" +" incl %%edx \n" +" inb %%dx,%%al \n" + : "=a" (a), "=d" (dummy) : "a" (a), "d" (GraphicsController)); + return a; +} + +uchar ReadSEQ(uchar index) +{ + int dummy; + uchar a RegEAX; + a=index; + asm volatile ( +" outb %%al,%%dx \n" +" incl %%edx \n" +" inb %%dx,%%al \n" + : "=a" (a), "=d" (dummy) : "a" (a), "d" (Sequencer)); + return a; +} + +void WriteCRT(uchar index, uchar value) +{ + int dummy; + asm volatile ( +" movb %1,%%ah \n" +" outw %%ax,%%dx \n" + : "=a" (dummy) : "qi" (value), "a" (index), "d" (CRTController)); +} + +void WriteGRA(uchar index, uchar value) +{ + int dummy; + asm volatile ( +" movb %1,%%ah \n" +" outw %%ax,%%dx \n" + : "=a" (dummy) : "qi" (value), "a" (index), "d" (GraphicsController)); +} + +void WriteSEQ(uchar index, uchar value) +{ + int dummy; + asm volatile ( +" movb %1,%%ah \n" +" outw %%ax,%%dx \n" + : "=a" (dummy) : "qi" (value), "a" (index), "d" (Sequencer)); +} + +void WaitVRT() +{ + asm volatile( +" 1: \n" +" inb %%dx,%%al \n" +" testb $8,%%al \n" +" jne 1b \n" +" .align 2,0x90 \n" +" 2: \n" +" inb %%dx,%%al \n" +" testb $8,%%al \n" +" je 2b \n" + : : "d" (InputStatusRegister1) : "%eax" ); +} + +#endif + +uchar ReadATT(int index) +{ + /* Ensure we will write to the index */ + inportb(ATTdir); + /* Set the index and disable the screen or we will read nothing */ + outportb(ATTindex,index); + return inportb(ATTdataR); +} + +void ATTEndReads(void) +{ + /* Ensure we will write to the index */ + inportb(ATTdir); + /* Enable the screen */ + outportb(ATTindex,0x20); +} + +void WriteATT(int index, int val) +{ + outportb(ATTindex,index); + outportb(ATTdataW,val); +} + +uchar ReadMOR(void) +{ + return inportb(MORdataR); +} + +void WriteMOR(int val) +{ + outportb(MORdataW,val); +} + +uchar ReadEDAC(int index) +{ + outportb(EDACindex,index); + return inportb(EDACdata); +} + +void WriteEDAC(int index, int val) +{ + outportb(EDACindex,index); + outportb(EDACdata,val); +} + +void RPF_SetPalRange(unsigned char *_pal_ptr, int color, int cant) +{ + int dummy1,dummy2,dummy3,dummy4; + asm volatile( +" outb %%al,%%dx \n" +" incl %%edx \n" +" cli \n" +" rep \n" +" outsb \n" +" sti \n" +: "=a" (dummy1), "=d" (dummy2), "=S" (dummy3), "=c" (dummy4) +: "c" (cant*3), "S" (_pal_ptr), "a" (color), "d" (0x3C8) +); +} + +void RPF_GetPalRange(unsigned char *_pal_ptr, int color, int cant) +{ + int dummy1,dummy2,dummy3,dummy4; + asm volatile ( +" outb %%al,%%dx \n" +" addl $2,%%edx \n" +" cli \n" +" rep \n" +" insb \n" +" sti \n" +: "=a" (dummy1), "=d" (dummy2), "=D" (dummy3), "=c" (dummy4) +: "c" (cant*3), "D" (_pal_ptr), "a" (color), "d" (0x3C7) +); +} +#endif // DJGPP + diff --git a/tvision/classes/dos/vgaregs.h b/tvision/classes/dos/vgaregs.h new file mode 100644 index 0000000..7cf9f15 --- /dev/null +++ b/tvision/classes/dos/vgaregs.h @@ -0,0 +1,320 @@ +/* Copyright 1998-2002 (c) by Salvador Eduardo Tropea + This code is part of the port of Turbo Vision to gcc, please see the rest + of the file for copying information. + */ + +#if defined(TVCompf_djgpp) && !defined(VGAREGS_HEADER_INCLUDED) +#define VGAREGS_HEADER_INCLUDED + +#include + +/* CRT (Cathode Rays Tube) Controller Registers + They control the sync signals. + 0x00 to 0x18 */ +// SVGALib and XFree86 uses <0x18 so they miss the line compare register, +// don't know why. +#define CRTbase 0 +#define CRTcant 25 +/* ATT Attribute Controller Registers + They control some attributes like 16 colors palette, overscan color, etc. + 0x00 to 0x14 */ +#define ATTbase (CRTbase+CRTcant) +#define ATTcant 21 +/* GRA Graphics Controller Registers + They control the read/write mode to the video memory. + 0x00 to 0x08 */ +#define GRAbase (ATTbase+ATTcant) +#define GRAcant 9 +/* SEQ Sequence Registers + They control how the memory is scanned. + 0x00 to 0x04 */ +#define SEQbase (GRAbase+GRAcant) +#define SEQcant 5 +/* MOR Miscellaneous Output Register + 1 register */ +#define MORbase (SEQbase+SEQcant) +#define MORcant 1 + +#define VGARegsCant (MORbase+MORcant) + +/* (I don't take care about mono by now) */ +/* VGA Atttibute controller */ +#define ATTindex 0x3C0 +#define ATTdataW 0x3C0 +#define ATTdataR 0x3C1 +#define ATTdir 0x3DA +/* Miscellaneous Output Register */ +#define MORdataW 0x3C2 +#define MORdataR 0x3CC +/* VGA Sequencer Registers */ +#define Sequencer 0x3C4 +#define SequencerIndex 0x3C4 +#define SequencerData 0x3C5 +/* VGA Palette Registers */ +#define ReadDataAddress 0x3C7 +#define WriteDataAddress 0x3C8 +#define PaletteDataRegister 0x3C9 +/* VGA Graphics Controller Registers */ +#define GraphicsController 0x3CE +#define GraphicsControllerIndex 0x3CE +#define GraphicsControllerData 0x3CF +/* VGA CRT Controller Register */ +#define CRTController 0x3D4 +#define CRTControllerIndex 0x3D4 +#define CRTControllerData 0x3D5 +/* VGA Input Status Register 1 */ +#define InputStatusRegister1 0x3DA +/* Trident's DAC/Clock */ +#define EDACindex 0x83C8 +#define EDACdata 0x83C6 + +#if __GNUC__<3 + // GCC 3.0 doesn't support it for local variables. + // But takes the right way. + #define RegEAX asm("%eax") +#else + #define RegEAX +#endif + +#ifndef NO_INLINE +//#define SAFE_IO + +#ifdef SAFE_IO +/* C approach, safier than my assembler ;-) */ + +extern inline +uchar ReadCRT(uchar index) +{ + outportb(CRTControllerIndex,index); + return inportb(CRTControllerData); +} + +extern inline +uchar ReadGRA(uchar index) +{ + outportb(GraphicsControllerIndex,index); + return inportb(GraphicsControllerData); +} + +extern inline +uchar ReadSEQ(uchar index) +{ + outportb(SequencerIndex,index); + return inportb(SequencerData); +} + +extern inline +void WriteCRT(uchar index, uchar value) +{ + outportb(CRTControllerIndex,index); + outportb(CRTControllerData,value); +} + + +extern inline +void WriteGRA(uchar index, uchar value) +{ + outportb(GraphicsControllerIndex,index); + outportb(GraphicsControllerData,value); +} + +extern inline +void WriteSEQ(uchar index, uchar value) +{ + outportb(SequencerIndex,index); + outportb(SequencerData,value); +} + +extern inline +void WaitVRT() +{ + while (inportb(InputStatusRegister1) & 8); + while (!(inportb(InputStatusRegister1) & 8)); +} + +#else +/* + Assembler stuff: It is normally more compact and in some cases faster. As + the functions are inline I think size is important. + They save 524 bytes in the driver (1.89%). +*/ + +extern inline +uchar ReadCRT(uchar index) +{ + int dummy; + uchar a RegEAX; + a=index; + asm volatile ( +" outb %%al,%%dx \n" +" incl %%edx \n" +" inb %%dx,%%al \n" + : "=a" (a), "=d" (dummy) : "a" (a), "d" (CRTController)); + return a; +} + + +extern inline +uchar ReadGRA(uchar index) +{ + int dummy; + uchar a RegEAX; + a=index; + asm volatile ( +" outb %%al,%%dx \n" +" incl %%edx \n" +" inb %%dx,%%al \n" + : "=a" (a), "=d" (dummy) : "a" (a), "d" (GraphicsController)); + return a; +} + +extern inline +uchar ReadSEQ(uchar index) +{ + int dummy; + uchar a RegEAX; + a=index; + asm volatile ( +" outb %%al,%%dx \n" +" incl %%edx \n" +" inb %%dx,%%al \n" + : "=a" (a), "=d" (dummy) : "a" (a), "d" (Sequencer)); + return a; +} + +extern inline +void WriteCRT(uchar index, uchar value) +{ + int dummy; + asm volatile ( +" movb %1,%%ah \n" +" outw %%ax,%%dx \n" + : "=a" (dummy) : "qi" (value), "a" (index), "d" (CRTController)); +} + +extern inline +void WriteGRA(uchar index, uchar value) +{ + int dummy; + asm volatile ( +" movb %1,%%ah \n" +" outw %%ax,%%dx \n" + : "=a" (dummy) : "qi" (value), "a" (index), "d" (GraphicsController)); +} + +extern inline +void WriteSEQ(uchar index, uchar value) +{ + int dummy; + asm volatile ( +" movb %1,%%ah \n" +" outw %%ax,%%dx \n" + : "=a" (dummy) : "qi" (value), "a" (index), "d" (Sequencer)); +} + + +extern inline +void WaitVRT() +{ + asm volatile( +" 1: \n" +" inb %%dx,%%al \n" +" testb $8,%%al \n" +" jne 1b \n" +" .align 2,0x90 \n" +" 2: \n" +" inb %%dx,%%al \n" +" testb $8,%%al \n" +" je 2b \n" + : : "d" (InputStatusRegister1) : "%eax" ); +} + +#endif + +extern inline +uchar ReadATT(int index) +{ + /* Ensure we will write to the index */ + inportb(ATTdir); + /* Set the index and disable the screen or we will read nothing */ + outportb(ATTindex,index); + return inportb(ATTdataR); +} + +extern inline +void ATTEndReads(void) +{ + /* Ensure we will write to the index */ + inportb(ATTdir); + /* Enable the screen */ + outportb(ATTindex,0x20); +} + +extern inline +void WriteATT(int index, int val) +{ + outportb(ATTindex,index); + outportb(ATTdataW,val); +} + +extern inline +uchar ReadMOR(void) +{ + return inportb(MORdataR); +} + +extern inline +void WriteMOR(int val) +{ + outportb(MORdataW,val); +} + +extern inline +uchar ReadEDAC(int index) +{ + outportb(EDACindex,index); + return inportb(EDACdata); +} + +extern inline +void WriteEDAC(int index, int val) +{ + outportb(EDACindex,index); + outportb(EDACdata,val); +} + +extern inline +void RPF_SetPalRange(unsigned char *_pal_ptr, int color, int cant) +{ + int dummy1,dummy2,dummy3,dummy4; + asm volatile ( +" outb %%al,%%dx \n" +" incl %%edx \n" +" cli \n" +" rep \n" +" outsb \n" +" sti \n" +: "=a" (dummy1), "=d" (dummy2), "=S" (dummy3), "=c" (dummy4) +: "c" (cant*3), "S" (_pal_ptr), "a" (color), "d" (0x3C8) +); +} + +extern inline +void RPF_GetPalRange(unsigned char *_pal_ptr, int color, int cant) +{ + int dummy1,dummy2,dummy3,dummy4; + asm volatile ( +" outb %%al,%%dx \n" +" addl $2,%%edx \n" +" cli \n" +" rep \n" +" insb \n" +" sti \n" +: "=a" (dummy1), "=d" (dummy2), "=D" (dummy3), "=c" (dummy4) +: "c" (cant*3), "D" (_pal_ptr), "a" (color), "d" (0x3C7) +); +} +#endif // NO_INLINE + +#endif // defined(TVCompf_djgpp) && !defined(VGAREGS_HEADER_INCLUDED) + diff --git a/tvision/classes/dos/vgastate.c b/tvision/classes/dos/vgastate.c new file mode 100644 index 0000000..578ab18 --- /dev/null +++ b/tvision/classes/dos/vgastate.c @@ -0,0 +1,207 @@ +/* Copyright 1998-1999 (c) by Salvador Eduardo Tropea + This code is part of the port of Turbo Vision to gcc, please see the rest + of the file for copying information. + */ +/***************************************************************************** + + ROUTINES to store/retrieve the VGA registers. + +*****************************************************************************/ +#include + +typedef unsigned char uchar; +typedef unsigned short ushort; +#include "vgaregs.h" + +#ifdef TVCompf_djgpp + +#include + +/**[txh]******************************************************************** + + Description: + This function stores ALL the VGA registers in an array. + +***************************************************************************/ + +static +int VGASaveRegs(uchar *regs) +{ + int i; + uchar MORval; + + /* I'm trying to do this routine as strong and generic as possible + without loosing performance. + So I ever put the VGA chip in the color mode (ports=0x3Dx) but I + store the real state */ + MORval=ReadMOR(); + WriteMOR(MORval | 1); + regs[MORbase]=MORval; + + for (i=0; i success + +***************************************************************************/ + +int VGAStateSave(void *buffer) +{ + uchar *s=(uchar *)buffer; + if (!s) return 0; + VGASaveRegs(s); + VGASavePal(s+VGARegsCant); + SaveBIOSDTA(s+VGARegsCant+VGAPalSize); + VGALoadRegs(s); + return 1; +} + +/**[txh]******************************************************************** + + Description: + Restores the current video mode information from the provided buffer. + + Return: + !=0 => success + +***************************************************************************/ + +int VGAStateLoad(void *buffer) +{ + uchar *s=(uchar *)buffer; + if (!s) return 0; + LoadBIOSDTA(s+VGARegsCant+VGAPalSize); + VGALoadPal(s+VGARegsCant); + VGALoadRegs(s); + return 1; +} + +#endif // DJGPP diff --git a/tvision/classes/dos/vgastate.h b/tvision/classes/dos/vgastate.h new file mode 100644 index 0000000..cd22c3a --- /dev/null +++ b/tvision/classes/dos/vgastate.h @@ -0,0 +1,19 @@ +/* Copyright 1998-2002 (c) by Salvador Eduardo Tropea + This code is part of the port of Turbo Vision to gcc, please see the rest + of the file for copying information. + */ + +#if defined(TVCompf_djgpp) && !defined(VGASTATE_HEADER_INCLUDED) +#define VGASTATE_HEADER_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif +int VGAStateGetBufferSize(void); +int VGAStateSave(void *buffer); +int VGAStateLoad(void *buffer); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tvision/classes/fontcoll.cc b/tvision/classes/fontcoll.cc new file mode 100644 index 0000000..5eae2b3 --- /dev/null +++ b/tvision/classes/fontcoll.cc @@ -0,0 +1,574 @@ +/**[txh]******************************************************************** + + Copyright 1996-2002 by Salvador Eduardo Tropea (SET) + This file is covered by the GPL license. + + Module: TVFontCollection + Comments: + This module handles collections of 8xN bitmaped fonts useful for text +consoles. The collection is created from a fonts files. Each item is a font +of certain height. The collection can return interpolated and extrapolated +fonts in a range of +/- one from the available fonts. The fonts file should +contain fonts with all the supported symbols.@p + +@
+  SFT Files: This is currently platform dependent! It means SFT files should
+  be generated in the same platform they are used. It will be fixed in the
+  future.
+
+  17 bytes: SET's editor font
+   1 byte:  26 (DOS EOF)
+      int:  version (1 or 2)
+      int:  number of fonts contained.
+   2 bytes: size of name
+            the name, the length includes the EOS, but this isn't stored on
+            disk.
+
+  Here are the fonts, each one have this format:
+  version 1:
+  int: first symbol defined.
+  int: last symbol defined.
+  unsigned: height of the font.
+  The width is assumed to be 8 pixels (1 byte)
+
+  version 2, the same but adds:
+  unsigned: width of the font.
+
+  The fonts itself follows the internal code.
+@
+ +***************************************************************************/ + +#define Uses_stdlib +#define Uses_string +#define Uses_dirent +#define Uses_limits +#define Uses_TVCodePage +#define Uses_TVFontCollection +#include + +//#define TEST + +const int SizeInDisk1=3*sizeof(int); +const int SizeInDisk2=SizeInDisk1+sizeof(int); +const char TVFontCollection::Signature[]="SET's editor font\x1A"; +const char TVFontCollection::SFTExtension[]=".sft"; +int TVFontCollection::invertEndian=0; + +struct SizeFont +{ + unsigned width,height; +}; + +static +int isWordChar(int i) +{ + return i=='_' || TVCodePage::isAlpha(i); +} + +/**[txh]******************************************************************** + + Description: + A specialized free to free the memory used by the font structure. + +***************************************************************************/ + +void TVFontCollection::freeItem(void *item) +{ + TVBitmapFont *p=(TVBitmapFont *)item; + if (p) + { + DeleteArray(p->font); + DeleteArray(p->fontFull); + delete p; + } +} + +/**[txh]******************************************************************** + + Description: + Internally used during searchs to look for a font that matchs a specified +size. + +***************************************************************************/ + +Boolean TVFontCollection::CheckForLines(void *item, void *arg) +{ + TVBitmapFont *p=(TVBitmapFont *)item; + SizeFont *s=(SizeFont *)arg; + if (p && p->lines==s->height && p->width==s->width) + return True; + return False; +} + +/**[txh]******************************************************************** + + Description: + Creates a font of the specified height from another of the same height +plus one. The destination buffer should be large enough (num*height bytes). +Special care is taked for letters. + +***************************************************************************/ + +void TVFontCollection::ReduceOne(uchar *dest, uchar *ori, int height, + int wBytes, int num) +{ + int i; + unsigned sizeDest=wBytes*height; + unsigned sizeOri=sizeDest+wBytes; + // height is the dest size, ori is one more + + for (i=0; ifont) + return NULL; + + unsigned size=256*height*p->wBytes; + uchar *fontShape=new uchar[size]; + if (oneMore) + ReduceOne(fontShape,p->font,height,p->wBytes); + else if (oneLess) + EnlargeOne(fontShape,p->font,height,p->wBytes); + else + memcpy(fontShape,p->font,size); + + return fontShape; +} + +/**[txh]******************************************************************** + + Description: + Internally used to check if we opened a fonts file. + +***************************************************************************/ + +int TVFontCollection::CheckSignature(FILE *f) +{ + char buf[sizeof(Signature)]; + fread(buf,sizeof(Signature)-1,1,f); + buf[sizeof(Signature)-1]=0; + return strcmp(Signature,buf)==0; +} + +/**[txh]******************************************************************** + + Description: + Internally used to get the font's name. + +***************************************************************************/ + +char *TVFontCollection::ReadName(FILE *f) +{ + uint16 strLen; + fread(&strLen,2,1,f); + Swap(&strLen); + char *aux=new char[strLen]; + strLen--; + fread(aux,strLen,1,f); + aux[strLen]=0; + return aux; +} + +#define SwapMacro(a,b) t=v[a]; v[a]=v[b]; v[b]=t +void TVFontCollection::Swap(int *value) +{ + if (!invertEndian) return; + char *v=(char *)value, t; + SwapMacro(0,3); + SwapMacro(1,2); +} + +void TVFontCollection::Swap(uint16 *value) +{ + if (!invertEndian) return; + char *v=(char *)value, t; + SwapMacro(0,1); +} + +/**[txh]******************************************************************** + + Description: + Internally used to read the version and number of fonts in the file. + +***************************************************************************/ + +void TVFontCollection::ReadVersionNum(FILE *f, int *version, int *numfonts) +{ + fread(version,4,1,f); + fread(numfonts,4,1,f); + invertEndian=*version>0x1000; + Swap(version); + Swap(numfonts); +} + + +/**[txh]******************************************************************** + + Description: + Internally used to read the information about a font contained in an SFT +file. + + Return: Size of the data font. + +***************************************************************************/ + +unsigned TVFontCollection::ReadFontInfo(FILE *f, int version, TVBitmapFont *p) +{ + if (version==1) + { + fread(p,SizeInDisk1,1,f); + p->width=8; + p->wBytes=1; + } + else + { + fread(p,SizeInDisk2,1,f); + Swap(&p->width); + p->wBytes=(p->width+7)/8; + } + Swap(&p->first); + Swap(&p->last); + Swap(&p->lines); + return (p->last-p->first+1)*p->lines*p->wBytes; +} + +/**[txh]******************************************************************** + + Description: + Internally used to create a font for a desired code page. + +***************************************************************************/ + +void TVFontCollection::CreateFont(void *item, void *arg) +{ + TVBitmapFont *f=(TVBitmapFont *)item; + ushort *map=(ushort *)arg; + DeleteArray(f->font); + unsigned size1=f->lines*f->wBytes; + unsigned size=256*size1; + f->font=new uchar[size]; + int i; + uchar *dest=f->font; + memset(f->font,0,size); + for (i=0; i<256; i++,dest+=size1) + { + int index=map[i]; + if (index>f->last) + { + index=TVCodePage::LookSimilarInRange(index,f->last); + if (index==-1) + index=f->first; + } + index-=f->first; + memcpy(dest,&f->fontFull[index*size1],size1); + } + + #if 0 + // This code stores the generated font to disk, is used for debug + // purposes + FILE *F; + char b[PATH_MAX],*t; + t=getenv("TMP"); + if (!t) t="/tmp"; + sprintf(b,"%s/font.%03d",t,f->lines); + F=fopen(b,"wb"); + fwrite(f->font,size,1,F); + fclose(F); + #endif +} + +/**[txh]******************************************************************** + + Description: + Sets the encoding of the fonts returned by GetFont. + +***************************************************************************/ + +void TVFontCollection::SetCodePage(int id) +{ + ushort *map=TVCodePage::GetTranslate(id); + if (map) + forEach(CreateFont,map); +} + +TVFontCollection::~TVFontCollection() +{ + DeleteArray(fontName); + DeleteArray(fileName); +} + +/**[txh]******************************************************************** + + Description: + Creates a font collection from the specified file and using the specified +code page. You must check the error status with GetError before using the +collection. + +***************************************************************************/ + +TVFontCollection::TVFontCollection(const char *file, int cp) : + TNSCollection(2,2) +{ + error=0; + fontName=fileName=NULL; + if (!file) + { + error=1; + return; + } + + FILE *f=fopen(file,"rb"); + if (!f) + { + error=2; + return; + } + + if (!CheckSignature(f)) + { + fclose(f); + error=3; + return; + } + + int version; + int numfonts; + ReadVersionNum(f,&version,&numfonts); + + int i; + TVBitmapFont *p; + uchar *fData; + unsigned size; + + fontName=ReadName(f); + fileName=newStr(file); + + for (i=0; ifontFull=fData; + p->font=0; + insert(p); + } + fclose(f); + SetCodePage(cp); +} + +/**[txh]******************************************************************** + + Description: + Constructs a string collection of fonts files that provides shapes inside +the specified range. The fonts are searched in the specified directory. If +you specify NULL as directory then the search is done in the current +directory. Each element in the collection is a string that contains two +ASCIIZ strings. The first is the fantasy name of the font and the second is +the name of the file containing it. It is useful to display the name in +a TSortedListBox and easilly locate which file contains it using strlen.@* + This is an static member. + + Return: The collection of available fonts or NULL if none. + +***************************************************************************/ + +TVBitmapFontDescCol *TVFontCollection::CreateListOfFonts(const char *dir, + unsigned wmin, unsigned wmax, unsigned hmin, unsigned hmax) +{ + char *FullName=new char[PATH_MAX]; + TVBitmapFontDescCol *col=new TVBitmapFontDescCol(); + + if (!dir) + dir="."; + DIR *d=opendir(dir); + struct dirent *de; + int version; + int numfonts; + unsigned size; + TVBitmapFont stF; + TVBitmapFontSize sizeSt; + if (d) + { + while ((de=readdir(d))!=0) + { + if (strstr(de->d_name,SFTExtension)) + { + strcpy(FullName,dir); + strcat(FullName,"/"); + strcat(FullName,de->d_name); + FILE *f=fopen(FullName,"rb"); + if (f) + { + if (CheckSignature(f)) + { + ReadVersionNum(f,&version,&numfonts); + char *name=ReadName(f); + TVBitmapFontDesc *d=NULL; + int i,j,added; + ccIndex pos; + for (i=0; i=wmin && stF.width<=wmax && + (stF.lines+j)>=hmin && (stF.lines+j)<=hmax) + { + if (!d) + { + d=new TVBitmapFontDesc; + d->name=name; + d->file=newStr(FullName); + d->sizes=new TVBitmapFontSizeCol(); + } + sizeSt.w=stF.width; sizeSt.h=stF.lines+j; + if (!d->sizes->search(&sizeSt,pos)) + { + TVBitmapFontSize *p=new TVBitmapFontSize; + p->w=stF.width; + p->h=stF.lines+j; + d->sizes->insert(p); + } + } + } + fseek(f,size,SEEK_CUR); + } + if (d) + col->insert(d); + else + DeleteArray(name); + } + fclose(f); + } + } + } + closedir(d); + } + delete[] FullName; + if (col->getCount()==0) + { + CLY_destroy(col); + return NULL; + } + return col; +} + +void TVBitmapFontDescCol::freeItem(void *item) +{ + TVBitmapFontDesc *p=(TVBitmapFontDesc *)item; + DeleteArray((char *)p->name); + DeleteArray((char *)p->file); + CLY_destroy(p->sizes); + delete p; +} + +void *TVBitmapFontDescCol::keyOf(void *item) +{ + TVBitmapFontDesc *p=(TVBitmapFontDesc *)item; + return (void *)p->name; +} + +void TVBitmapFontDescLBox::getText(char *dest, ccIndex item, short maxChars) +{ + TVBitmapFontDesc *p=(TVBitmapFontDesc *)items->at(item); + strncpy(dest,p->name,maxChars); + dest[maxChars]=0; +} + +int TVBitmapFontSizeCol::compare(void *key1, void *key2) +{ + TVBitmapFontSize *v1=(TVBitmapFontSize *)key1; + TVBitmapFontSize *v2=(TVBitmapFontSize *)key2; + if (v1->w>v2->w) return 1; + if (v1->ww) return -1; + return (v1->h>v2->h)-(v1->hh); +} + +void TVBitmapFontSizeLBox::getText(char *dest, ccIndex item, short maxChars) +{ + TVBitmapFontSize *p=(TVBitmapFontSize *)items->at(item); + // Limit the value to know we won't exceed the buffer + unsigned w=p->w; if (w>999) w=999; + unsigned h=p->h; if (h>999) h=999; + char b[12]; + sprintf(b,"%3d x %-3d",w,h); + strncpy(dest,b,maxChars); + dest[maxChars]=0; +} + diff --git a/tvision/classes/fpbase.cc b/tvision/classes/fpbase.cc new file mode 100644 index 0000000..5f86546 --- /dev/null +++ b/tvision/classes/fpbase.cc @@ -0,0 +1,143 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified to compile with gcc v3.x by Salvador E. Tropea, with the help of +Andris Pavenis and Christoph Bauer. + + * + * + */ + +#define Uses_pstream +#define Uses_fpbase +#define Uses_PubStreamBuf +#include + +UsingNamespaceStd + +fpbase::fpbase() +{ + buf=new CLY_int_filebuf(); + pstream::init(buf); +} + +fpbase::fpbase(int f) +{ + CLY_NewFBFromFD(buf,f); + pstream::init(buf); +} + +fpbase::fpbase( const char *name, CLY_OpenModeT omode, int prot ) +{ + buf=new CLY_int_filebuf(); + open(name,omode,prot); + pstream::init(buf); +} + +fpbase::fpbase( int f, char *b, int len ) +{ + CLY_NewFBFromFD(buf,f); + buf->CLY_PubSetBuf(b,len); + pstream::init(buf); +} + +void fpbase::setbuf(char* b, int len) +{ + if (buf->CLY_PubSetBuf(b,len)) + clear(CLY_IOSGoodBit); + else + setstate(CLY_IOSFailBit); +} + +#ifdef CLY_HaveFBAttach +void fpbase::attach(int f) +{ + if (buf->is_open()) + setstate(CLY_IOSFailBit); + else if(buf->attach(f)) + clear(CLY_IOSGoodBit); + else + clear(CLY_IOSBadBit); +} +#endif + +fpbase::~fpbase() +{ + delete buf; +} + +void fpbase::open( const char *b, CLY_OpenModeT m, int prot ) +{ + if (buf->is_open()) + clear(CLY_IOSFailBit); // fail - already open + else if (buf->CLY_FBOpen(b,m,prot)) + clear(CLY_IOSGoodBit); // successful open + else + clear(CLY_IOSBadBit); // open failed +} + +void fpbase::close() +{ + if (buf->close()) + clear(CLY_IOSGoodBit); + else + setstate(CLY_IOSFailBit); +} + +CLY_filebuf *fpbase::rdbuf() +{ + return buf; +} + +#ifdef CLY_DefineSpecialFileBuf +// gcc 3.1 specific +CLY_int_filebuf *CLY_int_filebuf::open(FILE *f, ios_base::openmode mode) +{ + CLY_int_filebuf *ret=NULL; + if (!this->is_open()) + { + _M_file.sys_open(f,mode); + if (this->is_open()) + { + _M_allocate_internal_buffer(); + _M_mode=mode; + + // For time being, set both (in/out) sets of pointers. + _M_set_indeterminate(); + if ((mode & ios_base::ate) && + this->seekoff(0,ios_base::end,mode)<0) + this->close(); + ret=this; + } + } + return ret; +} + +CLY_int_filebuf *CLY_int_filebuf::open(int h, ios_base::openmode mode) +{ + CLY_int_filebuf *ret=NULL; + if (!this->is_open()) + { + _M_file.sys_open(h,mode,false); + if (this->is_open()) + { + _M_allocate_internal_buffer(); + _M_mode=mode; + + // For time being, set both (in/out) sets of pointers. + _M_set_indeterminate(); + if ((mode & ios_base::ate) && + this->seekoff(0,ios_base::end,mode)<0) + this->close(); + ret=this; + } + } + return ret; +} +#endif // CLY_DefineSpecialFileBuf + diff --git a/tvision/classes/fpstream.cc b/tvision/classes/fpstream.cc new file mode 100644 index 0000000..6cda360 --- /dev/null +++ b/tvision/classes/fpstream.cc @@ -0,0 +1,83 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Vadim Beloborodov to be used on WIN32 console +Modified to compile with gcc v3.x by Salvador E. Tropea, with the help of +Andris Pavenis and Christoph Bauer. +Added filelength member by Salvador E. Tropea (SET) +Added fpstream( CLY_OpenModeT omode, const char* name, int prot ) to avoid +the CLY_IOSOut | CLY_IOSBin addition. + + * + * + */ + +#define Uses_fpbase +#define Uses_fpstream +#define Uses_IOS_BIN +#define Uses_filelength +#include + +UsingNamespaceStd + +fpstream::fpstream() +{ +} + +fpstream::fpstream( const char* name, CLY_OpenModeT omode, int prot ) : + fpbase( name, omode | CLY_IOSOut | CLY_IOSBin, prot ) +{ +} + +fpstream::fpstream( CLY_OpenModeT omode, const char* name, int prot ) : + fpbase( name, omode, prot ) +{ +} + +fpstream::fpstream( int f ) : fpbase( f ) +{ +} + +fpstream::fpstream(int f, char* b, int len) : fpbase(f, b, len) +{ +} + +fpstream::~fpstream() +{ +} + +CLY_filebuf *fpstream::rdbuf() +{ + return fpbase::rdbuf(); +} + +void fpstream::open( const char *name, CLY_OpenModeT omode, int prot ) +{ + fpbase::open( name, omode | CLY_IOSIn | CLY_IOSOut | CLY_IOSBin, prot ); +} + + +// SET: I added this member because a lot of applications tries to get +// the file descriptor just to find the filelength. This mechanism doesn't +// work with the ISO C++ 1998 standard so here I hide the difference using +// it. +#ifdef CLY_ISOCpp98 +long fpstream::filelength() +{ + long basePos=tellp(); + long ret=seekg(0, CLY_IOSEnd).tellg(); + seekg(basePos, CLY_IOSBeg); + return ret; +} +#else +long fpstream::filelength() +{ + return ::filelength(rdbuf()->fd()); +} +#endif + diff --git a/tvision/classes/help.cc b/tvision/classes/help.cc new file mode 100644 index 0000000..568b806 --- /dev/null +++ b/tvision/classes/help.cc @@ -0,0 +1,262 @@ +/* + * help.cc + * + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + * Modified by Sergio Sigala + * Modified by Salvador E. Tropea , + */ + +// SET: moved the standard headers before tv.h +#define Uses_limits +#define Uses_ctype +#define Uses_string +#define Uses_sys_stat + +#define Uses_TDrawBuffer +#define Uses_TKeys +#define Uses_TPalette +#define Uses_THelpWindow +#include + +// THelpViewer + +THelpViewer::THelpViewer( const TRect& bounds, TScrollBar* aHScrollBar, + TScrollBar* aVScrollBar, THelpFile *aHelpFile, ushort context ) + : TScroller( bounds, aHScrollBar, aVScrollBar ) +{ + options = (options | ofSelectable); + growMode = gfGrowHiX | gfGrowHiY; + hFile = aHelpFile; + topic = aHelpFile->getTopic(context); + topic->setWidth(size.x); + setLimit(78, topic->numLines()); + selected = 1; +} + +THelpViewer::~THelpViewer() +{ + delete hFile; + delete topic; +} + +void THelpViewer::changeBounds( const TRect& bounds ) +{ + TScroller::changeBounds(bounds); + topic->setWidth(size.x); + setLimit(limit.x, topic->numLines()); +} + +void THelpViewer::draw() +{ + TDrawBuffer b; + char line[256]; + char buffer[256]; + char *bufPtr; + int i, j, l; + int keyCount; + ushort normal, keyword, selKeyword, c; + TPoint keyPoint; + uchar keyLength; + int keyRef; + + normal = getColor(1); + keyword = getColor(2); + selKeyword = getColor(3); + keyCount = 0; + keyPoint.x = 0; + keyPoint.y = 0; + topic->setWidth(size.x); + if (topic->getNumCrossRefs() > 0) + { + do + { + topic->getCrossRef(keyCount, keyPoint, keyLength, keyRef); + ++keyCount; + } while ( (keyCount < topic->getNumCrossRefs()) && + (keyPoint.y <= delta.y)); + } + for (i = 1; i <= size.y; ++i) + { + b.moveChar(0, ' ', normal, size.x); + strcpy(line, topic->getLine(i + delta.y, buffer, sizeof( buffer ))); +// if (strlen(line) > delta.x) /* XXX */ + if ((int)strlen(line) > delta.x) /* XXX */ + { + bufPtr = line + delta.x; + strncpy(buffer, bufPtr, size.x); + buffer[size.x] = 0; + b.moveStr(0, buffer, normal); + } + else + b.moveStr(0, "", normal); + while (i + delta.y == keyPoint.y) + { + l = keyLength; + if (keyPoint.x < delta.x ) + { + l -= (delta.x - keyPoint.x); + keyPoint.x = delta.x; + } + if (keyCount == selected) + c = selKeyword; + else + c = keyword; + for(j = 0; j < l; ++j) + b.putAttribute((keyPoint.x - delta.x + j),c); + if (keyCount < topic->getNumCrossRefs()) + { + topic->getCrossRef(keyCount, keyPoint, keyLength, keyRef); + keyCount++; + } + else + keyPoint.y = 0; + } + writeLine(0, i-1, size.x, 1, b); + } +} + +TPalette& THelpViewer::getPalette() const +{ + static TPalette palette( cHelpViewer, sizeof( cHelpViewer)-1 ); + return palette; +} + +void THelpViewer::makeSelectVisible( int selected, TPoint& keyPoint, + uchar& keyLength, int& keyRef ) +{ + TPoint d; + + topic->getCrossRef(selected, keyPoint, keyLength, keyRef); + d = delta; + if (keyPoint.x < d.x) + d.x = keyPoint.x; + if (keyPoint.x > d.x + size.x) + d.x = keyPoint.x - size.x; + if (keyPoint.y <= d.y) + d.y = keyPoint.y-1; + if (keyPoint.y > d.y + size.y) + d.y = keyPoint.y - size.y; + if ((d.x != delta.x) || (d.y != delta.y)) + scrollTo(d.x, d.y); +} + +void THelpViewer::switchToTopic( int keyRef ) +{ + if (topic != 0) + delete topic; + topic = hFile->getTopic(keyRef); + topic->setWidth(size.x); + scrollTo(0, 0); + setLimit(limit.x, topic->numLines()); + selected = 1; + drawView(); +} + +void THelpViewer::handleEvent( TEvent& event ) +{ + + TPoint keyPoint, mouse; + uchar keyLength; + int keyRef; + int keyCount; + + + TScroller::handleEvent(event); + switch (event.what) + { + + case evKeyDown: + switch (event.keyDown.keyCode) + { + case kbTab: + ++selected; + if (selected > topic->getNumCrossRefs()) + selected = 1; + if ( topic->getNumCrossRefs() != 0 ) + makeSelectVisible(selected-1,keyPoint,keyLength,keyRef); + break; + case kbShiftTab: + --selected; + if (selected == 0) + selected = topic->getNumCrossRefs(); + if ( topic->getNumCrossRefs() != 0 ) + makeSelectVisible(selected-1,keyPoint,keyLength,keyRef); + break; + case kbEnter: + if (selected <= topic->getNumCrossRefs()) + { + topic->getCrossRef(selected-1, keyPoint, keyLength, keyRef); + switchToTopic(keyRef); + } + break; + case kbEsc: + event.what = evCommand; + event.message.command = cmClose; + putEvent(event); + break; + default: + return; + } + drawView(); + clearEvent(event); + break; + + case evMouseDown: + mouse = makeLocal(event.mouse.where); + mouse.x += delta.x; + mouse.y += delta.y; + keyCount = 0; + + do + { + ++keyCount; + if (keyCount > topic->getNumCrossRefs()) + return; + topic->getCrossRef(keyCount-1, keyPoint, keyLength, keyRef); + } while (!((keyPoint.y == mouse.y+1) && (mouse.x >= keyPoint.x) && + (mouse.x < keyPoint.x + keyLength))); + selected = keyCount; + drawView(); + if (event.mouse.doubleClick) + switchToTopic(keyRef); + clearEvent(event); + break; + + case evCommand: + if ((event.message.command == cmClose) && ((owner->state & sfModal) != 0)) + { + endModal(cmClose); + clearEvent(event); + } + break; + } +} + +// THelpWindow + +THelpWindow::THelpWindow( THelpFile *hFile, ushort context ): + TWindowInit( &THelpWindow::initFrame), + TWindow( TRect(0,0,50,18), helpWinTitle, wnNoNumber ) +{ + TRect r(0, 0, 50, 18); + options = (options | ofCentered); + r.grow(-2,-1); + insert(new THelpViewer (r, + standardScrollBar(sbHorizontal | sbHandleKeyboard), + standardScrollBar(sbVertical | sbHandleKeyboard), hFile, context)); +} + +TPalette& THelpWindow::getPalette() const +{ + static TPalette palette( cHelpWindow, sizeof(cHelpWindow)-1 ); + return palette; +} + +const char * THelpWindow::helpWinTitle = "Help"; +const char * THelpFile::invalidContext = + "\n No help available in this context."; + diff --git a/tvision/classes/helpbase.cc b/tvision/classes/helpbase.cc new file mode 100644 index 0000000..6f315e4 --- /dev/null +++ b/tvision/classes/helpbase.cc @@ -0,0 +1,651 @@ +/* + * helpbase.cc + * + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + * Modified by Sergio Sigala + * Modified by Salvador E. Tropea , + */ + +// SET: moved the standard headers before tv.h. Adapted to compat layer. +#define Uses_ctype +#define Uses_limits +#define Uses_string +#define Uses_sys_stat +#define Uses_filelength + +#define Uses_TStreamableClass +#define Uses_THelpFile +#include + +TCrossRefHandler crossRefHandler = notAssigned; + +// THelpTopic + +const char * const THelpTopic::name = "THelpTopic"; + +void THelpTopic::write( opstream& os ) +{ + writeParagraphs( os ); + writeCrossRefs( os ); + +} + +void *THelpTopic::read( ipstream& is ) +{ + readParagraphs( is ); + readCrossRefs( is ); + width = 0; + lastLine = INT_MAX; + return this; +} + +TStreamable *THelpTopic::build() +{ + return new THelpTopic( streamableInit ); +} + + +TStreamableClass RHelpTopic( THelpTopic::name, + THelpTopic::build, + __DELTA(THelpTopic) + ); + +THelpTopic::THelpTopic() : TObject() +{ + paragraphs = 0; + numRefs = 0; + crossRefs = 0; + width = 0; + lastOffset = 0; + lastLine = INT_MAX; + lastParagraph = 0; +}; + +void THelpTopic::readParagraphs( ipstream& s ) +{ + int i; + ushort size; + TParagraph **pp; + int temp; + + s >> i; + pp = ¶graphs; + while ( i > 0) + { + s >> size; + *pp = new TParagraph; + (*pp)->text = new char[size]; + (*pp)->size = (ushort) size; + s >> temp; + (*pp)->wrap = Boolean(temp); + s.readBytes((*pp)->text, (*pp)->size); + pp = &((*pp)->next); + --i; + } + *pp = 0; +} + +void THelpTopic::readCrossRefs( ipstream& s ) +{ + int i; + TCrossRef *crossRefPtr; + + s >> numRefs; + crossRefs = new TCrossRef[numRefs]; + for (i = 0; i < numRefs; ++i) + { + crossRefPtr = (TCrossRef *)crossRefs + i; + + /* + * SS: TCrossRef size is 9 bytes (int, int, char), but + * sizeof(TCrossRef) is rounded to 12. + */ + s >> crossRefPtr->ref; /* int */ + s >> crossRefPtr->offset; /* int */ + s >> crossRefPtr->length; /* char */ +// s.readBytes(crossRefPtr, sizeof(TCrossRef)); + } +} + +void THelpTopic::disposeParagraphs() +{ + TParagraph *p, *t; + + p = paragraphs; + while (p != 0) + { + t = p; + p = p->next; + delete t->text; + delete t; + } +} + + +THelpTopic::~THelpTopic() +{ + TCrossRef *crossRefPtr; + + disposeParagraphs(); + if (crossRefs != 0) + { + crossRefPtr = (TCrossRef *)crossRefs; + + /* SS: prevent anachronistic stuff */ + + delete [] crossRefPtr; +// delete [numRefs] crossRefPtr; + } +} + +void THelpTopic::addCrossRef( TCrossRef ref ) +{ + TCrossRef *p; + TCrossRef *crossRefPtr; + + p = new TCrossRef[numRefs+1]; + if (numRefs > 0) + { + crossRefPtr = crossRefs; + memmove(p, crossRefPtr, numRefs * sizeof(TCrossRef)); + + /* SS: prevent anachronistic stuff */ + + delete [] crossRefPtr; +// delete [numRefs] crossRefPtr; + } + crossRefs = p; + crossRefPtr = crossRefs + numRefs; + *crossRefPtr = ref; + ++numRefs; +} + + +void THelpTopic::addParagraph( TParagraph *p ) +{ + TParagraph *pp, *back; + + if (paragraphs == 0) + paragraphs = p; + else + { + pp = paragraphs; + back = pp; + while (pp != 0) + { + back = pp; + pp = pp->next; + } + back->next = p; + } + p->next = 0; +} + +void THelpTopic::getCrossRef( int i, TPoint& loc, uchar& length, + int& ref ) +{ + int oldOffset, curOffset, offset, paraOffset; + TParagraph *p; + int line; + TCrossRef *crossRefPtr; + + paraOffset = 0; + curOffset = 0; + oldOffset = 0; + line = 0; + crossRefPtr = crossRefs + i; + offset = crossRefPtr->offset; + p = paragraphs; + while (paraOffset + curOffset < offset) + { + char lbuf[256]; + + oldOffset = paraOffset + curOffset; + wrapText(p->text, p->size, curOffset, p->wrap, lbuf, sizeof(lbuf)); + ++line; + if (curOffset >= p->size) + { + paraOffset += p->size; + p = p->next; + curOffset = 0; + } + } + loc.x = offset - oldOffset - 1; + loc.y = line; + length = crossRefPtr->length; + ref = crossRefPtr->ref; +} + +char *THelpTopic::getLine( int line, char *buffer, int buflen ) +{ + int offset, i; + TParagraph *p; + + if (lastLine < line) + { + i = line; + line -= lastLine; + lastLine = i; + offset = lastOffset; + p = lastParagraph; + } + else + { + p = paragraphs; + offset = 0; + lastLine = line; + } + buffer[0] = 0; + while (p != 0) + { + while (offset < p->size) + { + char lbuf[256]; + + --line; + strncpy(buffer, wrapText(p->text, p->size, offset, p->wrap, lbuf, sizeof(lbuf)), buflen); + if (line == 0) + { + lastOffset = offset; + lastParagraph = p; + return buffer; + } + } + p = p->next; + offset = 0; + } + buffer[0] = 0; + return buffer; +} + +int THelpTopic::getNumCrossRefs() +{ + return numRefs; +} + +int THelpTopic::numLines() +{ + int offset, lines; + TParagraph *p; + + offset = 0; + lines = 0; + p = paragraphs; + while (p != 0) + { + offset = 0; + while (offset < p->size) + { + char lbuf[256]; + ++lines; + wrapText(p->text, p->size, offset, p->wrap, lbuf, sizeof(lbuf)); + } + p = p->next; + } + return lines; +} + +void THelpTopic::setCrossRef( int i, TCrossRef& ref ) +{ + TCrossRef *crossRefPtr; + + if (i < numRefs) + { + crossRefPtr = crossRefs + i; + *crossRefPtr = ref; + } +} + + +void THelpTopic::setNumCrossRefs( int i ) +{ + TCrossRef *p, *crossRefPtr; + + if (numRefs == i) + return; + p = new TCrossRef[i]; + if (numRefs > 0) + { + crossRefPtr = crossRefs; + if (i > numRefs) + memmove(p, crossRefPtr, numRefs * sizeof(TCrossRef)); + else + memmove(p, crossRefPtr, i * sizeof(TCrossRef)); + + /* SS: prevent anachronistic stuff */ + + delete [] crossRefPtr; +// delete [numRefs] crossRefPtr; + } + crossRefs = p; + numRefs = i; +} + + +void THelpTopic::setWidth( int aWidth ) +{ + width = aWidth; +} + +void THelpTopic::writeParagraphs( opstream& s ) +{ + int i; + TParagraph *p; + int temp; + + p = paragraphs; + for (i = 0; p != 0; ++i) + p = p->next; + s << i; + for(p = paragraphs; p != 0; p = p->next) + { + s << p->size; + temp = int(p->wrap); + s << temp; + s.writeBytes(p->text, p->size); + } +} + + +void THelpTopic::writeCrossRefs( opstream& s ) +{ + int i; + TCrossRef *crossRefPtr; + + s << numRefs; + if (crossRefHandler == notAssigned) + { + for(i = 0; i < numRefs; ++i) + { + crossRefPtr = crossRefs + i; + s << crossRefPtr->ref << crossRefPtr->offset << crossRefPtr->length; + } + } + else + for (i = 0; i < numRefs; ++i) + { + crossRefPtr = crossRefs + i; + (*crossRefHandler)(s, crossRefPtr->ref); + s << crossRefPtr->offset << crossRefPtr->length; + } +} + +Boolean isBlank( char ch ) +{ + if (isspace((uchar)ch)) + return True; + else + return False; +} + +int scan( char *p, int offset, char c) +{ + char *temp1, *temp2; + + temp1 = p + offset; + temp2 = strchr(temp1, c); + if (temp2 == 0) + return 256; + else + { + if ((int)(temp2 - temp1) <= 256 ) + return (int) (temp2 - temp1) + 1; + else + return 256; + } +} + +void textToLine( void *text, int offset, int length, char *line ) +{ + strncpy(line, (char *)text+offset, length); + line[length] = 0; +} + +char *THelpTopic::wrapText( char *text, int size, int& offset, Boolean wrap, + char *lineBuf, int lineBufLen ) +{ + int i; + + i = scan(text, offset, '\n'); + if (i + offset > size ) + i = size - offset; + if ((i >= width) && (wrap == True)) + { + i = offset + width; + if (i > size) + i = size; + else + { + while((i > offset) && !(isBlank(text[i]))) + --i; +/* + if (i == offset) + i = offset + width; + else + ++i; +*/ + if( i == offset ) + { + i = offset + width; + while( (i < size) && !isBlank(text[i]) ) + ++i; + if( i < size ) + ++i; + } + else + ++i; + } + if (i == offset) + i = offset + width; + i -= offset; + } + textToLine(text, offset, min(i,lineBufLen), lineBuf); + if (lineBuf[min(strlen(lineBuf) - 1, (size_t)lineBufLen)] == '\n') + lineBuf[min(strlen(lineBuf) - 1, (size_t)lineBufLen)] = 0; + offset += min(i,lineBufLen); + return lineBuf; +} + +// THelpIndex + +const char * const THelpIndex::name = "THelpIndex"; + +void THelpIndex::write( opstream& os ) +{ + long *indexArrayPtr; + + os << size; + for (int i = 0; i < size; ++i) + { + indexArrayPtr = index + i; + os << *indexArrayPtr; + } +} + +void *THelpIndex::read( ipstream& is ) +{ + long *indexArrayPtr; + + is >> size; + if (size == 0) + index = 0; + else + { + index = new long[size]; + for(int i = 0; i < size; ++i) + { + indexArrayPtr = index + i; + is >> *indexArrayPtr; + } + } + return this; +} + +TStreamable *THelpIndex::build() +{ + return new THelpIndex( streamableInit ); +} + +TStreamableClass RHelpIndex( THelpIndex::name, + THelpIndex::build, + __DELTA(THelpIndex) + ); + +THelpIndex::~THelpIndex() +{ + /* SS: prevent anachronistic stuff */ + + delete [] index; +// delete [size] index; +} + + +THelpIndex::THelpIndex(void): TObject () +{ + size = 0; + index = 0; +} + +long THelpIndex::position(int i) +{ + long *indexArrayPtr; + + if (i < size) + { + indexArrayPtr = index + i; + return (*indexArrayPtr); + } + else + return -1; +} + +void THelpIndex::add( int i, long val ) +{ + int delta = 10; + long *p; + int newSize; + long *indexArrayPtr; + + if (i >= size) + { + newSize = (i + delta) / delta * delta; + p = new long[newSize]; + if (p != 0) + { + memmove(p, index, size * sizeof(long)); + memset(p+size, 0xFF, (newSize - size) * sizeof(long)); + } + if (size > 0) + { + /* SS: prevent anachronistic stuff */ + + delete [] index; +// delete [size] index; + } + index = p; + size = newSize; + } + indexArrayPtr = index + i; + *indexArrayPtr = val; +} + +// THelpFile + +THelpFile::THelpFile( fpstream& s ) +{ + long magic; + long size; + + magic = 0; + size = s.filelength(); // SET: New syntax + s.seekg(0); + if (size > (long)sizeof(magic)) /* XXX */ + s >> magic; + if (magic != magicHeader) + { + indexPos = 12; + s.seekg(indexPos); + index = new THelpIndex; + modified = True; + } + else + { + s.seekg(8); + s >> indexPos; + s.seekg(indexPos); + s >> index; + modified = False; + } + stream = &s; +} + +THelpFile::~THelpFile(void) +{ + long magic, size; + + if (modified == True) + { + stream->seekp(indexPos); + *stream << index; + stream->seekp(0); + magic = magicHeader; + size = stream->filelength() - 8; // SET: New syntax + *stream << magic; + *stream << size; + *stream << indexPos; + } + delete stream; + delete index; +} + +THelpTopic *THelpFile::getTopic( int i ) +{ + long pos; + THelpTopic *topic = 0; + + pos = index->position(i); + if (pos > 0 ) + { + stream->seekg(pos); + *stream >> topic; + return topic; + } + else return(invalidTopic()); +} + +THelpTopic *THelpFile::invalidTopic() +{ + THelpTopic *topic; + TParagraph *para; + + topic = new THelpTopic; + para = new TParagraph; + para->text = newStr(invalidContext); + para->size = strlen(invalidContext); + para->wrap = False; + para->next = 0; + topic->addParagraph(para); + return topic; +} + +void THelpFile::recordPositionInIndex( int i ) +{ + index->add(i, indexPos); + modified = True; +} + +void THelpFile::putTopic( THelpTopic *topic ) +{ + stream->seekp(indexPos); + *stream << topic; + indexPos = stream->tellp(); + modified = True; +} + +void notAssigned( opstream& , int ) +{ +} diff --git a/tvision/classes/ifpstrea.cc b/tvision/classes/ifpstrea.cc new file mode 100644 index 0000000..48d8629 --- /dev/null +++ b/tvision/classes/ifpstrea.cc @@ -0,0 +1,55 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Vadim Beloborodov to be used on WIN32 console +Modified to compile with gcc v3.x by Salvador E. Tropea, with the help of +Andris Pavenis. + + * + * + */ + +#define Uses_fpbase +#define Uses_ifpstream +#define Uses_IOS_BIN +#include + +UsingNamespaceStd + +ifpstream::ifpstream() +{ +} + +ifpstream::ifpstream( const char* name, CLY_OpenModeT omode, int prot ) : + fpbase( name, omode | CLY_IOSIn | CLY_IOSBin, prot ) +{ +} + +ifpstream::ifpstream( int f ) : fpbase( f ) +{ +} + +ifpstream::ifpstream(int f, char* b, int len) : fpbase(f, b, len) +{ +} + +ifpstream::~ifpstream() +{ +} + +CLY_filebuf *ifpstream::rdbuf() +{ + return fpbase::rdbuf(); +} + +void ifpstream::open( const char *name, CLY_OpenModeT omode, int prot ) +{ + fpbase::open( name, omode | CLY_IOSIn | CLY_IOSBin, prot ); +} + + diff --git a/tvision/classes/iopstrea.cc b/tvision/classes/iopstrea.cc new file mode 100644 index 0000000..50d8932 --- /dev/null +++ b/tvision/classes/iopstrea.cc @@ -0,0 +1,34 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified to compile with gcc v3.x by Salvador E. Tropea, with the help of +Andris Pavenis. + + * + * + */ + +#define Uses_pstream +#define Uses_iopstream +#include + +UsingNamespaceStd + +iopstream::iopstream( CLY_streambuf * sb ) +{ + pstream::init( sb ); +} + +iopstream::~iopstream() +{ +} + +iopstream::iopstream() +{ +} + diff --git a/tvision/classes/ipstream.cc b/tvision/classes/ipstream.cc new file mode 100644 index 0000000..22530e6 --- /dev/null +++ b/tvision/classes/ipstream.cc @@ -0,0 +1,283 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + * Modified by Robert H”hne to be used for RHIDE. + * + * SET: Moved the standard headers here because according to DJ + * they can inconditionally declare symbols like NULL. + * Reworked code for endian stuff (readShort, readInt, readLong, read8, + * read16, read32 and read64) + * + * Modified to compile with gcc v3.x by Salvador E. Tropea, with the help of + * Andris Pavenis and Christoph Bauer. + * + * JASC: Endian compatible files + * + */ +#include +#define Uses_string +#define Uses_stdio // EOF +#define Uses_TStreamable +#define Uses_TStreamableClass +#define Uses_TStreamableTypes +#define Uses_pstream +#define Uses_ipstream +#define Uses_TPReadObjects +#define Uses_PubStreamBuf +#include + +ipstream::ipstream( CLY_streambuf *sb ) +{ + objs = new TPReadObjects(); + pstream::init( sb ); +} + +ipstream::~ipstream() +{ + objs->shouldDelete = False; + CLY_destroy((TObject *)objs); +} + +CLY_StreamPosT ipstream::tellg() +{ + return bp->CLY_PubSeekOff( 0, CLY_IOSCur, CLY_IOSIn ); +} + +ipstream& ipstream::seekg( CLY_StreamPosT pos ) +{ + objs->removeAll(); + bp->CLY_PubSeekOff( pos, CLY_IOSBeg ); + clear(); //is added by V.Bugrov for clear eof bit + return *this; +} + +ipstream& ipstream::seekg( CLY_StreamOffT off, CLY_IOSSeekDir dir ) +{ + objs->removeAll(); + bp->CLY_PubSeekOff( off, dir ); + clear(); //is added by V.Bugrov for clear eof bit + return *this; +} + +uchar ipstream::readByte() +{ + // Added modified code by V. Bugrov + int result = bp->sbumpc(); + if (result == EOF) + setstate(CLY_IOSEOFBit); + return (uchar)result; // This cast is safe here +} + + +/* + * readShort, readInt and readLong: + * These are platform dependent, reads the size and byte order of the native + * platform. + * Created by SET to be compatible with original code and V. Bugrov ideas. + */ + +#define DefineReadDep(name,type)\ +type ipstream::read##name()\ +{\ + type temp; size_t i;\ + i=bp->sgetn((char *)&temp,sizeof(type));\ + if (isgetn((char *)&temp,sizeof(type));\ + if (isgetn( (char *)data, sz ); + if (i < sz) + { + setstate(CLY_IOSEOFBit); + // SET: Fill with 0s. Avoid using unitialized memory. + memset( ((char *)data) + i, 0, sz - i); + } +} + +char *ipstream::readString() +{ + uchar _len = readByte(); + if( _len == 0xFF ) + return 0; + int len = _len; + if( len == 0xfe ) + // SET: Read a fixed ammount of bytes in all platforms + len = read32(); + char *buf = new char[len+1]; + if( buf == 0 ) + return 0; + readBytes( buf, len ); + buf[len] = EOS; + return buf; +} + +char *ipstream::readString( char *buf, unsigned maxLen ) +{ + assert( buf != 0 ); + char *tmp = readString(); + if (tmp) + { + strncpy(buf, tmp, maxLen-1); + buf[maxLen-1] = 0; + delete [] tmp; + } + else + *buf = 0; + return buf; +} + +/* Operators moved to headers by JASC */ + +CLY_EXPORT ipstream& operator >> ( ipstream& ps, TStreamable& t ) +{ + const TStreamableClass *pc = ps.readPrefix(); + ps.readData( pc, &t ); + ps.readSuffix(); + return ps; +} + +CLY_EXPORT ipstream& operator >> ( ipstream& ps, void *&t ) +{ + char ch = ps.readByte(); + switch( ch ) + { + case pstream::ptNull: + t = 0; + break; + case pstream::ptIndexed: + { + P_id_type index = ps.readWord(); + t = (void *)ps.find( index ); + assert( t != 0 ); + break; + } + case pstream::ptObject: + { + const TStreamableClass *pc = ps.readPrefix(); + t = ps.readData( pc, 0 ); + ps.readSuffix(); + break; + } + default: + ps.error( pstream::peInvalidType ); + break; + } + return ps; +} + +ipstream::ipstream() +{ + objs = new TPReadObjects(); +} + +const TStreamableClass *ipstream::readPrefix() +{ + char ch = readByte(); + assert( ch == '[' ); // don't combine this with the previous line! + // We must always do the read, even if we're + // not checking assertions + + char name[128]; + readString( name, sizeof name ); + const TStreamableClass *ret = types->lookup( name ); + assert( ret != NULL ); + return ret; +} + +void *ipstream::readData( const TStreamableClass *c, TStreamable *mem ) +{ + if( mem == 0 ) + mem = c->build(); + + registerObject( (char *)mem - c->delta ); // register the actual address + // of the object, not the address + // of the TStreamable sub-object + return mem->read( *this ); +} + +void ipstream::readSuffix() +{ + char ch = readByte(); + assert( ch == ']' ); // don't combine this with the previous line! + // We must always do the write, even if we're + // not checking assertions + +} + +const void *ipstream::find( P_id_type id ) +{ + return objs->find( id ); +} + +void ipstream::registerObject( const void *adr ) +{ + objs->registerObject( adr ); +} + diff --git a/tvision/classes/linux/linuxdis.cc b/tvision/classes/linux/linuxdis.cc new file mode 100644 index 0000000..daea92d --- /dev/null +++ b/tvision/classes/linux/linuxdis.cc @@ -0,0 +1,382 @@ +/***************************************************************************** + + Linux display routines. + Copyright (c) 1996-1998 by Robert Hoehne. + Copyright (c) 1999-2002 by Salvador E. Tropea (SET) + Covered by the GPL license. + + Known problems: +* Linux palette handling is quite poor, you can set the 16 colors used by your +VT, you can set the 16 colors used in all the consoles (at the same time and +making them the defaults) and you can get the 16 default colors. But you can't +know the 16 colors used by the current VT. Currently I assume the console is +using the same colors as the rest of the consoles. So I read the default +colors and restore them. + +*****************************************************************************/ +#include + +#define Uses_stdio +#define Uses_stdlib +#define Uses_unistd +#define Uses_signal +#define Uses_TDisplay +#define Uses_TScreen +#define Uses_string +#define Uses_TGKey +#define Uses_TVCodePage +#include + +// I delay the check to generate as much dependencies as possible +#ifdef TVOSf_Linux + +#include +//#include Not needed anymore +#include +// GIO_CMAP ioctl +#include + +#include +#include +#include + +int TDisplayLinux::curX=0; +int TDisplayLinux::curY=0; +// Current cursor shape +int TDisplayLinux::cursorStart=86; // 86 % +int TDisplayLinux::cursorEnd =99; // 99 % +// 1 when the size of the window where the program is running changed +volatile sig_atomic_t TDisplayLinux::windowSizeChanged=0; +int TDisplayLinux::vcsWfd=-1; // virtual console system descriptor +int TDisplayLinux::vcsRfd=-1; // Same for reading +int TDisplayLinux::hOut=-1; // Handle for the console output +FILE *TDisplayLinux::fOut=NULL; +char *TDisplayLinux::origEnvir=NULL; +char *TDisplayLinux::newEnvir=NULL; +int TDisplayLinux::maxLenTit=0; +char TDisplayLinux::tioclinuxOK=0; +char TDisplayLinux::cMap[16]={0,4,2,6,1,5,3,7,8,12,10,14,9,13,11,15}; +unsigned TDisplayLinux::oldCurX, + TDisplayLinux::oldCurY; + // These are the Linux kernel defaults: CP437 font and lat1 map +int TDisplayLinux::installedSFM=TVCodePage::PC437; +int TDisplayLinux::installedACM=TVCodePage::ISOLatin1Linux; + +// All the code is in TScreenLinux, but this is the right moment, by this +// time TScreenLinux is suspended. +TDisplayLinux::~TDisplayLinux() +{ + LOG("TDisplayLinux Destructor"); + TScreenLinux::DeallocateResources(); +} + +void TDisplayLinux::Init(int mode) +{ + switch (mode) + { + case lnxInitVCSrw: + setCursorPos=SetCursorPosVCS; + getCursorPos=GetCursorPosVCS; + break; + case lnxInitVCSwo: + setCursorPos=SetCursorPosVCS; + getCursorPos=GetCursorPosGeneric; + // Set the cursor to a known position to avoid reading the postion. + SetCursorPos(0,0); + break; + case lnxInitSimple: + setCursorPos=SetCursorPos; + getCursorPos=GetCursorPos; + break; + case lnxInitMDA: + setCursorPos=SetCursorPosMDA; + getCursorPos=GetCursorPosGeneric; + break; + } + if (mode==lnxInitMDA) + { + getCursorShape=GetCursorShapeMDA; + setCursorShape=SetCursorShapeMDA; + getRows=defaultGetRows; + getCols=defaultGetCols; + getDisPaletteColors=defaultGetDisPaletteColors; + setDisPaletteColors=defaultSetDisPaletteColors; + } + else + { + getCursorShape=GetCursorShape; + setCursorShape=SetCursorShape; + getRows=GetRows; + getCols=GetCols; + getDisPaletteColors=tioclinuxOK ? GetDisPaletteColors : defaultGetDisPaletteColors; + setDisPaletteColors=SetDisPaletteColors; + } + checkForWindowSize=CheckForWindowSize; + getWindowTitle=GetWindowTitle; + setWindowTitle=SetWindowTitle; + + setUpEnviron(); +} + +void TDisplayLinux::SetCursorPos(unsigned x, unsigned y) +{ + fprintf(fOut,"\E[%d;%dH",y+1,x+1); + curX=x; curY=y; +} + +// Generic approach, just returns the last value we set +// Used for MDA and VCS when we can't read +void TDisplayLinux::GetCursorPosGeneric(unsigned &x, unsigned &y) +{ + x=curX; y=curY; +} + +void TDisplayLinux::GetCursorPos(unsigned &x, unsigned &y) +{ + char s[40]; + + fputs("\E[6n",fOut); + *s=0; + fgets(s,sizeof(s)-1,TGKeyLinux::fIn); // Response is \E[y;xR + + if (sscanf(s,"\E[%d;%dR",&y,&x)==2) + { + x--; y--; + } + else + { + x=curX; y=curY; + } +} + +void TDisplayLinux::SetCursorShape(unsigned start, unsigned end) +{ + LOG("Setting cursor shape to " << start << "," << end); + if (start>=end) + { + if (!getShowCursorEver()) + fputs("\E[?1c",fOut); + cursorStart=start; + cursorEnd=end; + } + else + {// Approximate with the size (1-8) + int size=(int)((end-start)/12.5)+1; + if (size>8) size=8; + fprintf(fOut,"\E[?%dc",size); + cursorStart=(int)((8-size)*12.5); + cursorEnd=99; + } +} + +void TDisplayLinux::GetCursorShape(unsigned &start, unsigned &end) +{ + // Currently we don't know the real state. + start=cursorStart; + end =cursorEnd; +} + +ushort TDisplayLinux::GetRows() +{ + winsize win; + win.ws_row=0xFFFF; + ioctl(hOut,TIOCGWINSZ,&win); + return win.ws_row!=0xFFFF ? win.ws_row : 25; +} + +ushort TDisplayLinux::GetCols() +{ + winsize win; + win.ws_col=0xFFFF; + ioctl(hOut,TIOCGWINSZ,&win); + return win.ws_col!=0xFFFF ? win.ws_col : 80; +} + +int TDisplayLinux::CheckForWindowSize(void) +{ + int ret=windowSizeChanged!=0; + windowSizeChanged=0; + return ret; +} + +const char *TDisplayLinux::GetWindowTitle(void) +{ + if (origEnvir) + return newStr(origEnvir); + if (argv) + return newStr(argv[0]); + return 0; +} + +void TDisplayLinux::setUpEnviron() +{ + // Note: The old glibc provided the real environment/argv vector, now that's + // a copy :-( + + if (!argv || // The application didn't provide argv or + newEnvir) // we already initialized + return; + + origEnvir=argv[0]; + maxLenTit=strlen(argv[0]); +} + +int TDisplayLinux::SetWindowTitle(const char *name) +{ + if (!name || !origEnvir) + return 0; + int len=strlen(name); + if (len>=maxLenTit) + { + strncpy(origEnvir,name,maxLenTit-1); + origEnvir[maxLenTit-1]=0; + } + else + strcpy(origEnvir,name); + + return 1; +} + +int TDisplayLinux::SetDisPaletteColors(int from, int number, TScreenColor *colors) +{ + // Assume all will be ok + int ret=number; + while (number-- && from<16) + { + fprintf(fOut,"\E]P%1.1X%2.2X%2.2X%2.2X",cMap[from++],colors->R,colors->G,colors->B); + colors++; + } + return ret; +} + +void TDisplayLinux::GetDisPaletteColors(int from, int number, TScreenColor *colors) +{ + uchar vtColors[16*3]; + // Get default VT colors map + int ret=ioctl(hOut,GIO_CMAP,vtColors),index; + if (ret==0) + { + while (number-- && from<16) + { + index=cMap[from++]*3; + colors->R=vtColors[index]; + colors->G=vtColors[index+1]; + colors->B=vtColors[index+2]; + colors++; + } + } + else + // Shouldn't happend + defaultGetDisPaletteColors(from,number,colors); +} + +/***************************************************************************** + VCS specific code +*****************************************************************************/ + +void TDisplayLinux::SetCursorPosVCS(unsigned x, unsigned y) +{ + unsigned char where[2]={x,y}; + + lseek(vcsWfd,2,SEEK_SET); + write(vcsWfd,where,sizeof(where)); + // Cache the value to avoid the need to read it + curX=x; curY=y; +} + +void TDisplayLinux::GetCursorPosVCS(unsigned &x, unsigned &y) +{ + unsigned char where[2]; + + lseek(vcsRfd,2,SEEK_SET); + read(vcsRfd,where,sizeof(where)); + x=where[0]; + y=where[1]; +} + +/***************************************************************************** + Code to handle a secondary monochrome display, currently not implemented + but can be added. +*****************************************************************************/ + +#ifdef h386LowLevel +#if HAVE_OUTB_IN_SYS + #include +#else + #include +#endif + +static inline +unsigned char I(unsigned char i) +{ + outb(i,0x3b4); + return inb(0x3b5); +} + +static inline +void O(unsigned char i,unsigned char b) +{ + outb(i,0x3b4); + outb(b,0x3b5); +} + +void TDisplayLinux::SetCursorPosMDA(unsigned x, unsigned y) +{ + unsigned short loc = y*80+x; + O(0x0e,loc >> 8); + O(0x0f,loc & 0xff); +} + +void TDisplayLinux::SetCursorShapeMDA(unsigned start, unsigned end) +{ + if (start>=end) // cursor off + { + O(0x0a,0x01); + O(0x0b,0x00); + } + else + { + start=start*16/100; + end=end*16/100; + O(0x0a,start); + O(0x0b,end); + } + cursorStart=start; + cursorEnd=end; +} + +void TDisplayLinux::GetCursorShapeMDA(unsigned &start, unsigned &end) +{ + unsigned short ct; + ct=(I(0x0a)<<8) | I(0x0b); + if (!ct) + start=end=0; + else + { + start=86; + end=99; + } +} +#else +void TDisplayLinux::SetCursorPosMDA(unsigned , unsigned ) {} +void TDisplayLinux::SetCursorShapeMDA(unsigned start, unsigned end) +{ + cursorStart=start; + cursorEnd=end; +} + +void TDisplayLinux::GetCursorShapeMDA(unsigned &start, unsigned &end) +{ + start=cursorStart; + end=cursorEnd; +} +#endif // h386LowLevel + +#else // TVOSf_Linux + +#include +#include +#include + +#endif // else TVOSf_Linux + diff --git a/tvision/classes/linux/linuxkey.cc b/tvision/classes/linux/linuxkey.cc new file mode 100644 index 0000000..253f5b9 --- /dev/null +++ b/tvision/classes/linux/linuxkey.cc @@ -0,0 +1,937 @@ +/***************************************************************************** + + Linux keyboard routines. + Copyright (c) 1998-2002 by Salvador E. Tropea (SET) + Some portions come from code: + Copyright (c) 1998 by Robert Hoehne. + Covered by the GPL license. + + This driver is a relatively complex one because: + 1) Deals with console mode. + 2) Translates keyboard codes. + 3) Parses escape sequences. + 4) Patches keyboard tables and restores it on console switchs. + + Todo: + * How do I setup things before they are hooked? SetKbdMapping needs to + be reworked. + * Should I move VT detection to a separated module? + * Asegurarse que atexit se llame el que restaura el teclado. + * El módulo de TScreenLinux tendría que llamar a InitOnce(), si esto le da + error no seguir. Y si el tien problemas debería llamar al Suspend() para + que restaure. + +*****************************************************************************/ +#include + +#define Uses_stdio +#define Uses_string +#define Uses_unistd +#define Uses_signal +#define Uses_TEvent +#define Uses_TGKey +#define Uses_FullSingleKeySymbols +#define Uses_TScreen +#define Uses_TVCodePage +#include + +// I delay the check to generate as much dependencies as possible +#ifdef TVOSf_Linux + +#include +#include +#include +// For the VT and key patch stuff +#include +#include + +#include +#include +#include + +int TGKeyLinux::hIn=-1; +FILE *TGKeyLinux::fIn=NULL; +int TGKeyLinux::oldInFlags; +int TGKeyLinux::newInFlags; +struct termios TGKeyLinux::inTermiosOrig; +struct termios TGKeyLinux::inTermiosNew; +const char *TGKeyLinux::error=NULL; +int TGKeyLinux::bufferKeys[MaxLenEscapeSequence]; +int TGKeyLinux::keysInBuffer=0; +int TGKeyLinux::nextKey=-1; +int TGKeyLinux::lastKeyCode; +int TGKeyLinux::lastModifiers; +int TGKeyLinux::translatedModifiers; +char TGKeyLinux::dontPatchKeyboard=0; +int TGKeyLinux::ourVT=-1; +struct vt_mode TGKeyLinux::oldVTMode; +struct vt_mode TGKeyLinux::newVTMode; +char TGKeyLinux::vtHooked=0; +char TGKeyLinux::canPatchKeyboard=0; +char TGKeyLinux::keyPatched=0; +char TGKeyLinux::ascii; +struct kbentry TGKeyLinux::entry; + +/* Linux IOCTL values found experimentally */ +const int kblNormal=0,kblShift=1,kblAltR=2,kblCtrl=4,kblAltL=8; + +/**[txh]******************************************************************** + + Description: + Does initialization tasks performed only once. + + Return: + 0 if success, !=0 if an error ocurred. In the last case the error member +points to a descriptive error. + +***************************************************************************/ + +int TGKeyLinux::InitOnce() +{ + LOG("TGKeyLinux::InitOnce"); + hIn=fileno(stdin); + + if (!isatty(hIn)) + { + error=_("that's an interactive application, don't redirect stdin"); + return 1; + } + // We can't use stdin for all the operations, instead we must open it again + // using another file descriptor. + // Here is why: In order to get some keys, I saw it for ESC pressed alone, + // we must set the O_NONBLOCK attribute. + // We can do it, but the stdout file handle seems to be just a copy of the + // stdin file handle (dupped?). When you use duplicated file handles they + // share the "File Status Flags". It means that setting O_NONBLOCK will + // set O_NONBLOCK for output too. So what? well when we do that the one that + // doesn't block is Linux kernel, so if we send too much information to + // stdout, no matters if we use fflush, sometimes Linux could lose data. + // This effect seems to happend at exit, may be because owr process dies + // before Linux have a chance to process the remaining data and it closes + // the file handle. The fact is that using O_NONBLOCK sometimes we fail to + // restore the cursor position. + // Now a question remains: do I have to restore the mode? + char *ttyName=ttyname(hIn); + if (!ttyName) + { + error=_("failed to get the name of the current terminal used for input"); + return 3; + } + fIn=fopen(ttyName,"r+b"); + if (!fIn) + { + error=_("failed to open the input terminal"); + return 4; + } + hIn=fileno(fIn); + + if (tcgetattr(hIn,&inTermiosOrig)) + { + error=_("can't get input terminal attributes"); + return 2; + } + + memcpy(&inTermiosNew,&inTermiosOrig,sizeof(inTermiosNew)); + // Ignore breaks + inTermiosNew.c_iflag|= (IGNBRK | BRKINT); + // Disable Xon/off + inTermiosNew.c_iflag&= ~(IXOFF | IXON); + // Character oriented, no echo, no signals + inTermiosNew.c_lflag&= ~(ICANON | ECHO | ISIG); + if (tcsetattr(hIn,TCSAFLUSH,&inTermiosNew)) + { + error=_("can't set input terminal attributes"); + return 3; + } + // Don't block, needed to get some keys, even when the input is in character + // oriented mode. I saw it for ESC alone. + oldInFlags=fcntl(hIn,F_GETFL,0); + newInFlags=oldInFlags | O_NONBLOCK; + fcntl(hIn,F_SETFL,newInFlags); + + // Find if we are running in a VT and if that's the case the number + // This name should be the same but ... + ttyName=ttyname(STDOUT_FILENO); + if (ttyName) + { + if (sscanf(ttyName,"/dev/tty%2d",&ourVT)!=1) + // SET: Some Slackware systems (I think that is what Andris uses) + // define /dev/ttyNN as symlinks to /dev/vc/NN: + if (sscanf(ttyName,"/dev/vc/%2d",&ourVT)!=1) + ourVT=-1; + } + // Get the mode of the current VT + if (ourVT!=-1) + { + if (ioctl(hIn,VT_GETMODE,&oldVTMode)) + // If we fail disable it + ourVT=-1; + else + {// Tell the kernel to inform us about console changes + newVTMode=oldVTMode; + newVTMode.mode =VT_PROCESS; + newVTMode.relsig=SIGUSR1; + newVTMode.acqsig=SIGUSR2; + } + } + // Check if we can patch the keyboard + canPatchKeyboard=0; + long optPatchKeys=1; // Default is patch the keyboard + TScreen::optSearch("PatchKeys",optPatchKeys); + if (optPatchKeys && ourVT!=-1 && ioctl(hIn,KDGKBENT,&entry)==0) + { + canPatchKeyboard=1; + keyMapInit(); + } + // Now do the hook/patching + doHookAndPatch(); + // We don't need to call Resume + suspended=0; + return 0; +} + +/**[txh]******************************************************************** + + Description: + Restore the original console state. + +***************************************************************************/ + +void TGKeyLinux::Suspend() +{ + doUnHookAndUnPatch(); + // Now we use a new opened file handle for input. + // As these flags are the flags for the file handle (not the terminal itself) + // we don't need to restore the originals. + // Why don't do it anyways? because the TScreen::resume is called before and + // it needs to get the cursor position using escape sequences without waiting + // for an EOL. + //fcntl(hIn,F_SETFL,oldInFlags); + tcsetattr(hIn,TCSAFLUSH,&inTermiosOrig); + LOG("TGKeyLinux::Suspend"); +} + +/**[txh]******************************************************************** + + Description: + Memorize current console state and setup the one needed for us. + +***************************************************************************/ + +void TGKeyLinux::Resume() +{// Read current state + tcgetattr(hIn,&inTermiosOrig); + oldInFlags=fcntl(hIn,F_GETFL,0); + // Set our state + tcsetattr(hIn,TCSAFLUSH,&inTermiosNew); + // The following shouldn't be needed, I'll let it here unless I discover + // some side effect. + fcntl(hIn,F_SETFL,newInFlags); + // The user could do some action to alter the keyboard mapping tables + if (canPatchKeyboard) + keyMapInit(); + // Patch keyboard and hook the signals + doHookAndPatch(); + LOG("TGKeyLinux::Resume"); +} + +int TGKeyLinux::KbHit() +{ + if (keysInBuffer || nextKey!=-1) + return 1; // We have a key waiting for processing + nextKey=fgetc(fIn); + return nextKey!=-1; +} + +void TGKeyLinux::Clear() +{ + // Discard our buffer + keysInBuffer=0; + // Discard a key waiting + nextKey=-1; + // Flush the input + fflush(fIn); +} + +/***************************************************************************** + + Here starts the keyboard parser and translator. + It uses a static tree/hash to parse the escape sequences, may be this should +be configurable. + +*****************************************************************************/ + +// - 9 = Tab tiene conflicto con kbI+Control lo cual es natural, por otro +// -lado Ctrl+Tab no lo reporta en forma natural +// - a = Enter tiene conflicto con ^J, como ^J no lo reporta naturalmente sino +// -forzado por el keymap lo mejor es definirlo directamente. +unsigned char TGKeyLinux::kbToName[128] = +{ + 0,kbA,kbB,kbC,kbD,kbE,kbF,kbG, // 00-07 + kbH,kbTab,kbEnter,kbK,kbL,kbM,kbN,kbO, // 08-0F + kbP,kbQ,kbR,kbS,kbT,kbU,kbV,kbW, // 10-17 + kbX,kbY,kbZ,kbEsc,0,kbCloseBrace,kb6,kbMinus, // 18-1F + kbSpace,kbAdmid,kbDobleQuote,kbNumeral,kbDolar,kbPercent,kbAmper,kbQuote,// 20-27 + kbOpenPar,kbClosePar,kbAsterisk,kbPlus,kbComma,kbMinus,kbStop,kbSlash, // 28-2F + kb0,kb1,kb2,kb3,kb4,kb5,kb6,kb7, // 30-37 + kb8,kb9,kbDoubleDot,kbColon,kbLessThan,kbEqual,kbGreaterThan,kbQuestion, // 38-3F + kbA_Roba,kbA,kbB,kbC,kbD,kbE,kbF,kbG, // 40-47 + kbH,kbI,kbJ,kbK,kbL,kbM,kbN,kbO, // 48-4F + kbP,kbQ,kbR,kbS,kbT,kbU,kbV,kbW, // 50-57 + kbX,kbY,kbZ,kbOpenBrace,kbBackSlash,kbCloseBrace,kbCaret,kbUnderLine, // 58-5F + kbGrave,kbA,kbB,kbC,kbD,kbE,kbF,kbG, // 60-67 + kbH,kbI,kbJ,kbK,kbL,kbM,kbN,kbO, // 68-6F + kbP,kbQ,kbR,kbS,kbT,kbU,kbV,kbW, // 70-77 + kbX,kbY,kbZ,kbOpenCurly,kbOr,kbCloseCurly,kbTilde,kbBackSpace // 78-7F +}; + +unsigned char TGKeyLinux::kbExtraFlags[128] = +{ + 0,kblCtrl,kblCtrl,kblCtrl,kblCtrl,kblCtrl,kblCtrl,kblCtrl, // 00-07 + kblCtrl,0,0,kblCtrl,kblCtrl,kblCtrl,kblCtrl,kblCtrl, // 08-0F + kblCtrl,kblCtrl,kblCtrl,kblCtrl,kblCtrl,kblCtrl,kblCtrl,kblCtrl, // 10-17 + kblCtrl,kblCtrl,kblCtrl,0,0,kblCtrl,kblCtrl,kblCtrl, // 18-1F + 0,kblShift,kblShift,kblShift,kblShift,kblShift,kblShift,0, // 20-27 + kblShift,kblShift,kblShift,kblShift,0,0,0,0, // 28-2F + 0,0,0,0,0,0,0,0, // 30-37 + 0,0,kblShift,0,kblShift,0,kblShift,kblShift, // 38-3F + kblShift,kblShift,kblShift,kblShift,kblShift,kblShift,kblShift,kblShift, // 40-47 + kblShift,kblShift,kblShift,kblShift,kblShift,kblShift,kblShift,kblShift, // 48-4F + kblShift,kblShift,kblShift,kblShift,kblShift,kblShift,kblShift,kblShift, // 50-57 + kblShift,kblShift,kblShift,0,0,0,kblShift,kblShift, // 58-5F + 0,0,0,0,0,0,0,0, // 60-67 + 0,0,0,0,0,0,0,0, // 68-6F + 0,0,0,0,0,0,0,0, // 70-77 + 0,0,0,kblShift,kblShift,kblShift,kblShift,0, // 78-7F +}; + +/************************** Escape sequences tree **************************/ +struct node +{ + char value; + unsigned char code; + unsigned char modifiers; + node *next; +}; + +static node F6[]={{1,0,0},{'~',kbF6,0,0}}; +static node F7[]={{1,0,0},{'~',kbF7,0,0}}; +static node F8[]={{1,0,0},{'~',kbF8,0,0}}; +static node F9[]={{1,0,0},{'~',kbF9,0,0}}; +static node F10[]={{1,0,0},{'~',kbF10,0,0}}; +static node F11[]={{1,0,0},{'~',kbF11,0,0}}; +static node F12[]={{1,0,0},{'~',kbF12,0,0}}; +static node Delete[]={{1,0,0},{'~',kbDelete,0,0}}; +static node End[]={{1,0,0},{'~',kbEnd,0,0}}; +static node PgUp[]={{1,0,0},{'~',kbPgUp,0,0}}; +static node PgDn[]={{1,0,0},{'~',kbPgDn,0,0}}; + +static node Brace1[]= +{ + {4,0,0}, + {'~',kbHome,0,0}, + {'7',0,0,F6}, + {'8',0,0,F7}, + {'9',0,0,F8} +}; + +static node Brace2[]= +{ + {5,0,0}, + {'~',kbInsert,0,0}, + {'0',0,0,F9}, + {'1',0,0,F10}, + {'3',0,0,F11}, + {'4',0,0,F12} +}; + +static node BraceKeys[]= +{ + {5,0,0}, + {'A',kbF1,0,0}, + {'B',kbF2,0,0}, + {'C',kbF3,0,0}, + {'D',kbF4,0,0}, + {'E',kbF5,0,0}, +}; + +static node Sequences[]= +{ + {13,0,0}, + {'[',0,0,BraceKeys}, + {'A',kbUp,0,0}, + {'B',kbDown,0,0}, + {'C',kbRight,0,0}, + {'D',kbLeft,0,0}, + {'G',kb5,0,0}, + {'P',kbPause,0,0}, + {'1',0,0,Brace1}, + {'2',0,0,Brace2}, + {'3',0,0,Delete}, + {'4',0,0,End}, + {'5',0,0,PgUp}, + {'6',0,0,PgDn} +}; + +static node Keys[]= +{ + {1,0,0}, + {'[',0,0,Sequences} +}; +/*********************** End of escape sequences tree ***********************/ + +/**[txh]******************************************************************** + + Description: + Parse a escape sequence. + + Returns: 1 if the sequence found, 0 if not and the keys are stored in the +buffer. + +***************************************************************************/ + +int TGKeyLinux::ProcessEscape() +{ + int nextVal; + + nextVal=fgetc(fIn); + if (nextVal==EOF) // Just ESC + return 0; + + node *p=Keys; + int cant,i; + keysInBuffer=0; + while (nextVal!=EOF) + { + NextNode: + bufferKeys[keysInBuffer++]=nextVal; + cant=p->value; + for (i=1; i<=cant; i++) + { + if (p[i].value==nextVal) + { + if (p[i].next) + { + p=p[i].next; + nextVal=fgetc(fIn); + goto NextNode; + } + lastKeyCode=p[i].code; + lastModifiers=p[i].modifiers; + keysInBuffer=0; + return 1; + } + } + return 0; + } + return 0; +} + +int TGKeyLinux::GetKeyFromBuffer() +{ + int ret=bufferKeys[--keysInBuffer]; + if (keysInBuffer) + memcpy(bufferKeys,bufferKeys+1,keysInBuffer); + return ret; +} + +/**[txh]******************************************************************** + + Description: + Gets a key from the buffer, waiting value or stdin and if needed calls +the escape sequence parser. + +***************************************************************************/ + +int TGKeyLinux::GetKeyParsed() +{ + lastModifiers=0; + translatedModifiers=-1; + // If we have keys in the buffer take from there. + // They already failed the escape sequence test. + if (keysInBuffer) + return GetKeyFromBuffer(); + + // Use the value we have on hold or get a new one + int nextVal=nextKey; + nextKey=-1; + if (nextVal==-1) + nextVal=fgetc(fIn); + if (nextVal==-1) + return -1; + + // Is that an escape sequence? + if (nextVal=='\e') + { + if (ProcessEscape()) + return -2; + if (!keysInBuffer) + return '\e'; + lastKeyCode=GetKeyFromBuffer(); + lastModifiers=kblAltL; + return -3; + } + + return nextVal; +} + +/**[txh]******************************************************************** + + Description: + Gets the next key, their modifiers and ASCII. Is a postprocessor for +GetKeyParsed. + +***************************************************************************/ + +int TGKeyLinux::GetRaw() +{ + int result=GetKeyParsed(); + + if (result==-1) + return 0; // No key + if (result==-2) + { + lastModifiers|=GetLinuxShiftState(); + ascii=0; + return 1; // Key already processed + } + if (result==-3) // Forced modifier + { + result=lastKeyCode; + ascii=result>127 ? result : 0; + } + else + ascii=result; + + // Translate the key + if (result>=128) + lastKeyCode=kbUnkNown; + else + { + lastModifiers|=kbExtraFlags[result]; + lastKeyCode=kbToName[result]; + } + lastModifiers|=GetLinuxShiftState(); + return 1; +} + +/**[txh]******************************************************************** + + Description: + Gets a key from the input and converts it into the TV format. + +***************************************************************************/ + +ushort TGKeyLinux::GKey() +{ + if (GetRaw()) + { // Here I add the modifiers to the key code + if (lastModifiers & kblShift) + lastKeyCode|=kbShiftCode; + if (lastModifiers & kblCtrl) + lastKeyCode|=kbCtrlCode; + switch (AltSet) + { + case 0: // Normal thing, left is left, right is right + if (lastModifiers & kblAltL) + lastKeyCode|=kbAltLCode; + else + if (lastModifiers & kblAltR) + lastKeyCode|=kbAltRCode; + break; + case 1: // Reverse thing + if (lastModifiers & kblAltL) + lastKeyCode|=kbAltRCode; + else + if (lastModifiers & kblAltR) + lastKeyCode|=kbAltLCode; + break; + default: // Compatibility + if (lastModifiers & (kblAltL | kblAltR)) + lastKeyCode|=kbAltLCode; + } + return lastKeyCode; + } + return kbUnkNown; +} +/***************************************************************************** + End of parser and translator. +*****************************************************************************/ + +/**[txh]******************************************************************** + + Description: + Finds the value of the modifiers, if the ioctl fails the values we know +from the last key are used. + + Return: The modifiers in Linux kernel format. + +***************************************************************************/ + +unsigned TGKeyLinux::GetLinuxShiftState() +{ + int arg=6; /* TIOCLINUX function #6 */ + unsigned shift=0; + + if (ioctl(hIn,TIOCLINUX,&arg)!=-1) + shift=arg; + else + shift=lastModifiers; + return shift; +} + +/**[txh]******************************************************************** + + Description: + Finds the value of the modifiers in TV format. + +***************************************************************************/ + +unsigned TGKeyLinux::GetShiftState() +{ + lastModifiers=GetLinuxShiftState(); + if (!lastModifiers) return 0; + if (translatedModifiers==-1) + { + translatedModifiers=0; + if (lastModifiers & kblShift) + translatedModifiers|=kbLeftShiftDown | kbRightShiftDown; + if (lastModifiers & kblCtrl) + translatedModifiers|=kbLeftCtrlDown | kbRightCtrlDown | kbCtrlDown; + if (lastModifiers & kblAltR) + translatedModifiers|=kbRightAltDown | kbAltDown; + if (lastModifiers & kblAltL) + translatedModifiers|=kbLeftAltDown | kbAltDown; + } + return translatedModifiers; +} + + +/**[txh]******************************************************************** + + Description: + Fills the TV event structure for a key. + +***************************************************************************/ + +void TGKeyLinux::FillTEvent(TEvent &e) +{ + GKey(); + e.keyDown.charScan.charCode=lastModifiers & kblAltL ? 0 : ascii; + e.keyDown.charScan.scanCode=ascii; + e.keyDown.raw_scanCode=ascii; + e.keyDown.keyCode=lastKeyCode; + e.keyDown.shiftState=lastModifiers; + e.what=evKeyDown; +} + + +/***************************************************************************** + + Here starts the code to modify Linux kernel tables in order to get better +keyboard information. + Basically it makes Linux kernel map the key+modifiers to the key alone. +That's because these keys acts in special ways when a modifier is applied and +the application can't receive the key. + An example: Shift+PgUp is usually mapped to "scroll up one screen", so we +map it to just PgUp. In this way we get the key, then we get the modifiers +from the ioctl. + That's the code based in Robert's code it was readapted but the idea is +the same. + The code is complicated because we must restore the map when the user +changes to another console. So most of the code deals with the signals +related to virtual console switching. + +*****************************************************************************/ + +typedef struct +{ + uchar change_table; + uchar change_index; + uchar old_table; + uchar old_index; + ushort old_val; + ushort new_val; +} change_entry; + +#define SCAN_F1 0x3b +#define SCAN_F2 0x3c +#define SCAN_F3 0x3d +#define SCAN_F4 0x3e +#define SCAN_F5 0x3f +#define SCAN_F6 0x40 +#define SCAN_F7 0x41 +#define SCAN_F8 0x42 +#define SCAN_F9 0x43 +#define SCAN_F10 0x44 +#define SCAN_Q 0x10 +#define SCAN_S 0x1f +#define SCAN_J 0x24 +#define SCAN_M 0x32 +#define SCAN_Z 0x2C +#define SCAN_PGUP 104 +#define SCAN_PGDN 109 +#define SCAN_BKSP 14 +#define SCAN_SPAC 57 +#define SCAN_TAB 15 +// As ^[ is usually Esc we must be sure it doesn't happend +#define SCAN_LFBR 26 +// The Scroll lock key is evil for an interactive application +// As in my keyboard that's above Home and some people wrongly +// press it instead of Home I'm translating to Home. +#define SCAN_SCRL 70 +#define SCAN_HOME 102 + +static +change_entry changes[]= +{ + { kblAltL, SCAN_F1, kblNormal, SCAN_F1, 0, 0}, + { kblAltR, SCAN_F1, kblNormal, SCAN_F1, 0, 0}, + { kblCtrl, SCAN_F1, kblNormal, SCAN_F1, 0, 0}, + { kblShift, SCAN_F1, kblNormal, SCAN_F1, 0, 0}, + { kblAltL, SCAN_F2, kblNormal, SCAN_F2, 0, 0}, + { kblAltR, SCAN_F2, kblNormal, SCAN_F2, 0, 0}, + { kblCtrl, SCAN_F2, kblNormal, SCAN_F2, 0, 0}, + { kblShift, SCAN_F2, kblNormal, SCAN_F2, 0, 0}, + { kblAltL, SCAN_F3, kblNormal, SCAN_F3, 0, 0}, + { kblAltR, SCAN_F3, kblNormal, SCAN_F3, 0, 0}, + { kblCtrl, SCAN_F3, kblNormal, SCAN_F3, 0, 0}, + { kblShift, SCAN_F3, kblNormal, SCAN_F3, 0, 0}, + { kblAltL, SCAN_F4, kblNormal, SCAN_F4, 0, 0}, + { kblAltR, SCAN_F4, kblNormal, SCAN_F4, 0, 0}, + { kblCtrl, SCAN_F4, kblNormal, SCAN_F4, 0, 0}, + { kblShift, SCAN_F4, kblNormal, SCAN_F4, 0, 0}, + { kblAltL, SCAN_F5, kblNormal, SCAN_F5, 0, 0}, + { kblAltR, SCAN_F5, kblNormal, SCAN_F5, 0, 0}, + { kblCtrl, SCAN_F5, kblNormal, SCAN_F5, 0, 0}, + { kblShift, SCAN_F5, kblNormal, SCAN_F5, 0, 0}, + { kblAltL, SCAN_F6, kblNormal, SCAN_F6, 0, 0}, + { kblAltR, SCAN_F6, kblNormal, SCAN_F6, 0, 0}, + { kblCtrl, SCAN_F6, kblNormal, SCAN_F6, 0, 0}, + { kblShift, SCAN_F6, kblNormal, SCAN_F6, 0, 0}, + { kblAltL, SCAN_F7, kblNormal, SCAN_F7, 0, 0}, + { kblAltR, SCAN_F7, kblNormal, SCAN_F7, 0, 0}, + { kblCtrl, SCAN_F7, kblNormal, SCAN_F7, 0, 0}, + { kblShift, SCAN_F7, kblNormal, SCAN_F7, 0, 0}, + { kblAltL, SCAN_F8, kblNormal, SCAN_F8, 0, 0}, + { kblAltR, SCAN_F8, kblNormal, SCAN_F8, 0, 0}, + { kblCtrl, SCAN_F8, kblNormal, SCAN_F8, 0, 0}, + { kblShift, SCAN_F8, kblNormal, SCAN_F8, 0, 0}, + { kblAltL, SCAN_F9, kblNormal, SCAN_F9, 0, 0}, + { kblAltR, SCAN_F9, kblNormal, SCAN_F9, 0, 0}, + { kblCtrl, SCAN_F9, kblNormal, SCAN_F9, 0, 0}, + { kblShift, SCAN_F9, kblNormal, SCAN_F9, 0, 0}, + { kblAltL, SCAN_F10, kblNormal, SCAN_F10, 0, 0}, + { kblAltR, SCAN_F10, kblNormal, SCAN_F10, 0, 0}, + { kblCtrl, SCAN_F10, kblNormal, SCAN_F10, 0, 0}, + { kblShift, SCAN_F10, kblNormal, SCAN_F10, 0, 0}, + { kblCtrl, SCAN_Q, kblNormal, SCAN_Q, 0, 0}, + { kblCtrl, SCAN_S, kblNormal, SCAN_S, 0, 0}, + { kblCtrl, SCAN_J, kblNormal, SCAN_J, 0, 0}, + { kblCtrl, SCAN_M, kblNormal, SCAN_M, 0, 0}, + { kblCtrl, SCAN_Z, kblNormal, SCAN_Z, 0, 0}, + { kblShift, SCAN_PGUP, kblNormal, SCAN_PGUP, 0, 0}, + { kblShift, SCAN_PGDN, kblNormal, SCAN_PGDN, 0, 0}, + { kblCtrl, SCAN_BKSP, kblNormal, SCAN_BKSP, 0, 0}, + { kblCtrl, SCAN_SPAC, kblNormal, SCAN_SPAC, 0, 0}, + { kblCtrl, SCAN_LFBR, kblNormal, SCAN_LFBR, 0, 0}, + { kblNormal,SCAN_SCRL, kblNormal, SCAN_HOME, 0, 0}, + { kblAltL, SCAN_SCRL, kblNormal, SCAN_HOME, 0, 0}, + { kblAltR, SCAN_SCRL, kblNormal, SCAN_HOME, 0, 0}, + { kblCtrl, SCAN_TAB, kblNormal, SCAN_TAB, 0, 0}, + { kblCtrl | kblShift, SCAN_TAB, kblNormal, SCAN_TAB, 0, 0} +}; + +#define changeSize (sizeof(changes)/sizeof(change_entry)) + +void TGKeyLinux::unPatchKeyMap() +{ + if (!canPatchKeyboard || !keyPatched) + return; + + unsigned i; + for (i=0;ichange_table; + entry.kb_index=e->change_index; + entry.kb_value=e->old_val; + ioctl(hIn,KDSKBENT,&entry); + } + keyPatched=0; +} + +void TGKeyLinux::patchKeyMap() +{ + if (!canPatchKeyboard || keyPatched) + return; + + unsigned i; + for (i=0;ichange_table; + entry.kb_index=e->change_index; + entry.kb_value=e->new_val; + ioctl(hIn,KDSKBENT,&entry); + } + keyPatched=1; +} + +// Get the information needed to patch/unpatch +void TGKeyLinux::keyMapInit() +{ + unsigned i; + for (i=0; ichange_table; + entry.kb_index=e->change_index; + ioctl(hIn,KDGKBENT,&entry); + e->old_val=entry.kb_value; + entry.kb_table=e->old_table; + entry.kb_index=e->old_index; + ioctl(hIn,KDGKBENT,&entry); + e->new_val=entry.kb_value; + } +} + +void TGKeyLinux::hookVTSignals() +{ + if (vtHooked || dontPatchKeyboard || ourVT==-1) + return; + + // -------- Set up signal handlers to know about console switches + struct sigaction sig; + sigemptyset(&sig.sa_mask); + sigaddset(&sig.sa_mask,SIGUSR1); + sigaddset(&sig.sa_mask,SIGUSR2); + sig.sa_flags=SA_RESTART; + sigprocmask(SIG_BLOCK,&sig.sa_mask,NULL); // No switches now, we are not + // initialized yet + sig.sa_handler=releaseVTHandler; + sigaction(SIGUSR1,&sig,NULL); + sig.sa_handler=acquireVTHandler; + sigaction(SIGUSR2,&sig,NULL); + vtHooked=1; + + // -------- Tell our console to inform us about switches + if (ioctl(hIn,VT_SETMODE,&newVTMode)) + { + error=_("ioctl VT_SETMODE failed"); + return; + } + + sigprocmask(SIG_UNBLOCK,&sig.sa_mask,NULL); +} + +void TGKeyLinux::unHookVTSignals() +{ + if (!vtHooked || ourVT==-1) + return; + + // Make both signals to behave as default + struct sigaction sig; + sigemptyset(&sig.sa_mask); + sigaddset(&sig.sa_mask,SIGUSR1); + sigaddset(&sig.sa_mask,SIGUSR2); + sig.sa_flags=SA_RESTART; + sigprocmask(SIG_BLOCK,&sig.sa_mask,NULL); // No switches now, we are not + // initialized yet + sig.sa_handler=SIG_DFL; + sigaction(SIGUSR1,&sig,NULL); + sig.sa_handler=SIG_DFL; + sigaction(SIGUSR2,&sig,NULL); + + ioctl(hIn,VT_SETMODE,&oldVTMode); + + sigprocmask(SIG_UNBLOCK,&sig.sa_mask,NULL); + vtHooked=0; +} + +void TGKeyLinux::releaseVTHandler(int) +{ + unPatchKeyMap(); + TMouse::suspend(); + TScreenLinux::SuspendFont(); + ioctl(hIn,VT_RELDISP,1); +} + +void TGKeyLinux::acquireVTHandler(int) +{ + ioctl(hIn,VT_RELDISP,VT_ACKACQ); + ioctl(hIn,VT_WAITACTIVE,ourVT); + patchKeyMap(); + TMouse::resume(); + TScreenLinux::ResumeFont(); +} + +void TGKeyLinux::doHookAndPatch() +{ + if (!dontPatchKeyboard && canPatchKeyboard) + { + patchKeyMap(); + hookVTSignals(); + } +} + +void TGKeyLinux::doUnHookAndUnPatch() +{ + unPatchKeyMap(); + unHookVTSignals(); +} +/***************************************************************************** + End of keyboard patching and VT change hooking +*****************************************************************************/ + +void TGKeyLinux::SetKbdMapping(int version) +{ + if (version==linuxDisableKeyPatch) + { + dontPatchKeyboard=1; + doUnHookAndUnPatch(); + } + else if (version==linuxEnableKeyPatch) + { + dontPatchKeyboard=0; + doHookAndPatch(); + } + Mode=version; +} + +int TGKeyLinux::GetKbdMapping(int version) +{ + if (version==linuxDisableKeyPatch) + { + return dontPatchKeyboard; + } + else if (version==linuxEnableKeyPatch) + { + return !dontPatchKeyboard; + } + return 0; +} + +void TGKeyLinux::Init(int map) +{ + TGKey::Suspend =TGKeyLinux::Suspend; + TGKey::Resume =TGKeyLinux::Resume; + TGKey::kbhit =KbHit; + TGKey::clear =Clear; + TGKey::gkey =GKey; + TGKey::getShiftState =GetShiftState; + TGKey::fillTEvent =FillTEvent; + TGKey::SetKbdMapping =TGKeyLinux::SetKbdMapping; + TGKey::GetKbdMapping =TGKeyLinux::GetKbdMapping; + if (map==KOI8) + { + TGKey::SetCodePage(TVCodePage::KOI8r); + LOG("Using KOI8 keyboard table"); + } +} +#else // TVOSf_Linux + +#include +#include + +#endif // else TVOSf_Linux diff --git a/tvision/classes/linux/linuxmouse.cc b/tvision/classes/linux/linuxmouse.cc new file mode 100644 index 0000000..8871cf1 --- /dev/null +++ b/tvision/classes/linux/linuxmouse.cc @@ -0,0 +1,142 @@ +/***************************************************************************** + + Linux mouse routines. + Copyright (c) 1996-1998 by Robert Hoehne. + Copyright (c) 1999-2002 by Salvador E. Tropea (SET) + Covered by the GPL license. + +*****************************************************************************/ +#include + +#define Uses_stdlib +#define Uses_string +#define Uses_stdio +#define Uses_time +#define Uses_signal +#define Uses_TEvent +#define Uses_TEventQueue +#define Uses_TScreen +#include + +// I delay the check to generate as much dependencies as possible +#if defined(TVOSf_Linux) && defined(HAVE_GPM) + +//---------------- GPM version ----------------- + +#include +#include +#include +#include + +extern "C" { +#include +// Kernel 2.6.11 (from Gentoo) seems to need it: +// Not yet confirmed but doesn't interfere with 2.6.0 headers. +#include +} + +static +int SetUpGPMConnection() +{ + Gpm_Connect conn; + + conn.eventMask = ~0; /* I want all events */ + conn.defaultMask = 0; /* no default treatment */ + /* It doesn't report events from GPM when ALT or ALTGR are pressed. + I saw it in mc and my friends from BALUG, Ivan and Laszlo bugged me + about adding it. Was hyper-easy, no? (SET) */ + conn.maxMod = ~((1< max ? max : test; +} + +void THWMouseGPM::GetEvent(MouseEventType &me) +{ + Gpm_Event mev; + + me.buttons=TEventQueue::curMouse.buttons & ~(mbButton4 | mbButton5); + me.doubleClick=False; + if (!Gpm_Repeat(1) && (Gpm_GetEvent(&mev)==1)) + { + int b=mev.buttons; + if ((b & GPM_B_LEFT) && !(mev.type & GPM_UP)) + me.buttons|= mbLeftButton; + else + me.buttons&= ~mbLeftButton; + if ((b & GPM_B_RIGHT) && !(mev.type & GPM_UP)) + me.buttons|= mbRightButton; + else + me.buttons&= ~mbRightButton; + if (mev.wdy<0) + me.buttons=mbButton5; + else + if (mev.wdy>0) + me.buttons=mbButton4; + me.where.x=range(mev.x,0,TScreen::screenWidth-1); + me.where.y=range(mev.y,0,TScreen::screenHeight-1); + DrawMouse(me.where.x,me.where.y); + } + else + { + me.where.x=TEventQueue::curMouse.where.x; + me.where.y=TEventQueue::curMouse.where.y; + } +} + +void THWMouseGPM::Init() +{ + THWMouseUNIX::Init(); + THWMouse::Resume=Resume; + THWMouse::Suspend=Suspend; + THWMouse::GetEvent=GetEvent; +} + +THWMouseGPM::~THWMouseGPM() +{ +} + +#else // defined(TVOSf_Linux) && defined(HAVE_GPM) + +#if defined(TVOSf_Linux) + #include +#endif + +#include +#include +#include + +#endif // else defined(TVOSf_Linux) && defined(HAVE_GPM) diff --git a/tvision/classes/linux/linuxscr.cc b/tvision/classes/linux/linuxscr.cc new file mode 100644 index 0000000..2f2a69e --- /dev/null +++ b/tvision/classes/linux/linuxscr.cc @@ -0,0 +1,1958 @@ +/***************************************************************************** + + Linux screen routines. + Copyright (c) 1996-1998 by Robert Hoehne. + Copyright (c) 1999-2004 by Salvador E. Tropea (SET) + Covered by the GPL license. + + Important note: + This driver uses the G0 charset slot selecting the user defined map ACM. + If you load a font and their SFM map then you must load the propper ACM if +the font doesn't map 1 to 1 with the code page. If you don't understand it +please read the Console Tools documentation (html docs). Where each concept +is explained. + UseVCS=1 + UseMDA=1 + PatchKeys=1 + UseSecondaryFont=0 + AppCP + ScrCP + InpCP + LoadSecondFont + ScreenPalette + BrokenCursorShape + +*****************************************************************************/ +/* +ToDo: Find a way to enable SEPARATED_HANDLE without losing performance. How? + I know is possible, but not how, currently I must force the stream to + be unbuffered and the speed is 5 times inferior. Perhaps using an internal + buffer. + +ToDo: What if the user really have 512 characters? in this case the console have + only 8 colors. + +ToDo: What if the fonts geometry changes on the fly? Or in a console switch? + +ToDo: Add support for the ISO codepages as used by Linux, not just the standard ++ my frames. + +TODO: +TurboVision_screenOptions +See ToDo in the mouse initialization. + +When using no lat1 chars we had it: + else if (strchr(terminal, '-')!=NULL && // Have a modifier + !(strstr(terminal,"-c-")!=NULL || !strcmp(terminal+strlen(terminal)-2,"-c"))) // It isn't color modifier + { // Not some color variation, so most probably a different charset + use_pc_chars = 0; + TerminalType=GENER_TERMINAL; + } +This is not supported any more + +Important limitations: + +When using the escape sequences output (no VCS): +* We must set the charset to G1 and select G1 as transparent. We don't know +the original state so we just select G0 and use Graph map for G0. These are +the deafults after a console reset, but doesn't have to be the right +settings. + A similar thing happends with the option to display control characters. +* I don't know how to restore the console content. MC uses a separated +helper called cons.saver to do the trick. + In this new version of the driver I implemented something that saves +most of the information in the screen. I used an interesting thing in +Linux kernel, that's service 2 of TIOCLINUX, it can be used to select the +whole screen and then you can do a paste (like with the mouse), but this is +available only for real consoles and I don't know why when I restore such +a screen the mouse gets temporally invisible. + +When using VCS: +* The code to bypass mc and get the real console works, but the cons.saver +task of mc sometimes writes over the application. + +When GPM isn't available: +* The Linux kernel says: + * Code for xterm like mouse click reporting by Peter Orbaek 20-Jul-94 + * +But this doesn't work at all, if you enable mouse reporting (\E[?9h or +\E[?1000h) you get nothing. You'll get something when somebody calls +set_selection code using mode 16. This is far from usable. + +When trying to use a secondary font: +* The Linux kernel switchs to 8 colors mode. See comments in InitOnce(). +For this reason we don't enable it by default. + +When using unknown code pages: +* Looks like is common practice to load kernel maps that aren't really +encoded in Unicode, they are easier to create but they destroy any hope +to figure out what are representing. KOI8-R is an example, the SFM and +ACMs are in fact representing KOI8-R values and not Unicode. I got +information about systems mixing both: KOI8-R values + euro and others in +Unicode. I use a workaround for it, but this means most Linux systems +are just broken. +*/ +#include + +#define Uses_TScreen +#define Uses_TEvent +#define Uses_TDrawBuffer +#define Uses_TGKey +#define Uses_TVCodePage +#define Uses_string +#define Uses_ctype +#define Uses_signal +#include + +// I delay the check to generate as much dependencies as possible +#ifdef TVOSf_Linux + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef h386LowLevel + #if HAVE_OUTB_IN_SYS + #include + #else + #include + #endif +#endif + +// What a hell is that?! +#define force_redraw 0 + +#define ENTER_UTF8 "\e%G" +#define EXIT_UTF8 "\e%@" + +struct termios TScreenLinux::outTermiosOrig; +struct termios TScreenLinux::outTermiosNew; +const char *TScreenLinux::error=NULL; +char TScreenLinux::secondaryAvailable=0; +int TScreenLinux::mdaMemH=-1; +ushort *TScreenLinux::mdaMem=NULL; +int TScreenLinux::palette; +ushort *TScreenLinux::userBuffer=NULL; +unsigned TScreenLinux::userBufferSize; +int TScreenLinux::oldCol=-1, + TScreenLinux::oldBack=-1, + TScreenLinux::oldFore=-1; +CodePage TScreenLinux::unknownACM, + TScreenLinux::unknownSFM; +uchar TScreenLinux::canSetFonts=0, + TScreenLinux::primaryFontSet=0, + TScreenLinux::secondaryFontSet=0; +struct console_font_op + TScreenLinux::linuxFont, + TScreenLinux::ourFont; +int TScreenLinux::origCPScr, + TScreenLinux::origCPApp, + TScreenLinux::origCPInp, + TScreenLinux::origUTF8Mode, + TScreenLinux::font512Detected=0, + TScreenLinux::reduceTo8Colors=0; + +// Information about known font maps +struct stCodePageCk +{ + int codepage; + uint32 checksum; +}; + +// ISO 8859-2 fonts seems to have a lot of bugs: +// * The iso02.f16.psf file is useless, it have a map but doesn't have +// frames and wastes at least 17 glyphs. +// * The lat2-16.psf file is ok, but lack an unicode map. +// * The lat2u-16.psf file is usable, but doesn't help to display directly. +// It also have a bug, code 0x91 is N with accute but the unicode is missing +// in the map. + +// These are the SFM (Screen Font Map) maps +// This map explain which unicodes can be rendered by each character in the +// font. +struct stCodePageCk TScreenLinux::knownFonts[]= +{ + { TVCodePage::ISOLatin1Linux, 0x6E30159A }, + { TVCodePage::ISOLatin1uLinux, 0x2038159A }, + { TVCodePage::KOI8r, 0x207E10FA }, + { TVCodePage::ISOLatin2uLinux, 0xE50A3143 }, + { TVCodePage::ISOLatin2Sun, 0x92522C97 }, + { 0, 0 } +}; + +// These are the ACM (Application Charset Map) maps +// This map is used to determine what an 8 bits codes from the application +// means. Think about it: how the kernel knows if a file is encoded in +// latin 1, 2, koi8, etc? Simple: doesn't know, you must set this table. +// Important: ACM maps are usually strict, it means they define things as +// the standards says. This is quite annoying because you loose direct +// access to extra stuff defined in the controls range. Quite bad for VCS +// access so here I map the checksum to the equivalent Linux font. +struct stCodePageCk TScreenLinux::knownScreenMaps[]= +{ + { -1, 0xD53CF052 }, // Trivial map, what this mean? + //{ TVCodePage::ISOLatin1Linux, 0xD53CF052 }, // Trivial map, what this mean? + // It means the codes should pass unchanged, no remap on the fly. + // Hence 0xA0 is translated into unicode U+F0A0 which is then passed to the + // screen using the 0xA0 `glyph' of the font. + { TVCodePage::ISOLatin1Linux, 0xD62C0061 }, + { TVCodePage::ISOLatin2Linux, 0x5594183F }, + { TVCodePage::KOI8r, 0x4F463C4D }, + { TVCodePage::ISOLatin2eLinux, 0x72341867 }, // Euro hacked + { 0, 0 } +}; + +// Information about known languages +struct stCodePageLang +{ + const char *langs; + int codepage; +}; + +struct stCodePageLang TScreenLinux::langCodePages[]= +{ + { "ca,da,nl,et,fr,de,fi,is,it,no,pt,es,sv", TVCodePage::ISOLatin1Linux }, + { "hr,cs,hu,pl,ro,sk,sl", TVCodePage::ISOLatin2Linux }, + // ru_RU.KOI8-R is common, but not reliable according to Alexey Godin + { "ru", TVCodePage::KOI8r }, + { NULL, 0 } + //{ "el", TVCodePage::ISOGreek }, + ///{ "tr", TVCodePage::ISO9 }, + //hebrew iw_IL.ISO-8859-8 + //lithuanian lt_LT.ISO-8859-13 +}; + +// Structure for TIOCLINUX service 2 set selection, very kernel +// dependent. +typedef struct +{ + char service;// __attribute__((packed)); + ushort xs __attribute__((packed)); + ushort ys __attribute__((packed)); + ushort xe __attribute__((packed)); + ushort ye __attribute__((packed)); + ushort sel_mode __attribute__((packed)); +} setSel; + +static uint32 adler32(uint32 adler, const char *buf, unsigned len); + +TScreen *TV_LinuxDriverCheck() +{ + TScreenLinux *drv=new TScreenLinux(); + if (!TScreen::initialized) + { + delete drv; + return 0; + } + return drv; +} + +void TScreenLinux::sigWindowSizeChanged(int sig) +{ + // Set a flag because we don't know if we can do it right now + TScreenLinux::windowSizeChanged=1; + signal(sig,sigWindowSizeChanged); +} + +void TScreenLinux::Init(int mode) +{ + TScreen::Resume=Resume; + TScreen::Suspend=Suspend; + TScreen::setCrtData=defaultSetCrtData; + TScreen::setVideoMode=SetVideoMode; + TScreen::setVideoModeExt=SetVideoModeExt; + TScreen::getCharacter=GetCharacter; + TScreen::setCharacter=SetCharacter; + TScreen::System_p=System; + TDisplay::checkForWindowSize=CheckForWindowSize; + TScreen::getFontGeometry=GetFontGeometry; + TScreen::setFont_p=SetFont; + TScreen::restoreFonts=RestoreFonts; + + switch (mode) + { + case lnxInitVCSrw: + TScreen::setCharacters=SetCharactersVCS; + TScreen::getCharacters=GetCharactersVCS; + LOG("Using VCS r/w code"); + break; + case lnxInitVCSwo: + TScreen::setCharacters=SetCharactersVCS; + TScreen::getCharacters=defaultGetCharacters; + LOG("Using VCS write only code"); + break; + case lnxInitSimple: + TScreen::setCharacters=SetCharactersTerm; + TScreen::getCharacters=defaultGetCharacters; + LOG("Using escape sequences"); + break; + case lnxInitMDA: + TScreen::setCharacters=SetCharactersMDA; + TScreen::getCharacters=GetCharactersMDA; + LOG("Using MDA code"); + break; + } +} + + +const int firstTrySize=512; + +//#define DEBUG_CODEPAGE +#ifdef DEBUG_CODEPAGE +// This is the code to debug the code page detection +// The information generated by it is very useful and hence I keep the code +// here. +static int compareUni(const void *v1, const void *v2) +{ + struct unipair *p1=(struct unipair *)v1; + struct unipair *p2=(struct unipair *)v2; + if (p1->fontpos==p2->fontpos) + return (p1->unicode>p2->unicode)-(p1->unicodeunicode); + return (p1->fontpos>p2->fontpos)-(p1->fontposfontpos); +} + +int TScreenLinux::AnalyzeCodePage() +{ + ushort scrUniMap[E_TABSZ]; + int i,j; + + // GIO_UNIMAP: get unicode-to-font mapping from kernel + int success; + struct unimapdesc map; + map.entry_ct=firstTrySize; + map.entries=new struct unipair[firstTrySize]; + success= ioctl(hOut,GIO_UNIMAP,&map)!=-1; + if (!success && map.entry_ct>firstTrySize) + { + LOG("The starting size of " << firstTrySize << " wasn't enough, we need " << map.entry_ct); + delete[] map.entries; + map.entries=new struct unipair[map.entry_ct]; + success= ioctl(hOut,GIO_UNIMAP,&map)!=-1; + } + if (success) + { + fprintf(stderr,"The map have %d entries\n",map.entry_ct); + fprintf(stderr,"Raw information:\n"); + for (i=0; i 0x%04X\n",map.entries[i].fontpos,map.entries[i].unicode); + fprintf(stderr,"\n\nSorted information:\n"); + // Sort the entries + qsort(map.entries,map.entry_ct,sizeof(struct unipair),compareUni); + // Print all marking the entries that provides more than a code + for (i=0,j=0; i NO UNICODE\n",j++); + } + fprintf(stderr,"0x%02X => 0x%04X",map.entries[i].fontpos,map.entries[i].unicode); + if (i && map.entries[i-1].fontpos==map.entries[i].fontpos) + fputs(" *",stderr); + else + j++; + fputc('\n',stderr); + } + // Create a special list containing only one unicode by symbol + ushort UnicodeMap[256]; + memset(UnicodeMap,0xFF,256*sizeof(ushort)); + for (i=0; i255) + { + font512Detected++; + continue; + } + UnicodeMap[pos]=map.entries[i].unicode; + } + // Print this map + fputs("-------------\nSimplified map for checksum:\n",stderr); + for (i=0; i<256; i++) + if (UnicodeMap[i]==0xFFFF) + fprintf(stderr,"0x%02X NO UNICODE\n",i); + else + fprintf(stderr,"0x%02X U+%04x\n",i,UnicodeMap[i]); + // Compute a good check sum + uint32 cks=adler32(0,(char *)UnicodeMap,256*sizeof(ushort)); + fprintf(stderr,"Adler-32 checksum: 0x%08X\n",cks); + // Map it to internal codes + fputs("-------------\nInternal codes equivalent:\n",stderr); + for (i=0; i<256; i++) + { + int v=UnicodeMap[i]; + if (v==0xFFFF) + fputs(" 0,",stderr); + else + fprintf(stderr,"%3d,",TVCodePage::InternalCodeForUnicode(v)); + if (!((i+1) & 0xF)) + fputc('\n',stderr); + } + fputs("-------------\nWhat's missing:\n",stderr); + for (i=0; i<256; i++) + { + int v=UnicodeMap[i]; + if (v==0xFFFF) + continue; + if (TVCodePage::InternalCodeForUnicode(v)==-1) + fprintf(stderr,"%03d U+%04x\n",i,v); + } + fputs("-------------\n",stderr); + char SFMCreated=0; + for (i=0; knownFonts[i].codepage && knownFonts[i].checksum!=cks; i++); + if (knownFonts[i].codepage) + { + installedSFM=knownFonts[i].codepage; + fprintf(stderr,"Known code page detected %d\n",installedSFM); + } + else + { + fputs("Unknown code page, creating a custom one\n",stderr); + CreateSFMFromTable(UnicodeMap); + SFMCreated=1; + } + } + else + { + LOG("GIO_UNIMAP failed"); + // Something arbitrary + installedSFM=TVCodePage::ISOLatin1Linux; + } + + fputs("-------------\nGIO_UNISCRNMAP\n",stderr); + if (ioctl(hOut,GIO_UNISCRNMAP,scrUniMap)==-1) + { + LOG("GIO_UNISCRNMAP failed"); + delete[] map.entries; + return 0; + } + int isTrivial=1; + for (i=0; i U+%04x ",i,scrUniMap[i]); + if (i+0xF000!=scrUniMap[i] && i!=scrUniMap[i]) + { + isTrivial=0; + fputc('*',stderr); + } + fputc('\n',stderr); + } + fprintf(stderr,"This map %s trivial\n",isTrivial ? "IS" : "**ISN'T**"); + fputs("-------------\nInternal codes equivalent:\n",stderr); + for (i=0; i<256; i++) + { + int v=scrUniMap[i]; + if (v==0xFFFF) + fputs(" 0,",stderr); + else + fprintf(stderr,"%3d,",TVCodePage::InternalCodeForUnicode(v)); + if (!((i+1) & 0xF)) + fputc('\n',stderr); + } + // Compute a good check sum + uint32 cksS=adler32(0,(char *)scrUniMap,E_TABSZ*sizeof(ushort)); + fprintf(stderr,"Adler-32 checksum for screen map: 0x%08X\n",cksS); + for (i=0; knownScreenMaps[i].codepage && knownScreenMaps[i].checksum!=cksS; i++); + if (knownScreenMaps[i].codepage) + { + installedACM=knownScreenMaps[i].codepage; + if (installedACM==-1) + { + fprintf(stderr,"Using the same used for SFM\n"); + installedACM=installedSFM; + } + else + fprintf(stderr,"Known code page detected %d\n",installedACM); + } + else + { + fputs("Unknown code page, creating a new one\n",stderr); + // This a workaround for broken KOI8-R systems. + if (installedSFM==TVCodePage::KOI8r && scrUniMap[0xC0]==0xC0) + {// That's bogus, try to fix it + ushort *map=TVCodePage::GetTranslate(TVCodePage::KOI8r); + fputs("-------------\nACM is bogus, workaround:\n",stderr); + for (i=0; i<256; i++) + if (scrUniMap[i]<0x100) + { + scrUniMap[i]=TVCodePage::UnicodeForInternalCode(map[i]); + fprintf(stderr,"%3d => U+%04x\n",i,scrUniMap[i]); + } + else + fprintf(stderr,"%3d => U+%04x *\n",i,scrUniMap[i]); + } + CreateACMFromTable(scrUniMap); + } + + delete[] map.entries; + return 1; +} +#else +int TScreenLinux::AnalyzeCodePage() +{ + // Get the font unicode map (SFM) + // GIO_UNIMAP: get unicode-to-font mapping from kernel + int success; + struct unimapdesc map; + map.entry_ct=firstTrySize; + map.entries=new struct unipair[firstTrySize]; + success= ioctl(hOut,GIO_UNIMAP,&map)!=-1; + if (!success && map.entry_ct>firstTrySize) + { + LOG("The starting size of " << firstTrySize << " wasn't enough, we need " << map.entry_ct); + delete[] map.entries; + map.entries=new struct unipair[map.entry_ct]; + success= ioctl(hOut,GIO_UNIMAP,&map)!=-1; + } + if (!success) + { + delete[] map.entries; + return 0; + } + // Make a simplified version + int i; + ushort UnicodeMap[256]; + memset(UnicodeMap,0xFF,256*sizeof(ushort)); + for (i=0; i255) + { + font512Detected++; + continue; + } + if (map.entries[i].unicode. GPL. + setCursorPos(0,0); + // "\357\200\240" = U+F020 = `space' in Linux's straight-to-font zone + fputs("\357\200\240",fOut); + // Make sure it is printed + fflush(fOut); + getCursorPos(x,y); + // Get a single byte in UTF-8 and 3 bytes othewise + switch (x) + { + case 1: // UTF-8 + x=1; + LOG("UTF-8 mode detected"); + break; + case 3: // single-byte mode + x=0; + LOG("Single char mode detected"); + break; + default: // error + LOG("Error, can't determine UTF-8 state, column: " << x); + return -1; + } + + return x; +} + +void TScreenLinux::AvoidUTF8Mode() +{ + // Determine UTF-8 mode + origUTF8Mode=isInUTF8(); + if (origUTF8Mode==-1) + LOG("Error determining UTF-8 mode"); + // If necesary exit from it + if (origUTF8Mode==1) + fputs(EXIT_UTF8,fOut); +} + +int TScreenLinux::InitOnce() +{ + LOG("TScreenLinux::InitOnce"); + hOut=fileno(stdout); + // SET: Original code tried to open a tty at any cost, eg: if stdout was + // redirected it tried to open stdin's tty for writing. I don't see the + // point of such an effort and in fact crashes the library, so here I just + // explain to the user how to run the application in the right way. + if (!isatty(hOut)) + { + error=_("that's an interactive application, don't redirect stdout. " + "If you want to collect information redirect stderr like this: " + "program 2> file"); + return 1; + } + #ifdef SEPARATED_HANDLE + /* Testing a reopen */ + char *ttyName=ttyname(hOut); + if (!ttyName) + { + error=_("failed to get the name of the current terminal used for output"); + return 3; + } + fOut=fopen(ttyName,"w+b"); + if (!fOut) + { + error=_("failed to open the output terminal"); + return 4; + } + int fgs=fcntl(hOut,F_GETFL,0); + fcntl(fileno(fOut),F_SETFL,fgs); + + if (tcgetattr(hOut,&outTermiosOrig)) + { + error=_("can't get output terminal information"); + return 2; + } + hOut=fileno(fOut); + setvbuf(fOut,NULL,_IONBF,0); + #else + fOut=stdout; + + if (tcgetattr(hOut,&outTermiosOrig)) + { + error=_("can't get output terminal information"); + return 2; + } + #endif + + // Save cursor position, attributes and charset + fputs("\E7",fOut); + memcpy(&outTermiosNew,&outTermiosOrig,sizeof(outTermiosNew)); + outTermiosNew.c_oflag|=OPOST; + if (tcsetattr(hOut,TCSAFLUSH,&outTermiosNew)) + { + error=_("can't configure terminal mode"); + return 3; + } + + // Test the TIOCLINUX + int arg=6; + tioclinuxOK=(ioctl(hOut,TIOCLINUX,&arg)!=-1); + if (tioclinuxOK) + LOG("Linux Console IOCTL working"); + + if (tioclinuxOK) + {// We know the default colors, we can just hope they are the currently used + GetDisPaletteColors(0,16,OriginalPalette); + memcpy(ActualPalette,OriginalPalette,sizeof(ActualPalette)); + } + else + {// We don't know what palette is used so we can just setup our own palette + // Get the PC BIOS palette + defaultGetDisPaletteColors(0,16,ActualPalette); + // Now set it + SetDisPaletteColors(0,16,ActualPalette); + } + + // Look for user settings + optSearch("AppCP",forcedAppCP); + optSearch("ScrCP",forcedScrCP); + optSearch("InpCP",forcedInpCP); + // Try to figure out which code page is loaded + // Note: This is always needed for the defaults + if (!tioclinuxOK || !AnalyzeCodePage()) + { + GuessCodePageFromLANG(); + } + + #ifdef DEBUG_CODEPAGE + fprintf(stderr,"Using: AppCP: 0x%08lX ScrCP: 0x%08lX InpCP: 0x%08lX\n", + forcedAppCP!=-1 ? forcedAppCP : installedACM, + forcedScrCP!=-1 ? forcedScrCP : installedSFM, + forcedInpCP!=-1 ? forcedInpCP : installedACM); + fprintf(stderr,"Default: AppCP: 0x%08X ScrCP: 0x%08X InpCP: 0x%08X\n", + installedACM,installedSFM,installedACM); + #endif + + // User settings have more priority than detected settings + codePage=new TVCodePage(forcedAppCP!=-1 ? forcedAppCP : installedACM, + forcedScrCP!=-1 ? forcedScrCP : installedSFM, + forcedInpCP!=-1 ? forcedInpCP : installedACM); + SetDefaultCodePages(installedACM,installedSFM,installedACM); + if (tioclinuxOK && GetLinuxFontGeometry()) + { + canSetFonts=1; + linuxFont.data=ourFont.data=NULL; + linuxFont.flags=ourFont.flags=0; + } + + // Setup the driver properties. + // Our code page isn't fixed. + // We can change the palette (but can't restore it perfectly) + // We can also change the cursor shape. + // Even when Linux have a blanker we run in full screen so screen savers + // could be used with some sense. + // We support fonts, but we can change their geometry at will. + flags0=CanSetPalette | CodePageVar | UseScreenSaver; + // Some fbcon drivers fail to implement the cursor shape stuff. + // Using this variable we can inform it to the application. + long brokenCursorShapes=0; + optSearch("BrokenCursorShape",brokenCursorShapes); + if (!brokenCursorShapes) + flags0|=CursorShapes; + if (canSetFonts) + { + flags0|=CanSetBFont; + // When we use the secondary font Linux reduces the colors number to 8. + // This is good if the 512 chars are defining a big charset, but really + // bad if they are defining 2 different charsets. As we use it to define + // 2 charsets the impact is negative. So we enable it only if the user + // specifically asks for it. + long useSecondaryFont=0; + TScreen::optSearch("UseSecondaryFont",useSecondaryFont); + if (useSecondaryFont) + flags0|=CanSetSBFont; + } + if (font512Detected && !useSecondaryFont) + { + reduceTo8Colors=1; + LOG("Applying color reduction to 8 colors"); + } + + return 0; +} + + +void TScreenLinux::DetectVCS() +{ + /* + * This approach was suggested by: + * Martynas Kunigelis + * Date: Mon, 20 Jan 1997 15:55:14 +0000 (EET) + * Robert added code to bypass parents. + * SET added code to use write only devices. + */ + FILE *statfile; + char path[PATH_MAX]; + bool found_vcsa=false; + int pid=getpid(); + + sprintf(path,"/proc/%d/stat",pid); + /* If it fails lets see what terminal own our parent */ + while (!found_vcsa && + (pid!=-1) && + ((statfile=fopen(path,"r"))!=NULL)) + { + int dev; + int ppid; + + /* TTYs have 4 as major number */ + /* virtual consoles have minor numbers <= 63 */ + fscanf(statfile, "%*d %*s %*c %d %*d %*d %d", &ppid, &dev); + + LOG("ppid: " << ppid << " device: " << dev << "(" << (dev & 0xff) << ")"); + /* Be a little bit smart, we don't want to bypass X */ + /* X terminals are attached to 0 (unknown) terminal */ + if (dev==0) break; + + if ((dev & 0xff00)==0x0400 && (dev & 0xff)<=63) + { + LOG("virtual console detected"); + sprintf(path, "/dev/vcsa%d",dev & 0xff); + found_vcsa = true; + + // SET: Open it with two files, one for write and the other for read. + // Doing it the administrator can give write access to some users, + // but not read, that's very secure. + if ((vcsWfd=open(path,O_WRONLY))<0) + LOG("unable to open " << path << ", running in stdout mode"); + else + if ((vcsRfd=open(path,O_RDONLY))<0) + LOG("only write access to " << path); + } + fclose(statfile); + if (!found_vcsa && (pid!=ppid)) + { + pid=ppid; + sprintf(path,"/proc/%d/stat",pid); + } + else + pid=-1; + } +} +//--------------- End of VCS detection code + +void TScreenLinux::DetectSecondaryDisplay() +{ + //--------------- MDA initialization code + #ifdef h386LowLevel + secondaryAvailable=!ioperm(0x3b4,7,1); + if (secondaryAvailable) + { + unsigned char is_mda=(inb(0x3ba) & 0x70) >> 4; + is_mda=(is_mda==0) || (is_mda==1) || (is_mda==5); + if (is_mda) + { + mdaMemH=open("/dev/mem",O_RDWR); + if (mdaMemH!=-1) + { + mdaMem=(unsigned short *)mmap(NULL,80*25*2,PROT_READ|PROT_WRITE, + MAP_SHARED,mdaMemH,0xB0000); + } + else + secondaryAvailable=0; + } + else + secondaryAvailable=0; + } + #endif +} +//--------------- End of MDA initialization code + +TScreenLinux::TScreenLinux() +{ + // Identify the terminal, if that's linux or console go on. + char *terminal=getenv("TERM"); + if (!terminal || !(!strcmp(terminal,"console") || !strncmp(terminal,"linux",5))) + return; + + // Initialize terminal + if (InitOnce()) + { + fprintf(stderr,_("Error! %s"),error); + fprintf(stderr,"\r\n"); + return; + } + // Initialize keyboard + if (TGKeyLinux::InitOnce()) + { + tcsetattr(hOut,TCSAFLUSH,&outTermiosOrig); + fprintf(stderr,_("Error! %s"),TGKeyLinux::error); + fprintf(stderr,"\r\n"); + return; + } + // Ok, if we are here this driver is usable. + initialized=1; + if (dCB) dCB(); + + // Determine which subdriver to use (VCS R/W, VCS W or plain terminal) + { + long useVCS=1; + TScreen::optSearch("UseVCS",useVCS); + if (useVCS) + DetectVCS(); + } + { + long useMDA=1; + TScreen::optSearch("UseMDA",useMDA); + if (useMDA) + DetectSecondaryDisplay(); + } + + // Don't need special rights anymore + seteuid(getuid()); + setegid(getgid()); + + // Hook the signal generated when the size of the window changes + signal(SIGWINCH,sigWindowSizeChanged); + + // Initialize TDisplay using the detected capabilities + int mode=lnxInitSimple; + if (vcsWfd!=-1) + mode=vcsRfd!=-1 ? lnxInitVCSrw : lnxInitVCSwo; + TDisplayLinux::Init(mode); + Init(mode); + + TGKeyLinux::Init(installedSFM==TVCodePage::KOI8r ? TGKeyLinux::KOI8 : + TGKeyLinux::Default); + #ifdef HAVE_GPM + THWMouseGPM::Init(); + #endif + // Now we can do it + getCursorPos(oldCurX,oldCurY); + + if (mode==lnxInitVCSrw || mode==lnxInitVCSwo) + {// VCS access is assumed to be color + palette=PAL_HIGH; + TScreenLinux::screenMode=TScreenLinux::smCO80; + } + else + {// Start assuming linux or linux-c terminal (color) + palette=PAL_HIGH; + TScreenLinux::screenMode=TScreenLinux::smCO80; + // Now check if the user requested monochrome + if (strstr(terminal,"-m-")!=NULL || !strcmp(terminal+strlen(terminal)-2,"-m")) // linux-m + { // Mono mode, explicitly supress colors even if they are available + palette = PAL_MONO; + TScreen::screenMode=TScreen::smMono; + } + LOG((palette == PAL_HIGH ? "Using high palette" : "Using mono palette")); + } + + // User requested palette + if (palette==PAL_HIGH && parseUserPalette()) + setPaletteColors(0,16,UserStartPalette); + + cursorLines=startupCursor=getCursorType(); + screenMode=startupMode=getCrtMode(); + screenWidth =getCols(); + screenHeight=getRows(); + LOG("Screen size: " << (int)screenWidth << "," << (int)screenHeight); + screenBuffer=new ushort[screenWidth * screenHeight]; + SaveScreen(); + + AvoidUTF8Mode(); + + // Use G1 charset, set G1 to the loaded video fonts, print control chars. + // It means the kernel will send what we write directly to screen, just + // like in the VCSA case. + // How do I know the previous settings to restore them? I taked a look + // at the Linux kernel and couldn't find a way to get disp_ctrl. + if (!canWriteVCS()) + fputs("\e)K\xE",fOut); + // This is our state, save it + tcgetattr(hOut,&outTermiosNew); + suspended=0; + setCursorType(0); + + // Give a chance to the fonts callback + if (canSetFonts && frCB && GetLinuxFontGeometry()) + { + TScreenFont256 *font=frCB(0,linuxFont.width,linuxFont.height); + SetFont(1,font,0,NULL); + if (font) + DeleteArray(font->data); + delete font; + + #if 1 + long sec=0; + TScreenFont256 *font2=NULL; + if (optSearch("LoadSecondaryFont",sec) && sec) + { + font2=frCB(1,linuxFont.width,linuxFont.height); + if (font2) + { + SetFont(0,NULL,1,font2); + DeleteArray(font2->data); + delete font2; + } + } + #endif + } +} + +void TScreenLinux::Suspend() +{// Invalidate the knowledge about the current color of the terminal + oldCol=oldBack=oldFore=-1; + // Restore screen contents + RestoreScreen(); + // Restore the font + SuspendFont(); + // Restore the cursor shape + setCursorType(startupCursor); + // Restore cursor position, attributes and charset + // Here I just guess the previous state was G0 + no display control :-( + if (!canWriteVCS()) + fputs("\e)0\xF",fOut); + // Reset the palette, lamentably we don't know the original state :-( + if (tioclinuxOK) + // Go back to default colors we memorized + SetDisPaletteColors(0,16,OriginalPalette); + else + // Just reset to default palette (should be equivalent) + fputs("\E]R",fOut); + // Restore UTF-8 mode + if (origUTF8Mode==1) + fputs(ENTER_UTF8,fOut); + // Is that a Linux bug? Sometime \E8 works, others not. + fputs("\E8",fOut); + // Restore cursor position + SetCursorPos(oldCurX,oldCurY); + // Ensure the last command is executed + fflush(fOut); + // Restore console mode + tcsetattr(hOut,TCSAFLUSH,&outTermiosOrig); + LOG("TScreenLinux Suspend"); +} + +TScreenLinux::~TScreenLinux() +{ + // At this point we are not suspended + LOG("TScreenLinux Destructor"); +} + +void TScreenLinux::DeallocateResources() +{ + LOG("TScreenLinux DeallocateResources"); + // Now release allocated resources + if (screenBuffer) + { + DeleteArray(screenBuffer); + screenBuffer=NULL; + } + if (vcsWfd>=0) + close(vcsWfd); + if (vcsRfd>=0) + close(vcsRfd); + if (mdaMem) + { + munmap((char *)mdaMem,80*25*2); + mdaMem=NULL; + } + if (mdaMemH!=-1) + { + close(mdaMemH); + mdaMemH=-1; + } +} + +void TScreenLinux::Resume() +{ + // Save console mode + tcgetattr(hOut,&outTermiosOrig); + // Set our console mode + tcsetattr(hOut,TCSAFLUSH,&outTermiosNew); + // Save cursor position, attributes and charset + fputs("\E7",fOut); + getCursorPos(oldCurX,oldCurY); + AvoidUTF8Mode(); + // Restore our fonts + ResumeFont(); + if (tioclinuxOK) + // We know the default colors, we can just hope they are the currently used + GetDisPaletteColors(0,16,OriginalPalette); + SetDisPaletteColors(0,16,ActualPalette); + // When we set the video mode the cursor is hidded + ushort oldCursorLines=cursorLines; + // Check for video size change and save some state + setVideoMode(screenMode); + SaveScreen(); + // Set our cursor shape + setCursorType(oldCursorLines); + // Set the charset + if (!canWriteVCS()) + fputs("\e)K\xE",fOut); + LOG("TScreenLinux Resume"); +} + +/***************************************************************************** + Save/Restore screen +*****************************************************************************/ + +void TScreenLinux::SaveScreen() +{ + if (canReadVCS()) + { + userBufferSize=getCols()*getRows(); + userBuffer=(ushort *)realloc(userBuffer,userBufferSize*sizeof(ushort)); + getCharacters(0,userBuffer,userBufferSize); + } + else + {// First create an empty screen + // Fill the screenBuffer with spaces + unsigned i,size=screenWidth*screenHeight*2; + char *s=(char *)screenBuffer; + for (i=0; i> 4) & 7; + fore=s[i] & 15; + newfore=fore & 7; + if (back!=fore && back==newfore) + newfore=(newfore+1) & 7; + s[i]=newfore | (back<<4); + // The following is faster but you need a palette designed for 8 + // colors. I personally think people using UTF-8 for consoles + // must be ready to lose performance. + //s[i]&=0xF7; + } + } + + lseek(vcsWfd,dst*sizeof(ushort)+4,SEEK_SET); + #if TV_BIG_ENDIAN + { + unsigned i; + uchar *s=(uchar *)src; + uchar b[length*2]; + for (i=0; i0 && *old==*src) + { + dst++; + len--; + old++; + src++; + } + + /* remove unchanged characters from right to left */ + while (len>0 && *old_right==*src_right) + { + len--; + old_right--; + src_right--; + } + } + + /* write only middle changed characters */ + if (len>0) + writeBlock(dst,len,old,src); +} + +/* + * Writes a block of text. + */ + +void TScreenLinux::writeBlock(int dst, int len, ushort *old, ushort *src) +{ + int col=-1; + + fprintf(fOut,"\E[%d;%dH",dst/TScreenLinux::screenWidth+1,dst%TScreenLinux::screenWidth+1); + + while (len-->0) + { + int code =CLY_Low16(*src); + int newcol=CLY_High16(*src); + + *old++=*src++; + if (col!=newcol) /* change color ? */ + { + col=newcol; + if (palette==PAL_MONO) + { + if (col==0x0f) + fputs("\E[0;1m",fOut); // Bold + else + if (col==0x70) + fputs("\E[0;7m",fOut); // Reverse + else + fputs("\E[0m",fOut); // Normal + } + else + mapColor(col); + } + + /* SET: The following uses information I got from Linux kernel. + The file drivers/char/console.c have all the parsing of the + escape sequences. I put more information at the end of this + file. + Some characters are ever interpreted as control codes, here + I use a bitmap for them taked directly from the kernel. + The kernel code also sugest to use UTF-8 to print those + codes. + Note that Unicode 0xF000 | character means that character + must pass unchanged to the screen + */ + #define CTRL_ALWAYS 0x0800f501 /* Cannot be overridden by disp_ctrl */ + if (code<32 && ((CTRL_ALWAYS>>code) & 1)) + {/* This character can't be printed, we must use unicode */ + /* Enter UTF-8 and start constructing 0xF000 code */ + fputs(ENTER_UTF8 "\xEF\x80",fOut); + /* Set the last 6 bits */ + fputc(code | 0x80,fOut); + /* Escape UTF-8 */ + fputs(EXIT_UTF8,fOut); + } + else if (code==128+27) + {/* A specially evil code: Meta+ESC, it can't be printed */ + /* Just send Unicode 0xF09B to screen */ + fputs(ENTER_UTF8 "\xEF\x82\x9B" EXIT_UTF8,fOut); + } + else + /* The rest pass directly unchanged */ + fputc(code,fOut); + } + if (palette==PAL_MONO) + fputs("\E[0m",fOut); // Normal + + fprintf(fOut,"\E[%d;%dH",curY+1,curX+1); +} + +/* + * Converts colors from the large TV palette (16 foreground colors and + * 16 background colors) to ncurses small palette (8 foreground colors + * and 8 background colors). + */ + +void TScreenLinux::mapColor(int col) +{ + static char map[] = {0, 4, 2, 6, 1, 5, 3, 7}; + int back,fore; + + if (col==oldCol) + return; + oldCol=col; + back=(col >> 4) & 7; + fore=col & 15; + + if (reduceTo8Colors) + { + int newfore; + newfore=fore & 7; + if (back!=fore && back==newfore) + newfore=(newfore+1) & 7; + fore=newfore; + } + + #define SB set_a_background ? set_a_background : set_background + #define SF set_a_foreground ? set_a_foreground : set_foreground + + if (fore!=oldFore && back!=oldBack) + fprintf(fOut,"\E[%d;%d;%dm",fore>7 ? 1 : 22,30+map[fore & 7],40+map[back]); + else + { + if (fore!=oldFore) + fprintf(fOut,"\E[%d;%dm",fore>7 ? 1 : 22,30+map[fore & 7]); + else + fprintf(fOut,"\E[%dm",40+map[back]); + } + + oldFore = fore; + oldBack = back; + + #undef SB + #undef SF +} + +// SET: Call to an external program, optionally forking +int TScreenLinux::System(const char *command, pid_t *pidChild, int in, + int out, int err) +{ + if (!pidChild) + { + // If the caller asks for redirection replace the requested handles + if (in!=-1) + dup2(in,STDIN_FILENO); + if (out!=-1) + dup2(out,STDOUT_FILENO); + if (err!=-1) + dup2(err,STDERR_FILENO); + return system(command); + } + + pid_t cpid=fork(); + if (cpid==0) + {// Ok, we are the child + // I'm not sure about it, but is the best I have right now. + // Doing it we can kill this child and all the subprocesses + // it creates by killing the group. It also have an interesting + // effect that I must evaluate: By doing it this process lose + // the controlling terminal and won't be able to read/write + // to the parents console. I think that's good. + if (setsid()==-1) + _exit(127); + char *argv[4]; + + // If the caller asks for redirection replace the requested handles + if (in!=-1) + dup2(in,STDIN_FILENO); + if (out!=-1) + dup2(out,STDOUT_FILENO); + if (err!=-1) + dup2(err,STDERR_FILENO); + + // Note: execvp takes a char * const argument, but I think it should + // take a const char * + argv[0]=newStr(getenv("SHELL")); + if (!argv[0]) + argv[0]=newStr("/bin/sh"); + argv[1]=newStr("-c"); + argv[2]=newStr(command); + argv[3]=NULL; + execvp(argv[0],argv); + delete[] argv[0]; + delete[] argv[1]; + delete[] argv[2]; + // We get here only if exec failed + _exit(127); + } + if (cpid==-1) + {// Fork failed do it manually + *pidChild=0; + return system(command); + } + *pidChild=cpid; + return 0; +} + +/* The following is a modified version of Adler-32 checksum calculator: + * adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + The above mentioned header says: + + Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + This notice isn't removed, I clearly state the original author and that's + modified, so I think that's ok and compatible with GPL. + */ + +const uint32 Base=65521; /* largest prime smaller than 65536 */ +const unsigned nMax=5552; +/* nMax is the largest n such that 255n(n+1)/2 + (n+1)(Base-1) <= 2^32-1 */ + +#define DO1(buf,i) {s1+=buf[i]; s2+=s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +static +uint32 adler32(uint32 adler, const char *buf, unsigned len) +{ + uint32 s1=adler & 0xffff; + uint32 s2=(adler>>16) & 0xffff; + int k; + + if (buf==NULL) + return 1; + + while (len>0) + { + k=len=16) + { + DO16(buf); + buf+=16; + k-=16; + } + if (k) + do + { + s1+=*buf++; + s2+=s1; + } + while (--k); + s1%=Base; + s2%=Base; + } + return (s2 << 16) | s1; +} + +/***************************************************************************** + Fonts routines +*****************************************************************************/ + +int TScreenLinux::GetLinuxFontGeometry() +{ + memset(&linuxFont,0,sizeof(linuxFont)); + linuxFont.op=KD_FONT_OP_GET; + linuxFont.height=32; + linuxFont.width=16; + + int ret=ioctl(hOut,KDFONTOP,&linuxFont); + /*unsigned count=linuxFont.charcount; + linuxFont.charcount=0; + ioctl(hOut,KDFONTOP,&linuxFont); + linuxFont.charcount=count;*/ + + return ret>=0; +} + +int TScreenLinux::GetFontGeometry(unsigned &w, unsigned &h) +{ + if (!canSetFonts) return 0; + w=linuxFont.width; + h=linuxFont.height; + return 1; +} + +void TScreenLinux::FreeFontsMemory() +{ + if (linuxFont.data) + { + free(linuxFont.data); + linuxFont.data=NULL; + } + if (ourFont.data) + { + free(ourFont.data); + ourFont.data=NULL; + } +} + +int TScreenLinux::AllocateFontsMemory() +{ + unsigned bytes=32*((linuxFont.width+7)/8); + linuxFont.data=(uchar *)malloc(bytes*linuxFont.charcount); + ourFont.data=(uchar *)malloc(bytes*512); + return linuxFont.data && ourFont.data; +} + +int TScreenLinux::GetLinuxFont() +{ + linuxFont.op=KD_FONT_OP_GET; + return ioctl(hOut,KDFONTOP,&linuxFont)>=0; +} + +void TScreenLinux::ExpandFont(uchar *dest, TScreenFont256 *font) +{// No matters what's the height Linux uses 32 + int i; + unsigned bytes=32*((linuxFont.width+7)/8); + unsigned sizeOrig=font->h*((font->w+7)/8); + uchar *b=font->data; + memset(dest,0,bytes*256); + for (i=0; i<256; dest+=bytes, b+=sizeOrig, i++) + memcpy(dest,b,sizeOrig); +} + +int TScreenLinux::SetFont(int changeP, TScreenFont256 *fontP, + int changeS, TScreenFont256 *fontS, + int fontCP, int appCP) +{ + if (!canSetFonts) return 0; + if (!changeP && !changeS) return 1; + // Check for restore fonts + if (changeP && !fontP && ((!changeS && !secondaryFontSet) || (changeS && !fontS))) + {// Restore Linux font + linuxFont.op=KD_FONT_OP_SET; + int ret=ioctl(hOut,KDFONTOP,&linuxFont)>=0; + // We no longer have a font loaded + FreeFontsMemory(); + secondaryFontSet=primaryFontSet=0; + if (fontCP!=-1) + { + if (appCP==-1) + TVCodePage::SetScreenCodePage(fontCP); + else + TVCodePage::SetCodePage(appCP,fontCP,-1); + } + return ret; + } + // Solve the sizes + unsigned wP=linuxFont.width,hP=linuxFont.height, + wS=linuxFont.width,hS=linuxFont.height; + int newP=changeP && fontP; + if (newP) + { + wP=fontP->w; + hP=fontP->h; + } + int newS=changeS && fontS; + if (newS) + { + wS=fontS->w; + hS=fontS->h; + } + if (wP!=wS || hP!=hS) return 0; + // Check if the size is in the range + if (wP!=linuxFont.width || hP!=linuxFont.height) + return 0; + + // We are about changing the font, we must be sure that Linux font is saved + if ((newS || newP) && !primaryFontSet && !secondaryFontSet) + { + if (!AllocateFontsMemory() || !GetLinuxFont()) + return 0; + ourFont.width=linuxFont.width; + ourFont.height=linuxFont.height; + } + + // Change the requested fonts + unsigned bytes=32*((linuxFont.width+7)/8); + uchar newSecondaryFontSet=secondaryFontSet, + newPrimaryFontSet=primaryFontSet; + if (changeP) + { + if (!secondaryFontSet) + { // P but not S + ourFont.charcount=256; + } + if (!primaryFontSet) + TVCodePage::GetCodePages(origCPApp,origCPScr,origCPInp); + if (fontP) + { + ExpandFont(ourFont.data,fontP); + newPrimaryFontSet=1; + } + else + { + // Use Linux font as primary + memcpy(ourFont.data,linuxFont.data,256*bytes); + newPrimaryFontSet=0; + } + } + if (changeS) + { + if (fontS) + { + ourFont.charcount=512; + if (!primaryFontSet) + memcpy(ourFont.data,linuxFont.data,256*bytes); + ExpandFont(ourFont.data+256*bytes,fontS); + newSecondaryFontSet=1; + } + else + { + if (linuxFont.charcount==512) + { + ourFont.charcount=512; + memcpy(ourFont.data+256*bytes,linuxFont.data+256*bytes,256*bytes); + } + else + ourFont.charcount=256; + newSecondaryFontSet=0; + } + } + ourFont.op=KD_FONT_OP_SET; + if (ioctl(hOut,KDFONTOP,&ourFont)<0) return 0; + primaryFontSet=newPrimaryFontSet; + secondaryFontSet=newSecondaryFontSet; + + if (changeP && fontCP!=-1) + { + if (appCP==-1) + TVCodePage::SetScreenCodePage(fontCP); + else + TVCodePage::SetCodePage(appCP,fontCP,-1); + } + return 1; +} + +void TScreenLinux::RestoreFonts() +{ + if (!primaryFontSet && !secondaryFontSet) + return; // Protection + SetFont(1,NULL,1,NULL,origCPScr,origCPApp); +} + +void TScreenLinux::SuspendFont() +{ + if (primaryFontSet || secondaryFontSet) + {// Set the Linux fonts again + linuxFont.op=KD_FONT_OP_SET; + ioctl(hOut,KDFONTOP,&linuxFont); + // Free their memory, we will memorize them again in the resume + free(linuxFont.data); + linuxFont.data=NULL; + } +} + +void TScreenLinux::ResumeFont() +{ + if (primaryFontSet || secondaryFontSet) + {// Get Linux fonts info + GetLinuxFontGeometry(); + // Allocate memory for them + unsigned bytes=32*((linuxFont.width+7)/8); + linuxFont.data=(uchar *)malloc(bytes*linuxFont.charcount); + // Get them + GetLinuxFont(); + // Now restore our fonts + ourFont.op=KD_FONT_OP_SET; + ioctl(hOut,KDFONTOP,&ourFont); + } +} + + +#else // TVOSf_Linux + +#include +#include +#include +#include + +#endif // else TVOSf_Linux +/***************************************************************************** + + This code was in the constructor and commented, it could help in the + future. + * ESC ] Ps ND string NP + * ND can be any non-digit Character (it's discarded) + * NP can be any non-printing Character (it's discarded) + * string can be any ASCII printable string (max 511 characters) + * Ps = 0 -> use string as a new icon name and title + * Ps = 1 -> use string is a new icon name only + * Ps = 2 -> use string is a new title only + * Ps = 46 -> use string as a new log file name + if (getenv("DISPLAY") != NULL) cout << "\033]2;TurboVision\007"; + +SET: + Here is some information about the Linux console. I got it from the kernel +sources, they says that's VT102: + +\e(n +Sets the G0 character set. The terminal have 2 character sets, that's the +commonly used. The n value can be: +0 Graphics (DEC ISO 2022) +B Latin 1 (ISO 8859-1) +U IBM PC +K User + +\e)n +It sets what character set is used for G1. That's the alternative charset. + +\xF +Select the G0 charset, don't display control characters. After it all printed +values are in G0 charset. + +\xE +Select the G1 charset, display control characters. After it all printed +values are in G1 charset. Usually it selects the graphics chars. + +\e[10m +Selects G0 or G1 (depending of the last selection done by \xF or \xE), don't +display control characters, don't force the bit 7 to 1. + +\e[11m +Selects IBM PC, display control characters, don't force the bit 7 to 1. + +\e[12m +Selects IBM PC, display control characters, force the bit 7 to 1. + +Description of the available charsets for Linux: +1) Graphics (0): + This is latin 1 charset with some changes in the range 32-126. This charset +is called VT100. Here are the codes that differ from ASCII: + 43(+): Right arrow 109(m): simple lower left corner + 44(,): Left arrow 110(n): simple intersection + 45(-): Up arrow 111(o): first line filled + 46(.): Down arrow 112(p): 1/4 of height line filled + 48(0): Filled block 113(q): 1/2 of height line filled + 95(_): Non break space 114(r): 3/4 of height line filled + 96(`): Diamond 115(s): last line filled + 97(a): 50% filled. 116(t): simple vertical with right int. + 98(b): HT 117(u): simple vertical with left int. + 99(c): FF 118(v): simple horiz. with upper int. +100(d): CR 119(w): simple horiz. with lower int. +101(e): LF 120(x): simple vertical +102(f): Degree 121(y): <= +103(g): +/- 122(z): >= +104(h): 25% filled. 123({): pi +105(i): VT 124(|): /= +106(j): simple lower right corner 125(}): pounds +107(k): simple upper right corner 126(~): middle point +108(l): simple upper left corner + +2) Latin 1 (B): + That's pure ISO 8859-1 mapping. It means 128-159 have undefined shapes. + +3) IBM PC (U): + That's PC 437 code page. Some characters are undefined if the currently +loaded fonts doesn't have it. + +4) User defined (K): + That's just "send to screen this code". So it depends on the loaded fonts. + + Note that 0-31 and 127 are considered control characters and will be printed +only if this is enabled. Some characters aren't printed even if that's +enabled, that's because if they are printed you can't use the terminal +(imagine disabling ESC ;-). + Also: 128+27 will never be printed. + + In Eterm only Graphics (VT100) and Latin 1 are supported. + In xterm a simple program have troubles to print anything above 127. + +*****************************************************************************/ diff --git a/tvision/classes/ofpstrea.cc b/tvision/classes/ofpstrea.cc new file mode 100644 index 0000000..a50dcf6 --- /dev/null +++ b/tvision/classes/ofpstrea.cc @@ -0,0 +1,55 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Vadim Beloborodov to be used on WIN32 console. +Modified to compile with gcc v3.x by Salvador E. Tropea, with the help of +Andris Pavenis and Christoph Bauer. + + * + * + */ + +#define Uses_string +#define Uses_fpbase +#define Uses_ofpstream +#define Uses_IOS_BIN +#include + +UsingNamespaceStd + +ofpstream::ofpstream() +{ +} + +ofpstream::ofpstream( const char* name, CLY_OpenModeT omode, int prot ) : + fpbase( name, omode | CLY_IOSOut | CLY_IOSBin, prot ) +{ +} + +ofpstream::ofpstream( int f ) : fpbase( f ) +{ +} + +ofpstream::ofpstream(int f, char* b, int len) : fpbase(f, b, len) +{ +} + +ofpstream::~ofpstream() +{ +} + +CLY_filebuf *ofpstream::rdbuf() +{ + return fpbase::rdbuf(); +} + +void ofpstream::open( const char *name, CLY_OpenModeT omode, int prot ) +{ + fpbase::open( name, omode | CLY_IOSOut | CLY_IOSBin, prot ); +} + diff --git a/tvision/classes/opstream.cc b/tvision/classes/opstream.cc new file mode 100644 index 0000000..3da72a0 --- /dev/null +++ b/tvision/classes/opstream.cc @@ -0,0 +1,237 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + * + * Modified by Robert H”hne to be used for RHIDE. + * Modified by Vadim Beloborodov to be used on WIN32 console + * + * SET: Moved the standard headers here because according to DJ + * they can inconditionally declare symbols like NULL. + * Added members for platform indepent writes. Started with a JASC + * modification. Added: write8, write16, write32, write64, writeShort, + * writeInt and writeLong. + * + * Modified to compile with gcc v3.x by Salvador E. Tropea, with the help of + * Andris Pavenis and Christoph Bauer. + * + */ +#define Uses_stdio // fprintf in writeData +#define Uses_string +#define Uses_PubStreamBuf +#define Uses_TStreamable +#define Uses_TStreamableClass +#define Uses_TPWrittenObjects +#define Uses_TStreamableTypes +#define Uses_pstream +#define Uses_opstream +#define Uses_TPWrittenObjects +#include + +opstream::opstream() +{ + objs = new TPWrittenObjects(); +} + +opstream::opstream( CLY_streambuf * sb ) +{ + objs = new TPWrittenObjects(); + pstream::init( sb ); +} + +opstream::~opstream() +{ + CLY_destroy(objs); +} + +opstream& opstream::seekp( CLY_StreamPosT pos ) +{ + objs->freeAll(); + bp->CLY_PubSeekOff( pos, CLY_IOSBeg ); + return *this; +} + +opstream& opstream::seekp( CLY_StreamOffT pos, CLY_IOSSeekDir dir ) +{ + objs->freeAll(); + bp->CLY_PubSeekOff( pos, dir ); + return *this; +} + +CLY_StreamPosT opstream::tellp() +{ + return bp->CLY_PubSeekOff( 0, CLY_IOSCur, CLY_IOSOut ); +} + +opstream& opstream::flush() +{ + bp->CLY_PubSync(); + return *this; +} + +void opstream::writeByte( uchar ch ) +{ + bp->sputc( ch ); +} + +void opstream::writeBytes( const void *data, size_t sz ) +{ + bp->sputn( (char *)data, sz ); +} + +/* + * writeShort, writeInt and writeLong: + * These are platform dependent, writes the size and byte order of the native + * platform. + * Created by SET to be compatible with original code and V. Bugrov ideas. + */ + +#define DefineWriteDep(name,type)\ +void opstream::write##name(type val)\ +{\ + bp->sputn((char *)&val,sizeof(type));\ +} +DefineWriteDep(Short,ushort); +DefineWriteDep(Int,uint); +DefineWriteDep(Long,ulong); + +/* + * write16, write32 and write64: + * These are platform independent, writes a fixed size in little endian order + * and if the platform is big endian swaps bytes. + * Created by SET to be compatible with original code and JASC + V. Bugrov + * ideas. + */ + +#ifdef TV_BIG_ENDIAN +#define Swap(a,b) t=v[a]; v[a]=v[b]; v[b]=t + +static inline +void Swap16(char *v) +{ + char t; + Swap(0,1); +} + +static inline +void Swap32(char *v) +{ + char t; + Swap(0,3); + Swap(1,2); +} + +static inline +void Swap64(char *v) +{ + char t; + Swap(0,7); + Swap(1,6); + Swap(2,5); + Swap(3,4); +} +#else +static inline +void Swap16(char *) {} +static inline +void Swap32(char *) {} +static inline +void Swap64(char *) {} +#endif + +#define DefineWrite(name,type)\ +void opstream::write##name(type val)\ +{\ + Swap##name((char *)&val);\ + bp->sputn((char *)&val,sizeof(type));\ +} +DefineWrite(16,uint16); +DefineWrite(32,uint32); +DefineWrite(64,uint64); + +void opstream::writeString( const char *str ) +{ + if( str == 0 ) + { + writeByte( 0xFF ); + return; + } + int len = strlen( str ); + if (len > 0xfd) + { + writeByte( 0xfe ); + write32(len); + } + else + { + writeByte( (uchar)len ); + } + writeBytes( str, len ); +} + +/* Operators moved to headers by JASC */ + +CLY_EXPORT opstream& operator << ( opstream& ps, TStreamable& t ) +{ + ps.writePrefix( t ); + ps.writeData( t ); + ps.writeSuffix( t ); + return ps; +} + +CLY_EXPORT opstream& operator << ( opstream& ps, TStreamable *t ) +{ + P_id_type index; + if( t == 0 ) + ps.writeByte( pstream::ptNull ); + else if( (index = ps.find( t )) != P_id_notFound ) + { + ps.writeByte( pstream::ptIndexed ); + ps.writeWord( index ); + } + else + { + ps.writeByte( pstream::ptObject ); + ps << *t; + } + return ps; +} + +void opstream::writePrefix( const TStreamable& t ) +{ + writeByte( '[' ); + writeString( t.streamableName() ); +} + + +void opstream::writeData( TStreamable& t ) +{ + if( types->lookup( t.streamableName() ) == 0 ) + { + fprintf(stderr,_("type not registered: %s\n"),t.streamableName()); + error( peNotRegistered, t ); + } + else + { + registerObject( &t ); + t.write( *this ); + } +} + +void opstream::writeSuffix( const TStreamable& ) +{ + writeByte( ']' ); +} + +P_id_type opstream::find( const void *adr ) +{ + return objs->find( adr ); +} + +void opstream::registerObject( const void *adr ) +{ + objs->registerObject( adr ); +} + diff --git a/tvision/classes/osclipboard.cc b/tvision/classes/osclipboard.cc new file mode 100644 index 0000000..67aa106 --- /dev/null +++ b/tvision/classes/osclipboard.cc @@ -0,0 +1,34 @@ +/**[txh]******************************************************************** + + Copyright (c) 2002 by Salvador E. Tropea (SET) + Covered by the GPL license. + + Header: TVOSClipboard + Module: OS Clipboard + Comments: + OS independent clipboard system class. Uses to access the OS clipboard.@* + It was created to abstract the X11 and Windows clipboards. + +***************************************************************************/ + +#define Uses_TVOSClipboard +#include + +const char *TVOSClipboard::name="None"; +int TVOSClipboard::available=0; +int (*TVOSClipboard::copy)(int id, const char *buffer, unsigned len)=NULL; +char *(*TVOSClipboard::paste)(int id, unsigned &length)=NULL; +void (*TVOSClipboard::destroy)()=NULL; +int TVOSClipboard::error=0; +int TVOSClipboard::errors=0; +const char **TVOSClipboard::nameErrors=NULL; + + +const char *TVOSClipboard::getError() +{ + if (error>errors || !error || !nameErrors) + return NULL; + return _(nameErrors[error]); +} + + diff --git a/tvision/classes/pstream.cc b/tvision/classes/pstream.cc new file mode 100644 index 0000000..4286d69 --- /dev/null +++ b/tvision/classes/pstream.cc @@ -0,0 +1,132 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified to compile with gcc v3.x by Salvador E. Tropea, with the help of +Andris Pavenis and Christoph Bauer. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#include + +#define Uses_TStreamableTypes +#define Uses_TStreamableClass +#define Uses_TStreamable +#define Uses_pstream +#include + +UsingNamespaceStd + +pstream::pstream( CLY_streambuf *sb ) +{ + init( sb ); +} + +pstream::~pstream() +{ +} + +void pstream::deInitTypes(void) +{ + if (types) + delete types; +} + +// The following call to new is overloaded, avoid +// using MSS for it. +#include + +void pstream::initTypes() +{ + if (!types) + { + types=new TStreamableTypes; + atexit(pstream::deInitTypes); + } +} + +#include + +int pstream::rdstate() const +{ + return state; +} + +int pstream::eof() const +{ + return state & CLY_IOSEOFBit; +} + +int pstream::fail() const +{ + return state & (CLY_IOSFailBit | CLY_IOSBadBit); +} + +int pstream::bad() const +{ + return state & (CLY_IOSBadBit); +} + +int pstream::good() const +{ + return state == 0; +} + +void pstream::clear( int i ) +{ + state = (i & 0xFF); +} + +void pstream::registerType( TStreamableClass *ts ) +{ + types->registerType( ts ); +} + +pstream::operator void *() const +{ + return fail() ? 0 : (void *)this; +} + +int pstream::operator! () const +{ + return fail(); +} + +CLY_streambuf * pstream::rdbuf() const +{ + return bp; +} + +pstream::pstream() +{ +} + +void pstream::error( StreamableError ) +{ + abort(); +} + +void pstream::error( StreamableError, const TStreamable& ) +{ + abort(); +} + +void pstream::init( CLY_streambuf *sbp ) +{ + state = 0; + bp = sbp; +} + +void pstream::setstate( int b ) +{ + state |= (b&0xFF); +} + +TStreamableTypes * pstream::types; diff --git a/tvision/classes/qnx4/qnx4dis.cc b/tvision/classes/qnx4/qnx4dis.cc new file mode 100644 index 0000000..b3e4156 --- /dev/null +++ b/tvision/classes/qnx4/qnx4dis.cc @@ -0,0 +1,230 @@ +/* QNX 4 screen routines source. + Copyright (c) 1998-2003 by Mike Gorchak + Covered by the BSD license. */ + +#include + +#define Uses_stdio +#define Uses_stdlib +#define Uses_unistd +#define Uses_TDisplay +#define Uses_TScreen +#define Uses_string +#define Uses_ioctl +#define Uses_signal + +#include + +// I delay the check to generate as much dependencies as possible +#if defined(TVOS_UNIX) && defined(TVOSf_QNX4) + +#include + +#include + +extern "C" +{ + #include + #include +} + +#include + +ushort TDisplayQNX4::CursorLastX=0xFFFF; +ushort TDisplayQNX4::CursorLastY=0xFFFF; +ushort TDisplayQNX4::CursorShapeStart=85; +ushort TDisplayQNX4::CursorShapeEnd=100; +ushort TDisplayQNX4::ConsoleResizing=0; +ushort TDisplayQNX4::IgnoreConsoleResizing=0; +char TDisplayQNX4::ConsoleMode=1; +struct _VideoModes TDisplayQNX4::modes[NUM_MODES]= +{ + {smCO80x25, 80, 25}, {smCO80x28, 80, 28}, {smCO80x35, 80, 35}, + {smCO80x40, 80, 40}, {smCO80x43, 80, 43}, {smCO80x50, 80, 50}, + {smCO80x30, 80, 30}, {smCO80x34, 80, 34}, {smCO90x30, 90, 30}, + {smCO90x34, 90, 34}, {smCO94x30, 94, 30}, {smCO94x34, 94, 34}, + {smCO82x25, 82, 25}, {smCO80x60, 80, 60}, {smCO132x25, 132, 25}, + {smCO132x43, 132, 34}, {smCO132x50, 132, 50}, {smCO132x60, 132, 60} +}; + +TDisplayQNX4::~TDisplayQNX4() +{ +} + +void TDisplayQNX4::Init() +{ + TDisplay::setCursorPos=SetCursorPos; + TDisplay::getCursorPos=GetCursorPos; + TDisplay::getCursorShape=GetCursorShape; + TDisplay::setCursorShape=SetCursorShape; + TDisplay::getRows=GetRows; + TDisplay::getCols=GetCols; + TDisplay::getCrtMode=GetCrtMode; + TDisplay::setCrtMode=SetCrtMode; + TDisplay::setCrtModeRes_p=SetCrtModeRes; + TDisplay::setCrtModeExt=SetCrtModeExt; + TDisplay::checkForWindowSize=CheckForWindowSize; +} + +void TDisplayQNX4::SetCursorPos(unsigned x, unsigned y) +{ + CursorLastX=x; + CursorLastY=y; + term_cur(y, x); + term_flush(); +} + +void TDisplayQNX4::GetCursorPos(unsigned &x, unsigned &y) +{ + x=CursorLastX; + y=CursorLastY; +} + +void TDisplayQNX4::SetCursorShape(unsigned start, unsigned end) +{ + char* CursorShapeControlString; + + if (start>=end) + { + CursorShapeControlString=cursor_invisible; + } + else + { + if (end-start>15) + { + CursorShapeControlString=cursor_visible; + } + else + { + CursorShapeControlString=cursor_normal; + } + } + + __putp(CursorShapeControlString); + term_flush(); + + CursorShapeStart=start; + CursorShapeEnd=end; +} + +void TDisplayQNX4::GetCursorShape(unsigned &start, unsigned &end) +{ + start=CursorShapeStart; + end=CursorShapeEnd; +} + +ushort TDisplayQNX4::GetRows() +{ + struct winsize win; + + ioctl(fileno(stdin), TIOCGWINSZ, &win); + + return win.ws_row; +} + +ushort TDisplayQNX4::GetCols() +{ + struct winsize win; + + ioctl(fileno(stdin), TIOCGWINSZ, &win); + + return win.ws_col; +} + +ushort TDisplayQNX4::GetCrtMode() +{ + int x=GetCols(); + int y=GetRows(); + + for (int i=0; i>8) & 0x000000FFUL); + win.ws_row=char(mode & 0x000000FFUL); + win.ws_xpixel=0; + win.ws_ypixel=0; + + if (mode!=0xFFFF) + { + IgnoreConsoleResizing=1; + if (ioctl(fileno(stdin), TIOCSWINSZ, &win)!=-1) + { + term_relearn_size(); + } + } +} + +int TDisplayQNX4::SetCrtModeRes(unsigned w, unsigned h, int fW, int fH) +{ + struct winsize win; + + win.ws_col=w; + win.ws_row=h; + win.ws_xpixel=0; + win.ws_ypixel=0; + + IgnoreConsoleResizing=1; + if (ioctl(fileno(stdin), TIOCSWINSZ, &win)!=-1) + { + term_relearn_size(); + return 1; + } + + return 0; +} + +void TDisplayQNX4::SetCrtModeExt(char* mode) +{ + IgnoreConsoleResizing=1; + system(mode); + term_relearn_size(); +} + +int TDisplayQNX4::CheckForWindowSize(void) +{ + int ret=0; + + if (ConsoleResizing) + { + if (IgnoreConsoleResizing) + { + ret=0; + ConsoleResizing=0; + IgnoreConsoleResizing=0; + } + else + { + ret=1; + ConsoleResizing=0; + } + } + + return ret; +} + +const char* TDisplayQNX4::GetWindowTitle(void) +{ + return NULL; +} + +int TDisplayQNX4::SetWindowTitle(const char* name) +{ + return 0; +} + +#else +// Here to generate the dependencies in RHIDE +#include +#endif // TVOS_UNIX && TVOSf_QNX4 diff --git a/tvision/classes/qnx4/qnx4key.cc b/tvision/classes/qnx4/qnx4key.cc new file mode 100644 index 0000000..aa7c3fb --- /dev/null +++ b/tvision/classes/qnx4/qnx4key.cc @@ -0,0 +1,288 @@ +/* QNX 4 screen routines source. + Copyright (c) 1998-2003 by Mike Gorchak + Covered by the BSD license. */ + +#include + +#define Uses_stdio +#define Uses_unistd +#define Uses_ctype +#define Uses_stdlib +#define Uses_TEvent +#define Uses_TGKey +#define Uses_TKeys +#define Uses_TKeys_Extended +#define Uses_TDisplay +#define Uses_TScreen +#define Uses_string +#include + +// I delay the check to generate as much dependencies as possible +#if defined(TVOS_UNIX) && defined(TVOSf_QNX4) + +#include + +#include +#include + +extern "C" +{ + #include + #include + #include + #include +} + +struct termios TGKeyQNX4::saved_attributes; + +ushort TGKeyQNX4::keytranslatetable[QNX4_KEYTABLE_SIZE]= +{ + 0x0000, kbCtA, kbCtB, kbCtC, kbCtD, kbCtE, kbCtF, kbCtG, /* 0x000-0x007 */ // Low translation table. + kbCtH, kbTab, kbCtJ, kbCtK, kbCtL, kbEnter, kbCtN, kbCtO, /* 0x008-0x00F */ + kbCtP, kbCtQ, kbCtR, kbCtS, kbCtT, kbCtU, kbCtV, kbCtW, /* 0x010-0x017 */ + kbCtX, kbCtY, kbCtZ, kbEsc, 0x0000, kbCtOpenBrace, kbCt6, kbCtMinus, /* 0x018-0x01F */ + kbSpace, kbAdmid, kbDobleQuote, kbNumeral, kbDolar, kbPercent, kbAmper, kbQuote, /* 0x020-0x027 */ + kbOpenPar, kbClosePar, kbAsterisk, kbPlus, kbComma, kbMinus, kbStop, kbSlash, /* 0x028-0x02F */ + kb0, kb1, kb2, kb3, kb4, kb5, kb6, kb7, /* 0x030-0x037 */ + kb8, kb9, kbDoubleDot, kbColon, kbLessThan, kbEqual, kbGreaterThan, kbQuestion, /* 0x038-0x03F */ + kbA_Roba, kbShA, kbShB, kbShC, kbShD, kbShE, kbShF, kbShG, /* 0x040-0x047 */ + kbShH, kbShI, kbShJ, kbShK, kbShL, kbShM, kbShN, kbShO, /* 0x048-0x04F */ + kbShP, kbShQ, kbShR, kbShS, kbShT, kbShU, kbShV, kbShW, /* 0x050-0x057 */ + kbShX, kbShY, kbShZ, kbOpenBrace, kbBackSlash, kbCloseBrace, kbCaret, kbUnderLine, /* 0x058-0x05F */ + kbQuote, kbA, kbB, kbC, kbD, kbE, kbF, kbG, /* 0x060-0x067 */ + kbH, kbI, kbJ, kbK, kbL, kbM, kbN, kbO, /* 0x068-0x06F */ + kbP, kbQ, kbR, kbS, kbT, kbU, kbV, kbW, /* 0x070-0x077 */ + kbX, kbY, kbZ, kbOpenCurly, kbOr, kbCloseCurly, kbTilde, kbBackSpace, /* 0x077-0x07F */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x080-0x087 */ // International input characters starting here. + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x088-0x08F */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x090-0x097 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x098-0x09F */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x0A0-0x0A7 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x0A8-0x0AF */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x0B0-0x0B7 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x0B8-0x0BF */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x0C0-0x0C7 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x0C8-0x0CF */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x0D0-0x0D7 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x0D8-0x0DF */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x0E0-0x0E7 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x0E8-0x0EF */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x0F0-0x0F7 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x0F8-0x0FF */ + 0x0000, 0x0000, kbDown, kbUp, kbLeft, kbRight, kbHome, 0x0000, /* 0x100-0x107 */ // High translation table. + 0x0000, kbF1, kbF2, kbF3, kbF4, kbF5, kbF6, kbF7, /* 0x108-0x10F */ + kbF8, kbF9, kbF10, kbF11, kbF12, kbShF1, kbShF2, kbShF3, /* 0x110-0x117 */ + kbShF4, kbShF5, kbShF6, kbShF7, kbShF8, kbShF9, kbShF10, kbShF11, /* 0x118-0x11F */ + kbShF12, kbCtF1, kbCtF2, kbCtF3, kbCtF4, kbCtF5, kbCtF6, kbCtF7, /* 0x120-0x127 */ + kbCtF8, kbCtF9, kbCtF10, kbCtF11, kbCtF12, kbAlF1, kbAlF2, kbAlF3, /* 0x128-0x12F */ + kbAlF4, kbAlF5, kbAlF6, kbAlF7, kbAlF8, kbAlF9, kbAlF10, kbAlF11, /* 0x130-0x137 */ + kbAlF12, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x138-0x13F */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x140-0x147 */ + kbCtDelete, kbCtInsert, kbDelete, kbInsert, kbAlInsert, kbAlA, kbAlDelete, kbAlEnd, /* 0x148-0x14F */ + 0x0000, 0x0000, kbPgDn, kbPgUp, kbAlB, 0x0000, kbAlD, kbCtEnter, /* 0x150-0x157 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x158-0x15F */ + 0x0000, kbShTab, 0x0000, kbMinus, kbAlC, 0x0000, 0x0000, 0x0000, /* 0x160-0x167 */ // FIXME: kbMinus is a gray minus. + kbEnd, kbCtEnd, kbAlF, kbAlH, kbAlM, kbAlE, kbAlI, 0x0000, /* 0x168-0x16F */ + kbAlO, kbAlK, 0x0000, kbCtBackSpace, kbAlL, kbAlG, kbAlR, kbAlJ, /* 0x170-0x177 */ + kbAlP, kbAlQ, kbAlN, 0x0000, 0x0000, kbAlS, kbAlT, 0x0000, /* 0x178-0x17F */ + kbAlV, kbPlus, 0x0000, 0x0000, kbAlW, kbAlX, kbAlY, kbCtHome, /* 0x180-0x187 */ // FIXME: kbPlus - plus is gray. + kbShEnter, kbCtLeft, 0x0000, 0x0000, kbCtPgDn, kbAlZ, kbCtPgUp, 0x0000, /* 0x187-0x18F */ // FIXME: Code 0x18F - is Ctrl-PrintScreen and Ctrl-Asterisk. + 0x0000, kbAlEnter, kbCtRight, kbShBackSpace, 0x0000, kbAlMinus, kbAlBackSpace, 0x0000, /* 0x190-0x197 */ // FIXME: kbAlMinus is a Alt + gray Minus. Code 0x197 - is Alt-PrintScreen. + kbAlU, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x198-0x19F */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x1A0-0x1A7 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x1A8-0x1AF */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x1B0-0x1B7 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x1B8-0x1BF */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x1C0-0x1C7 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x1C8-0x1CF */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x1D0-0x1D7 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x1D8-0x1DF */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x1E0-0x1E7 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x1E8-0x1EF */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x1F0-0x1F7 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 /* 0x1F8-0x1FF */ +}; + +void TGKeyQNX4::Init() +{ + TGKey::kbhit=TGKeyQNX4::KbHit; + TGKey::clear=TGKeyQNX4::Clear; + TGKey::gkey=TGKeyQNX4::GKey; + TGKey::Resume=TGKeyQNX4::Resume; + TGKey::Suspend=TGKeyQNX4::Suspend; + TGKey::fillTEvent=TGKeyQNX4::FillTEvent; + TGKey::getShiftState=TGKeyQNX4::GetShiftState; +} + +int TGKeyQNX4::KbHit() +{ + int key; + int tempkey; + + key=::kbhit(); + + if (!key) + { + __nodelay(0, 1); + tempkey=term_key(); + if (tempkey!=-1) + { + key=1; + if (tempkey==K_RESIZE) + { + TDisplayQNX4::ConsoleResizing=1; + term_relearn_size(); + } + __ungetch(tempkey); + } + __nodelay(0, 0); + } + + return key; +} + +void TGKeyQNX4::Resume() +{ + tcgetattr(fileno(stdin), &saved_attributes); +} + +void TGKeyQNX4::Suspend() +{ + tcsetattr(fileno(stdin), TCSANOW, &saved_attributes); +} + +void TGKeyQNX4::Clear() +{ + tcflush(fileno(stdin), TCIFLUSH); +} + +ushort TGKeyQNX4::GKey() +{ + return term_key(); +} + +void TGKeyQNX4::FillTEvent(TEvent &e) +{ + ushort fullcode; + unsigned shiftstate; + + shiftstate=GetShiftState(); + fullcode=GKey(); + + if (fullcode0x001F) && (fullcode<0x0100)) + { + e.keyDown.charScan.charCode=fullcode; + } + else + { + e.keyDown.charScan.charCode=0; + } + + e.keyDown.shiftState=shiftstate; + + if ((e.keyDown.keyCode==kbEnter) && (shiftstate & (kbLeftCtrl | kbRightCtrl))) + { + e.keyDown.keyCode=kbCtM; + } + + // qnxterm keyboard hack. + if (e.keyDown.keyCode==kbCtJ) + { + if (shiftstate & (kbLeftCtrl | kbRightCtrl)) + { + e.keyDown.keyCode=kbCtJ; + } + else + { + e.keyDown.keyCode=kbEnter; + } + } + + if ((e.keyDown.keyCode==kbTab) && (shiftstate & (kbLeftCtrl | kbRightCtrl))) + { + e.keyDown.keyCode=kbCtI; + } + + if (shiftstate & (kbLeftShift | kbRightShift)) + { + switch(e.keyDown.keyCode) + { + case kbLeft: + e.keyDown.keyCode=kbShLeft; + break; + case kbRight: + e.keyDown.keyCode=kbShRight; + break; + case kbUp: + e.keyDown.keyCode=kbShUp; + break; + case kbDown: + e.keyDown.keyCode=kbShDown; + break; + case kbHome: + e.keyDown.keyCode=kbShHome; + break; + case kbEnd: + e.keyDown.keyCode=kbShEnd; + break; + case kbPgDn: + e.keyDown.keyCode=kbShPgDn; + break; + case kbPgUp: + e.keyDown.keyCode=kbShPgUp; + break; + case kbInsert: + e.keyDown.keyCode=kbShInsert; + break; + case kbDelete: + e.keyDown.keyCode=kbShDelete; + break; + } + } + + if ((shiftstate & (kbLeftShift | kbRightShift)) && (e.keyDown.keyCode==kb0)) + { + e.keyDown.charScan.charCode=0; + e.keyDown.keyCode=kbShInsert; // on numeric keypad. + } + + if ((shiftstate & (kbLeftShift | kbRightShift)) && (e.keyDown.keyCode==kbStop)) + { + e.keyDown.charScan.charCode=0; + e.keyDown.keyCode=kbShDelete; // on numeric keypad. + } + + e.what=evKeyDown; +} + +unsigned TGKeyQNX4::GetShiftState() +{ + unsigned ModState=0x00000000UL; + + char SendBuffer[0x08]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + char RecvBuffer[0x04]={0x00, 0x00, 0x00, 0x00}; + + qnx_ioctl(fileno(stdin), QCTL_DEV_CTL, SendBuffer, 0x08, RecvBuffer, 0x04); + + if (RecvBuffer[0x02]&0x01) ModState|=kbLeftShift | kbRightShift; + if (RecvBuffer[0x02]&0x02) ModState|=kbLeftCtrl | kbRightCtrl; + if (RecvBuffer[0x02]&0x04) ModState|=kbLeftAlt | kbRightAlt; + + return ModState; +} + +#else + + // Here to generate the dependencies in RHIDE + #include + +#endif // TVOS_UNIX && TVOSf_QNX4 diff --git a/tvision/classes/qnx4/qnx4mouse.cc b/tvision/classes/qnx4/qnx4mouse.cc new file mode 100644 index 0000000..d892af1 --- /dev/null +++ b/tvision/classes/qnx4/qnx4mouse.cc @@ -0,0 +1,254 @@ +/* QNX 4 screen routines source. + Copyright (c) 1998-2003 by Mike Gorchak + Covered by the BSD license. */ + +#include + +#if defined(TVOS_UNIX) && defined(TVOSf_QNX4) + +#define Uses_stdlib +#define Uses_string +#define Uses_stdio +#define Uses_time +#define Uses_TEvent +#define Uses_TEventQueue +#define Uses_TScreen +#include + +extern "C" +{ + #include + #include +} + +#include +#include + +int THWMouseQNX4::MousePositionX=0; +int THWMouseQNX4::MousePositionY=0; +int THWMouseQNX4::MouseButtons=0; +ushort THWMouseQNX4::ConsoleMode=QNX_CONSOLE_RAW; + +THWMouseQNX4::~THWMouseQNX4() +{ + // this destructor is never called ! + // instead of it ::Suspend method called. +} + +void THWMouseQNX4::Init(ushort mousemode) +{ + ConsoleMode=mousemode; + + if (ConsoleMode!=QNX_CONSOLE_RAW) + { + // a bit of black magic :) + printf("\x1B""/""0""t"); // clear mouse options. + printf("\x1B""/"">""1""h"); // enable clicking events (press). + printf("\x1B""/"">""6""h"); // enable clicking events. (release). + printf("\x1B""/"">""7""h"); // enable movement events. + printf("\x1B""/"">""9""l"); // intercept all stuff (X10 mouse events reporting). + fflush(stdout); + } + + if (term_mouse_on()==0) + { + buttonCount=3; + } + else + { + if (ConsoleMode==QNX_CONSOLE_XQSH) + { + // under qnxterm mouse is not detected by termlib. + buttonCount=3; + } + else + { + buttonCount=0; + } + } + + term_mouse_handler(MouseHandler); + + if (ConsoleMode==QNX_CONSOLE_PTERM) + { + term_mouse_flags(TERM_MOUSE_RELEASE | TERM_MOUSE_ADJUST | TERM_MOUSE_MENU | TERM_MOUSE_SELECT, + TERM_MOUSE_RELEASE | TERM_MOUSE_ADJUST | TERM_MOUSE_MENU | TERM_MOUSE_SELECT); + }; + + THWMouse::Show=Show; + THWMouse::Hide=Hide; + THWMouse::Suspend=Suspend; + THWMouse::Resume=Resume; + THWMouse::GetEvent=GetEvent; +} + +void THWMouseQNX4::Show() +{ + if (term_mouse_on()==0) + { + buttonCount=3; + } + else + { + if (ConsoleMode==QNX_CONSOLE_XQSH) + { + // under qnxterm mouse is not detected by termlib. + buttonCount=3; + } + else + { + buttonCount=0; + } + } + + term_mouse_move(-1, -1); + term_flush(); +} + +void THWMouseQNX4::Hide() +{ + buttonCount=0; + term_mouse_hide(); + term_flush(); +} + +void THWMouseQNX4::Suspend() +{ + buttonCount=0; + term_mouse_off(); + term_flush(); + + if (ConsoleMode!=QNX_CONSOLE_RAW) + { + printf("\x1B""/""0""t"); // clear all mouse options. + printf("\x1B""/"">""1""l"); // disable clicking events (press). + printf("\x1B""/"">""6""l"); // disable clicking events. (release). + printf("\x1B""/"">""7""l"); // disable movement events. + printf("\x1B""/"">""9""h"); // release hook (Disable X10 mouse events reporting). + fflush(stdout); + } +} + +void THWMouseQNX4::Resume() +{ + if (term_mouse_on()==0) + { + buttonCount=3; + } + else + { + if (ConsoleMode==QNX_CONSOLE_XQSH) + { + // under qnxterm mouse is not detected by termlib. + buttonCount=3; + } + else + { + buttonCount=0; + } + } + + if (ConsoleMode!=QNX_CONSOLE_RAW) + { + // a bit of black magic :) + printf("\x1B""/""0""t"); // clear mouse options. + printf("\x1B""/"">""1""h"); // enable clicking events (press). + printf("\x1B""/"">""6""h"); // enable clicking events. (release). + printf("\x1B""/"">""7""h"); // enable movement events. + printf("\x1B""/"">""9""l"); // intercept all stuff (X10 mouse events reporting). + fflush(stdout); + } +} + +int THWMouseQNX4::MouseHandler(unsigned int* key, struct mouse_event* event) +{ + if (term_mouse_process(key, event)) + { + return 1; + } + term_mouse_move(-1, -1); + + if (event==NULL) + { + // special case for the pterm. + MousePositionX = term_state.mouse_col; + MousePositionY = term_state.mouse_row; + + if ((key!=NULL) && (*key!=0x00000000UL)) + { + if ((*key & K_MOUSE_POS) == K_MOUSE_POS) + { + if ((*key & K_MOUSE_BSELECT) == K_MOUSE_BSELECT) + { + if ((*key & K_MOUSE_CLICK) == K_MOUSE_CLICK) + { + MouseButtons|=mbLeftButton; // left button; + } + if ((*key & K_MOUSE_RELEASE) == K_MOUSE_RELEASE) + { + MouseButtons&=~mbLeftButton; // left button; + } + } + if ((*key & K_MOUSE_BADJUST) == K_MOUSE_BADJUST) + { + if ((*key & K_MOUSE_CLICK) == K_MOUSE_CLICK) + { + MouseButtons|=mbMiddleButton; // middle button; + } + if ((*key & K_MOUSE_RELEASE) == K_MOUSE_RELEASE) + { + MouseButtons&=~mbMiddleButton; // middle button; + } + } + if ((*key & K_MOUSE_BMENU) == K_MOUSE_BMENU) + { + if ((*key & K_MOUSE_CLICK) == K_MOUSE_CLICK) + { + MouseButtons|=mbRightButton; // right button; + } + if ((*key & K_MOUSE_RELEASE) == K_MOUSE_RELEASE) + { + MouseButtons&=~mbRightButton; // right button; + } + } + } + } + + return 0; + } + + MouseButtons=0; + if (event->buttons&_MOUSE_LEFT) + { + MouseButtons|=mbLeftButton; // left button; + } + if (event->buttons & _MOUSE_RIGHT) + { + MouseButtons|=mbRightButton; // right button; + } + if (event->buttons & _MOUSE_MIDDLE) + { + MouseButtons|=mbMiddleButton; // middle button; + } + + MousePositionX = term_state.mouse_col; + MousePositionY = term_state.mouse_row; + + return 0; +} + +void THWMouseQNX4::GetEvent(MouseEventType &me) +{ + me.buttons=MouseButtons; + me.doubleClick = False; + me.where.x = MousePositionX; + me.where.y = MousePositionY; +} + +#else + + // Here to generate the dependencies in RHIDE + #include + #include + +#endif // TVOS_UNIX && TVOSf_QNX4 diff --git a/tvision/classes/qnx4/qnx4scr.cc b/tvision/classes/qnx4/qnx4scr.cc new file mode 100644 index 0000000..05fdfda --- /dev/null +++ b/tvision/classes/qnx4/qnx4scr.cc @@ -0,0 +1,723 @@ +/* QNX 4 screen routines source. + Copyright (c) 1998-2003 by Mike Gorchak + Covered by the BSD license. */ + +#include + +#define Uses_TScreen +#define Uses_TEvent +#define Uses_TDrawBuffer +#define Uses_TGKey +#define Uses_TVCodePage +#define Uses_string +#define Uses_ctype +#define Uses_stdio +#define Uses_unistd +#define Uses_fcntl +#define Uses_stdlib +#define Uses_sys_stat + +#include + +// I delay the check to generate as much dependencies as possible +#if defined(TVOS_UNIX) && defined(TVOSf_QNX4) + +#include + +#include +#include +#include + +extern "C" +{ + #include + #include + #include +} + +TScreen* TV_QNX4DriverCheck() +{ + TScreenQNX4* drv=new TScreenQNX4(); + + if (!TScreen::initialized) + { + delete drv; + + return 0; + } + + return drv; +} + +unsigned char TScreenQNX4::DefaultRadioButton = 0x07; +cc_t TScreenQNX4::oldKeys[5]; +ushort TScreenQNX4::oldScreenSizeX=0; +ushort TScreenQNX4::oldScreenSizeY=0; +ushort TScreenQNX4::ForceModeChange=0; +ushort* TScreenQNX4::UserScreenData=NULL; + +TScreenQNX4::TScreenQNX4() +{ + char* terminaltype; + int len; + + terminaltype=getenv("TERM"); + if (terminaltype==NULL) + { + return; + } + if (strlen(terminaltype)<3) + { + return; + } + if (memcmp(terminaltype, "qnx", 3)!=0) + { + return; + } + + SpecialKeysDisable(fileno(stdin)); + + TDisplayQNX4::Init(); + + if (!InitTermLib()) + { + return; + } + + if (dCB) dCB(); + + // Added by SET: + // Look for user settings + optSearch("AppCP",forcedAppCP); + optSearch("ScrCP",forcedScrCP); + optSearch("InpCP",forcedInpCP); + + // User settings have more priority than detected settings + codePage=new TVCodePage(forcedAppCP!=-1 ? forcedAppCP : TVCodePage::PC437, + forcedScrCP!=-1 ? forcedScrCP : TVCodePage::PC437, + forcedInpCP!=-1 ? forcedInpCP : TVCodePage::PC437); + SetDefaultCodePages(TVCodePage::PC437,TVCodePage::PC437,TVCodePage::PC437); + + suspended=0; + + startupCursor=getCursorType(); + screenMode=startupMode=getCrtMode(); + + /* save the user screen contents */ + TScreen::screenWidth =getCols(); + TScreen::screenHeight=getRows(); + + UserScreenData=new ushort[TScreen::screenWidth*TScreen::screenHeight]; + for (int i=0; i 25); + TScreen::cursorLines = getCursorType(); + setCursorType(0); +} + +void TScreenQNX4::SetVideoMode(ushort mode) +{ + int oldWidth=TScreen::screenWidth; + int oldHeight=TScreen::screenHeight; + ushort _rows=25; + ushort _cols=80; + + SetCrtMode(FixCrtMode(mode)); + SetCrtData(); + + if ((oldWidth!=TScreen::screenWidth) || (oldHeight!=TScreen::screenHeight) || (ForceModeChange)) + { + if (screenBuffer) + { + DeleteArray(screenBuffer); + screenBuffer=NULL; + } + screenBuffer = new ushort[screenWidth*screenHeight]; + + memset(screenBuffer, 0, screenWidth*screenHeight*sizeof(ushort)); + + ForceModeChange=0; + } + else + { + // restore screen contents if mode not setted up. + if (screenBuffer!=NULL) + { + for (int i=0; i 0 && *old == *src) + { + dst++; + len--; + old++; + src++; + } + while (len > 0 && *old_right == *src_right) + { + len--; + old_right--; + src_right--; + } + + if (len > 0) + { + int x = dst % TScreen::screenWidth; + int y = dst / TScreen::screenWidth; + unsigned char* oldchar = (unsigned char*) old; + unsigned char* srcchar = (unsigned char*) src; + + if (ConsoleMode!=QNX_CONSOLE_RAW) + { + if (ConsoleMode==QNX_CONSOLE_PTERM) + { + unsigned char* oldchar = (unsigned char*) old; + unsigned char* srcchar = (unsigned char*) src; + + for (int EachSymbol=0; EachSymbolTScreen::screenWidth/2) + { + term_cur(0, 0); + } + else + { + term_cur(TScreen::screenHeight-1, 0); + } + term_flush(); + + term_cur(y, x); + term_flush(); + } + + term_restore_image(y, x, (char*)old, len); + term_flush(); + + if (ConsoleMode!=QNX_CONSOLE_RAW) + { + TDisplayQNX4::SetCursorPos(CursorLastX, CursorLastY); + } + } +} + +void TScreenQNX4::setCharacter(unsigned offset, ushort value) +{ + setCharacters(offset, &value, 1); +} + +int TScreenQNX4::System(const char *command, pid_t* pidChild, int in, int out, int err) +{ + char *argv[4]; + + if (!pidChild) + { + // If the caller asks for redirection replace the requested handles + if (in!=-1) + dup2(in,STDIN_FILENO); + if (out!=-1) + dup2(out,STDOUT_FILENO); + if (err!=-1) + dup2(err,STDERR_FILENO); + return system(command); + } + + pid_t cpid=fork(); + + if (cpid==0) + { + if (setsid()==-1) + { + _exit(127); + } + + // If the caller asks for redirection replace the requested handles + if (in!=-1) + dup2(in,STDIN_FILENO); + if (out!=-1) + dup2(out,STDOUT_FILENO); + if (err!=-1) + dup2(err,STDERR_FILENO); + + argv[0]=newStr(getenv("SHELL")); + if (!argv[0]) + argv[0]=newStr("/bin/sh"); + argv[1]=newStr("-c"); + argv[2]=newStr(command); + argv[3]=NULL; + execvp(argv[0],argv); + delete[] argv[0]; + delete[] argv[1]; + delete[] argv[2]; + _exit(127); + } + + if (cpid==-1) + { + *pidChild=0; + + return system(command); + } + + *pidChild=cpid; + + return 0; +} + +void TScreenQNX4::SpecialKeysDisable(int fd) +{ + struct termios terminal; + + tcgetattr(fd, &terminal); + oldKeys[0]=terminal.c_cc[VSUSP]; + oldKeys[1]=terminal.c_cc[VSTART]; + oldKeys[2]=terminal.c_cc[VSTOP]; + oldKeys[3]=terminal.c_cc[VQUIT]; + oldKeys[4]=terminal.c_cc[VINTR]; + terminal.c_cc[VSUSP] =0; + terminal.c_cc[VSTART]=0; + terminal.c_cc[VSTOP] =0; + terminal.c_cc[VQUIT] =0; + terminal.c_cc[VINTR] =0; + tcsetattr(fd, TCSANOW, &terminal); +} + +void TScreenQNX4::SpecialKeysRestore(int fd) +{ + struct termios terminal; + + tcgetattr(fd, &terminal); + terminal.c_cc[VSUSP] =oldKeys[0]; + terminal.c_cc[VSTART]=oldKeys[1]; + terminal.c_cc[VSTOP] =oldKeys[2]; + terminal.c_cc[VQUIT] =oldKeys[3]; + terminal.c_cc[VINTR] =oldKeys[4]; + tcsetattr(fd, TCSANOW, &terminal); +} + + +ushort TScreenQNX4::FixCrtMode(ushort mode) +{ + ushort internalmode=0; + ushort _rows=25; + ushort _cols=80; + + switch(mode) + { + case smBW80: + case smCO80: + case smMono: + break; + case smFont8x8: + _rows=50; + break; + case smCO80x28: + _rows=28; + break; + case smCO80x35: + _rows=35; + break; + case smCO80x40: + _rows=40; + break; + case smCO80x43: + _rows=43; + break; + case smCO80x50: + _rows=50; + break; + case smCO80x30: + _rows=30; + break; + case smCO80x34: + _rows=34; + break; + case smCO90x30: + _cols=90; + _rows=30; + break; + case smCO90x34: + _cols=90; + _rows=34; + break; + case smCO94x30: + _cols=94; + _rows=30; + break; + case smCO94x34: + _cols=94; + _rows=34; + break; + case smCO82x25: + _cols=82; + break; + case smCO80x60: + _rows=60; + break; + case smCO132x25: + _cols=132; + break; + case smCO132x43: + _cols=132; + _rows=43; + break; + case smCO132x50: + _cols=132; + _rows=50; + break; + case smCO132x60: + _cols=132; + _rows=60; + break; + default: + _cols=(mode & 0x0000FF00UL) >> 8; + _rows=(mode & 0x000000FFUL); + } + + internalmode=_rows | (_cols << 8); + + return internalmode; +} + +#else + + // Here to generate the dependencies in RHIDE + #include + #include + +#endif // TVOS_UNIX && TVOSf_QNX4 diff --git a/tvision/classes/qnxrtp/qnxdis.cc b/tvision/classes/qnxrtp/qnxdis.cc new file mode 100644 index 0000000..d805aa5 --- /dev/null +++ b/tvision/classes/qnxrtp/qnxdis.cc @@ -0,0 +1,171 @@ +/* QNX RtP screen routines source. + Copyright (c) 2002-2003 by Mike Gorchak + Covered by the BSD license. */ + +#include + +#define Uses_stdio +#define Uses_stdlib +#define Uses_unistd +#define Uses_TDisplay +#define Uses_TScreen +#define Uses_string + +#include + +// I delay the check to generate as much dependencies as possible +#if defined(TVOS_UNIX) && defined(TVOSf_QNXRtP) + +#include +#include + +#include +#include + +int TDisplayQNXRtP::cur_x=0; +int TDisplayQNXRtP::cur_y=0; + +int TDisplayQNXRtP::tty_fd=-1; + +int TDisplayQNXRtP::cursorStart=85; +int TDisplayQNXRtP::cursorEnd=100; + +ushort TDisplayQNXRtP::mode=0; + +volatile sig_atomic_t TDisplayQNXRtP::windowSizeChanged=0; + +TDisplayQNXRtP::~TDisplayQNXRtP() +{ +} + +void TDisplayQNXRtP::Init() +{ + TDisplay::setCursorPos=SetCursorPos; + TDisplay::getCursorPos=GetCursorPos; + TDisplay::getCursorShape=GetCursorShape; + TDisplay::setCursorShape=SetCursorShape; + TDisplay::getRows=GetRows; + TDisplay::getCols=GetCols; + TDisplay::setCrtModeExt=SetCrtModeExt; + TDisplay::checkForWindowSize=CheckForWindowSize; +} + +void TDisplayQNXRtP::SetCursorPos(unsigned x, unsigned y) +{ + char out[1024], *p = out; + + safeput(p, tparm(cursor_address, y, x)); + p-=4; + write(tty_fd, out, p - out); + + cur_x = x; + cur_y = y; +} + +void TDisplayQNXRtP::GetCursorPos(unsigned &x, unsigned &y) +{ + y = cur_y; + x = cur_x; +} + +void TDisplayQNXRtP::SetCursorShape(unsigned start, unsigned end) +{ + char out[1024], *p=out; + + if (start>=end) + { + safeput(p, tparm(cursor_invisible)); + write(tty_fd, out, p-out); + } + else + { + if (end-start>15) + { + // It is hack for now. cursor_visible is empty string. Why ??? + safeput(p, tparm(cursor_normal)); + safeput(p, tparm(cursor_visible)); + write(tty_fd, out, p-out); + } + else + { + safeput(p, tparm(cursor_normal)); + write(tty_fd, out, p-out); + } + } + cursorStart=start; + cursorEnd=end; +} + +void TDisplayQNXRtP::GetCursorShape(unsigned &start, unsigned &end) +{ + start = cursorStart; + end = cursorEnd; +} + +ushort TDisplayQNXRtP::GetRows() +{ + winsize win; + + win.ws_row=0xFFFF; + ioctl(tty_fd, TIOCGWINSZ, &win); + + return win.ws_row!=0xFFFF ? win.ws_row : 25; +} + +ushort TDisplayQNXRtP::GetCols() +{ + winsize win; + + win.ws_col=0xFFFF; + ioctl(tty_fd, TIOCGWINSZ, &win); + + return win.ws_col!=0xFFFF ? win.ws_col : 80; +} + +void TDisplayQNXRtP::SetCrtMode(ushort mode) +{ + TDisplayQNXRtP::mode=mode; +} + +void TDisplayQNXRtP::SetCrtModeExt(char* mode) +{ + system(mode); +} + +int TDisplayQNXRtP::CheckForWindowSize(void) +{ + int ret; + + ret=windowSizeChanged!=0; + windowSizeChanged=0; + + return ret; +} + +const char* TDisplayQNXRtP::GetWindowTitle(void) +{ + return NULL; +} + +int TDisplayQNXRtP::SetWindowTitle(const char* name) +{ + return 0; +} + +inline void TDisplayQNXRtP::safeput(char* &p, char* cap) +{ + if (cap) + { + while (*cap) + { + *p++=*cap++; + } + } +} + +#else + + // Here to generate the dependencies in RHIDE + #include + +#endif // TVOS_UNIX && TVOSf_QNXRtP diff --git a/tvision/classes/qnxrtp/qnxkey.cc b/tvision/classes/qnxrtp/qnxkey.cc new file mode 100644 index 0000000..61a3f3b --- /dev/null +++ b/tvision/classes/qnxrtp/qnxkey.cc @@ -0,0 +1,477 @@ +/* QNX RtP keyboard handler routines source. + Copyright (c) 2002-2003 by Mike Gorchak + Covered by the BSD license. */ + +#include + +#define Uses_stdio +#define Uses_unistd +#define Uses_ctype +#define Uses_stdlib +#define Uses_TEvent +#define Uses_TGKey +#define Uses_TKeys +#define Uses_TKeys_Extended +#define Uses_string +#include + +// I delay the check to generate as much dependencies as possible +#if defined(TVOS_UNIX) && defined(TVOSf_QNXRtP) + +/* include main photon header for pterm key modifier support. */ +/* we must include photon headers before all (GUI vs TUI conflict ;) */ +#include + +#include + +#include +#include +#include +#include + +#include + +#include + +struct dlphoton +{ + void* phhandle; + struct _Ph_ctrl* phctrl; + unsigned short ig; + PhCursorInfo_t qcurbuf; + + /* photon functions */ + struct _Ph_ctrl* (*PhAttach)(char const* name, PhChannelParms_t const* parms); + int (*PhDetach)(struct _Ph_ctrl* Ph); + int (*PhInputGroup)(PhEvent_t* event); + int (*PhQueryCursor)(unsigned short ig, PhCursorInfo_t* buf); +}; + +struct dlphoton TGKeyQNXRtP::phcon; +bool TGKeyQNXRtP::inpterm; + +int openph(struct dlphoton* ph); +int closeph(struct dlphoton* ph); +int detectph(struct dlphoton* ph); +unsigned long getkeymodph(struct dlphoton* ph); + +int openph(struct dlphoton* ph) +{ + ph->phctrl=NULL; + ph->ig=0; + + ph->phhandle=dlopen("/usr/lib/libph.so", RTLD_NOW | RTLD_GLOBAL | RTLD_WORLD); + + if (ph->phhandle==NULL) + { + return -1; + } + + (void*)(ph->PhAttach)=dlsym(ph->phhandle, "PhAttach"); + if (ph->PhAttach==NULL) + { + closeph(ph); + return -3; + } + + (void*)ph->PhDetach=dlsym(ph->phhandle, "PhDetach"); + if (ph->PhDetach==NULL) + { + closeph(ph); + return -4; + } + + (void*)ph->PhInputGroup=dlsym(ph->phhandle, "PhInputGroup"); + if (ph->PhInputGroup==NULL) + { + closeph(ph); + return -5; + } + + (void*)ph->PhQueryCursor=dlsym(ph->phhandle, "PhQueryCursor"); + if (ph->PhQueryCursor==NULL) + { + closeph(ph); + return -6; + } + + return 0; +} + +int closeph(struct dlphoton* ph) +{ + if (ph->phhandle!=NULL) + { + if (ph->phctrl!=NULL) + { + ph->PhDetach(ph->phctrl); + } + dlclose(ph->phhandle); + ph->phhandle=NULL; + } + + return 0; +} + +int detectph(struct dlphoton* ph) +{ + ph->phctrl=ph->PhAttach(NULL, NULL); + + if(!ph->phctrl) + { + return -1; + } + + ph->ig=ph->PhInputGroup(NULL); + + return 0; +} + +unsigned long getkeymodph(struct dlphoton* ph) +{ + int stat; + + stat=ph->PhQueryCursor(ph->ig, &ph->qcurbuf); + + if (stat==-1) + { + return 0x00000000UL; + } + + return ph->qcurbuf.key_mods; +} + +#define kbCtrl (kbLeftCtrl | kbRightCtrl) +#define kbAlt (kbRightAlt | kbLeftAlt) + +struct termios TGKeyQNXRtP::saved_attributes; +ushort TGKeyQNXRtP::sFlags; +ushort TGKeyQNXRtP::undecoded; + +ushort TGKeyQNXRtP::hightranstable[0x0100]= +{// 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F + 0x0000, 0x0000, kbDown, kbUp, kbLeft, kbRight, kbHome, kbCtH, // 0x0100 + 0x0000, kbF1, kbF2, kbF3, kbF4, kbF5, kbF6, kbF7, // 0x0108 + kbF8, kbF9, kbF10, kbF11, kbF12, kbShF1, kbShF2, kbShF3, // 0x0110 + kbShF4, kbShF5, kbShF6, kbShF7, kbShF8, kbShF9, kbShF10, kbShF11, // 0x0118 + kbShF12, kbCtF1, kbCtF2, kbCtF3, kbCtF4, kbCtF5, kbCtF6, kbCtF7, // 0x0120 + kbCtF8, kbCtF9, kbCtF10, kbCtF11, kbCtF12, kbAlF1, kbAlF2, kbAlF3, // 0x0128 + kbAlF4, kbAlF5, kbAlF6, kbAlF7, kbAlF8, kbAlF9, kbAlF10, kbAlF11, // 0x0130 + kbAlF12, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0138 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0140 + kbCtDelete, kbCtInsert, kbDelete, kbInsert, 0x0000, kbAlA, 0x0000, 0x0000, // 0x0148 + kbCtUp, kbCtDown, kbPgDn, kbPgUp, kbAlB, kbCtTab, kbAlD, 0x0000, // 0x0150 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0158 + kbShInsert, kbShTab, kbShDelete, kbMinus, kbAlC, kb5, kbCt5, 0x0000, // 0x0160 // FIXME: kbMinus - gray minus, kb5 - numeric 5, kbCt5 - numeric Ctrl-5 + kbEnd, kbCtEnd, kbAlF, kbAlH, kbAlM, kbAlE, kbAlI, 0x0000, // 0x0168 + kbAlO, kbAlK, 0x0000, 0x0000, kbAlL, kbAlG, kbAlR, kbAlJ, // 0x0170 + kbAlP, kbAlQ, kbAlN, kbCtMinus, kbCtPlus, kbAlS, kbAlT, 0x0000, // 0x0178 // FIXME: kbCtMinus and kbCtPlus are gray. + kbAlV, kbPlus, 0x0000, 0x0000, kbAlW, kbAlX, kbAlY, kbCtHome, // 0x0180 // FIXME: kbPlus is gray. + 0x0000, kbCtLeft, 0x0000, 0x0000, kbCtPgDn, kbAlZ, kbCtPgUp, 0x0000, // 0x0188 + kbShUp, kbShDown, kbCtRight, kbShLeft, kbShRight, kbShCtLeft, kbShCtRight, kbAlSpace, // 0x0190 + kbAlU, kbCtBackSpace, kbCtEnter, kbAlEnter, kbShEnter, kbShEnd, kbShHome, kbShPgUp, // 0x0198 + kbShPgDn, kbShBackSpace, kbCt0, kbCt1, kbCt2, kbCt3, kbCt4, kbCt5, // 0x01A0 + kbCt6, kbCt7, kbCt8, kbCt9, kbCtSpace, kbShCtTab, kbShCtHome, kbShCtEnd, // 0x01A8 + kbShCtPgUp, kbShCtPgDn, kbShCtInsert, kbShCt0, kbShCt1, kbShCt2, kbShCt3, kbShCt4, // 0x01B0 + kbShCt5, kbShCt6, kbShCt7, kbShCt8, kbShCt9, 0x0000, 0x0000, 0x0000, // 0x01B8 + kbShCtA, kbShCtB, kbShCtC, kbShCtD, kbShCtE, kbShCtF, kbShCtG, kbShCtH, // 0x01C0 + kbShCtI, kbShCtJ, kbShCtK, kbShCtL, kbShCtM, kbShCtN, kbShCtO, kbShCtP, // 0x01C8 + kbShCtQ, kbShCtR, kbShCtS, kbShCtT, kbShCtU, kbShCtV, kbShCtW, kbShCtX, // 0x01D0 + kbShCtY, kbShCtZ, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x01D8 + kbAl0, kbAl1, kbAl2, kbAl3, kbAl4, kbAl5, kbAl6, kbAl7, // 0x01E0 + kbAl8, kbAl9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, kbCtEsc, // 0x01E8 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x01F0 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 // 0x01F8 +}; + +ushort TGKeyQNXRtP::lowtranstable[0x0100]= +{// 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F + 0x0000, kbCtA, kbCtB, kbCtC, kbCtD, kbCtE, kbCtF, kbCtG, // 0x0000 + 0x0000, kbTab, kbCtJ, kbCtK, kbCtL, kbEnter, kbCtN, kbCtO, // 0x0008 + kbCtP, kbCtQ, kbCtR, kbCtS, kbCtT, kbCtU, kbCtV, kbCtW, // 0x0010 + kbCtX, kbCtY, kbCtZ, kbEsc, kbCtBackSpace, kbCtOpenBrace, 0x0000, 0x0000, // 0x0018 + kbSpace, kbAdmid, kbDobleQuote, kbNumeral, kbDolar, kbPercent, kbAmper, kbQuote, // 0x0020 + kbOpenPar, kbClosePar, kbAsterisk, kbPlus, kbComma, kbMinus, kbStop, kbSlash, // 0x0028 + kb0, kb1, kb2, kb3, kb4, kb5, kb6, kb7, // 0x0030 + kb8, kb9, kbDoubleDot, kbColon, kbLessThan, kbEqual, kbGreaterThan, kbQuestion, // 0x0038 + kbA_Roba, kbShA, kbShB, kbShC, kbShD, kbShE, kbShF, kbShG, // 0x0040 + kbShH, kbShI, kbShJ, kbShK, kbShL, kbShM, kbShN, kbShO, // 0x0048 + kbShP, kbShQ, kbShR, kbShS, kbShT, kbShU, kbShV, kbShW, // 0x0050 + kbShX, kbShY, kbShZ, kbOpenBrace, kbBackSlash, kbCloseBrace, kbCaret, kbUnderLine, // 0x0058 + kbQuote, kbA, kbB, kbC, kbD, kbE, kbF, kbG, // 0x0060 + kbH, kbI, kbJ, kbK, kbL, kbM, kbN, kbO, // 0x0068 + kbP, kbQ, kbR, kbS, kbT, kbU, kbV, kbW, // 0x0070 + kbX, kbY, kbZ, kbOpenCurly, kbOr, kbCloseCurly, kbTilde, kbBackSpace, // 0x0078 + /* add russian or other keys here */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0080 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0088 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0090 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0098 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00A0 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00A8 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00B0 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00B8 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00C0 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00C8 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00D0 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00D8 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00E0 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00E8 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00F0 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 // 0x00F8 +}; + +QNXRtPArtKeys TGKeyQNXRtP::shifttranstable[]= +{ + {kbLeft, kbShLeft}, + {kbRight, kbShRight}, + {kbUp, kbShUp}, + {kbDown, kbShDown}, + {kbInsert, kbShInsert}, + {kbDelete, kbShDelete}, + {kbHome, kbShHome}, + {kbEnd, kbShEnd}, + {kbPgUp, kbShPgUp}, + {kbPgDn, kbShPgDn}, + {kbEnter, kbShEnter}, + {kbBackSpace, kbShBackSpace}, + {kb0, kbShInsert}, // numeric keypad insert + {kbStop, kbShDelete}, // numeric keypad delete + {0xFFFF, 0xFFFF} // end of shift modifyier artificial keys list +}; + +QNXRtPArtKeys TGKeyQNXRtP::alttranstable[]= +{ + {kbEnter, kbAlEnter}, + {kbSpace, kbAlSpace}, + {0xFFFF, 0xFFFF} // end of alt modifyier artificial keys list +}; + +QNXRtPArtKeys TGKeyQNXRtP::ctrltranstable[]= +{ + {kbEnter, kbCtEnter}, + {kbTab, kbCtI}, + {kbBackSpace, kbCtBackSpace}, + {0xFFFF, 0xFFFF} // end of ctrl modifyier artificial keys list +}; + +void TGKeyQNXRtP::Resume() +{ + tcgetattr(fileno(stdin), &saved_attributes); +} + +void TGKeyQNXRtP::Suspend() +{ + tcsetattr(fileno(stdin), TCSANOW, &saved_attributes); +} + +int TGKeyQNXRtP::KbHit() +{ + int c; + + c=getch(); + + if (c != ERR) + { + ungetch(c); + } + + return c != ERR; +} + +void TGKeyQNXRtP::Clear() +{ + tcflush(fileno(stdin), TCIFLUSH); +} + +ushort TGKeyQNXRtP::MakeArtKeys(QNXRtPArtKeys* array, ushort rawkey) +{ + int eachkey=0; + ushort newkey=rawkey; + + do { + + if ((array[eachkey].rawkey==0xFFFF) && + (array[eachkey].transkey==0xFFFF)) + { + break; + } + + if (rawkey==array[eachkey].rawkey) + { + newkey=array[eachkey].transkey; + break; + } + + eachkey++; + + } while(1); + + return newkey; +} + +ushort TGKeyQNXRtP::GKey() +{ + ushort rawkey; + + rawkey=GetRaw(); + undecoded=rawkey; + + do { + if (rawkey<0x0100) + { + rawkey=lowtranstable[rawkey]; + break; + } + + if ((rawkey>0x00FF) && (rawkey<0x01FF)) + { + rawkey=hightranstable[rawkey-0x0100]; + break; + } + } while(1); + + // artificial keys. + + if (sFlags==0) + { + return rawkey; // no artificial keys available. + } + + if (sFlags==kbShift) // processing only shift key (nor Alt, nor Ctrl) + { + rawkey=MakeArtKeys(shifttranstable, rawkey); + } + if (sFlags==kbAlt) // processing only alt key (nor Shift, nor Ctrl) + { + rawkey=MakeArtKeys(alttranstable, rawkey); + } + if (sFlags==kbCtrl) // processing only ctrl key (nor Shift, nor Alt) + { + rawkey=MakeArtKeys(ctrltranstable, rawkey); + } + + return rawkey; +} + +unsigned TGKeyQNXRtP::GetShiftState() +{ + int shift = 0; + int QNXShift = 0; + int QNXShiftEx = 0; + int DieStatus; + + if (!inpterm) + { + devctl(fileno(stdin), DCMD_CHR_LINESTATUS, &QNXShift, sizeof(QNXShift), &DieStatus); + + QNXShiftEx=QNXShift & 0xFFFFFF00UL; + QNXShift&=0x7F; + + if (QNXShift & _LINESTATUS_CON_ALT) + { + shift|=(kbRightAlt | kbLeftAlt); + } + + if (QNXShift & _LINESTATUS_CON_CTRL) + { + shift|=(kbRightCtrl | kbLeftCtrl); + } + + if (QNXShift & _LINESTATUS_CON_SHIFT) + { + shift|=(kbRightShift | kbLeftShift); + } + else + { + if (QNXShiftEx & 0x00000800UL) // grey keys shift modifyier + { + shift|=(kbRightShift | kbLeftShift); + } + } + } + else + { + QNXShift=getkeymodph(&phcon); + + if (QNXShift & TVPH_KEY_ALT) + { + shift|=(kbRightAlt | kbLeftAlt); + } + + if (QNXShift & TVPH_KEY_CTRL) + { + shift|=(kbRightCtrl | kbLeftCtrl); + } + + if (QNXShift & TVPH_KEY_SHIFT) + { + shift|=(kbRightShift | kbLeftShift); + } + } + + return shift; +} + +void TGKeyQNXRtP::FillTEvent(TEvent &e) +{ + ushort fullcode; + + fullcode=GKey(); + + if ((undecoded>0x001F)&&(undecoded<0x0100)) + { + e.keyDown.charScan.charCode=(uchar)undecoded; + } + else + { + e.keyDown.charScan.charCode=0; + } + + e.keyDown.keyCode=fullcode; + e.keyDown.shiftState=sFlags; + e.what=evKeyDown; +} + +void TGKeyQNXRtP::Init() +{ + TGKey::Suspend =TGKeyQNXRtP::Suspend; + TGKey::Resume =TGKeyQNXRtP::Resume; + TGKey::kbhit =TGKeyQNXRtP::KbHit; + TGKey::clear =TGKeyQNXRtP::Clear; + TGKey::gkey =TGKeyQNXRtP::GKey; + TGKey::getShiftState=TGKeyQNXRtP::GetShiftState; + TGKey::fillTEvent =TGKeyQNXRtP::FillTEvent; + + inpterm=false; + if (openph(&phcon)==0) + { + if (detectph(&phcon)==0) + { + inpterm=true; + } + } + +} + +ushort TGKeyQNXRtP::GetRaw() +{ + int code; + + if ((code = getch()) == ERR) + { + sFlags=0; + return 0; + } + + sFlags=GetShiftState(); + + return code; +} + +#else + + // Here to generate the dependencies in RHIDE + #include + +#endif // TVOS_UNIX && TVOSf_QNXRtP diff --git a/tvision/classes/qnxrtp/qnxmouse.cc b/tvision/classes/qnxrtp/qnxmouse.cc new file mode 100644 index 0000000..60a55bb --- /dev/null +++ b/tvision/classes/qnxrtp/qnxmouse.cc @@ -0,0 +1,241 @@ +/* QNX RtP mouse handler routines source. + Copyright (c) 2002-2003 by Mike Gorchak + Covered by the BSD license. */ + +#include + +#if defined(TVOS_UNIX) && defined(TVOSf_QNXRtP) + +#define Uses_stdlib +#define Uses_string +#define Uses_stdio +#define Uses_time +#define Uses_TEvent +#define Uses_TEventQueue +#define Uses_TScreen +#include + +#include +#include +#include +#include + +#include +#include + +int THWMouseQNXRtP::MousePositionX=0; +int THWMouseQNXRtP::MousePositionY=0; +int THWMouseQNXRtP::MouseButtons; + +int THWMouseQNXRtP::MouseMickeyPositionX=0; +int THWMouseQNXRtP::MouseMickeyPositionY=0; + +THWMouseQNXRtP::~THWMouseQNXRtP() +{ + // this destructor is never called ! + // instead of it THWMouseQNXRtP::Suspend method called. +} + +int THWMouseQNXRtP::mousehandle=-1; + +int THWMouseQNXRtP::OpenDeviMouse() +{ + mousehandle=open("/dev/devi/mouse0", O_RDONLY); + if (mousehandle==-1) + { + return 0; + } + + MousePositionX=0; + MousePositionY=0; + MouseButtons=0; + MouseMickeyPositionX=0; + MouseMickeyPositionY=0; + + return 1; +} + +void THWMouseQNXRtP::CloseDeviMouse() +{ + if (mousehandle!=-1) + { + close(mousehandle); + mousehandle=-1; + } + + MousePositionX=0; + MousePositionY=0; + MouseButtons=0; + MouseMickeyPositionX=0; + MouseMickeyPositionY=0; +} + +void THWMouseQNXRtP::ProcessDeviMouse() +{ + fd_set mev; + int selectret; + struct timeval twait; + struct _mouse_packet pkt; + int cols=TDisplayQNXRtP::GetCols(); + int rows=TDisplayQNXRtP::GetRows(); + int TempMousePositionX=MousePositionX; + int TempMousePositionY=MousePositionY; + + FD_ZERO(&mev); + FD_SET(mousehandle, &mev); + + twait.tv_sec=0; + twait.tv_usec=1; + + selectret=select(mousehandle + 1, &mev, NULL, NULL, &twait); + switch (selectret) + { + case -1: + case 0: + break; + default: if (FD_ISSET(mousehandle, &mev)) + { + selectret=read(mousehandle, &pkt, sizeof(struct _mouse_packet)); + if (selectret==sizeof(struct _mouse_packet)) + { + MouseMickeyPositionX+=pkt.dx; + if (MouseMickeyPositionX<0) + { + MouseMickeyPositionX=0; + } + MouseMickeyPositionY-=pkt.dy; + if (MouseMickeyPositionY<0) + { + MouseMickeyPositionY=0; + } + TempMousePositionX=MouseMickeyPositionX/6; + TempMousePositionY=MouseMickeyPositionY/14; + if (TempMousePositionX>=cols) + { + TempMousePositionX=cols-1; + MouseMickeyPositionX=TempMousePositionX*6; + } + if (TempMousePositionY>=rows) + { + TempMousePositionY=rows-1; + MouseMickeyPositionY=TempMousePositionY*14; + } + if ((pkt.hdr.buttons & _POINTER_BUTTON_LEFT)==_POINTER_BUTTON_LEFT) + { + MouseButtons|=mbLeftButton; + } + else + { + MouseButtons&=~mbLeftButton; + } + if ((pkt.hdr.buttons & _POINTER_BUTTON_RIGHT)==_POINTER_BUTTON_RIGHT) + { + MouseButtons|=mbRightButton; + } + else + { + MouseButtons&=~mbRightButton; + } + if ((pkt.hdr.buttons & _POINTER_BUTTON_MIDDLE)==_POINTER_BUTTON_MIDDLE) + { + MouseButtons|=mbMiddleButton; + } + else + { + MouseButtons&=~mbMiddleButton; + } + } + } + break; + } + if ((TempMousePositionX!=MousePositionX) || (TempMousePositionY!=MousePositionY)) + { + Hide(); + + MousePositionX=TempMousePositionX; + MousePositionY=TempMousePositionY; + + Show(); + } +} + +void THWMouseQNXRtP::Init() +{ + if (OpenDeviMouse()) + { + buttonCount=3; + + THWMouse::Show=Show; + THWMouse::Hide=Hide; + THWMouse::Suspend=Suspend; + THWMouse::Resume=Resume; + THWMouse::GetEvent=GetEvent; + } + else + { + buttonCount=0; + } +} + +void THWMouseQNXRtP::Show() +{ + if (mousehandle!=-1) + { + int cols=TDisplayQNXRtP::GetCols(); + ushort offset=MousePositionY*cols+MousePositionX; + ushort mdata=TScreenQNXRtP::screenBuffer[offset]; + + // a la Windows 2000 style text mouse cursor. + mdata=(mdata & 0x00FF) | (mdata & 0x8800) | (~(mdata) & 0x7000) | (~(mdata) & 0x0700); + TScreenQNXRtP::writeBlock(offset, 1, &mdata, &mdata); + } +} + +void THWMouseQNXRtP::Hide() +{ + if (mousehandle!=-1) + { + int cols=TDisplayQNXRtP::GetCols(); + ushort offset=MousePositionY*cols+MousePositionX; + + TScreenQNXRtP::writeBlock(offset, 1, TScreenQNXRtP::screenBuffer+offset, TScreenQNXRtP::screenBuffer+offset); + } +} + +void THWMouseQNXRtP::Suspend() +{ + CloseDeviMouse(); +} + +void THWMouseQNXRtP::Resume() +{ + if (OpenDeviMouse()) + { + buttonCount=3; + } + else + { + buttonCount=0; + } +} + +void THWMouseQNXRtP::GetEvent(MouseEventType &me) +{ + if (mousehandle!=-1) + { + ProcessDeviMouse(); + } + + me.buttons = MouseButtons; + me.doubleClick = False; + me.where.x = MousePositionX; + me.where.y = MousePositionY; +} + +#else + + // Here to generate the dependencies in RHIDE + #include + #include + +#endif // TVOS_UNIX && TVOSf_QNXRtP diff --git a/tvision/classes/qnxrtp/qnxscr.cc b/tvision/classes/qnxrtp/qnxscr.cc new file mode 100644 index 0000000..1be2f09 --- /dev/null +++ b/tvision/classes/qnxrtp/qnxscr.cc @@ -0,0 +1,577 @@ +/* QNX RtP screen routines source. + Copyright (c) 2002-2003 by Mike Gorchak + Covered by the BSD license. */ + +#include + +#define Uses_TScreen +#define Uses_TEvent +#define Uses_TDrawBuffer +#define Uses_TGKey +#define Uses_TVCodePage +#define Uses_string +#define Uses_ctype +#define Uses_stdio +#define Uses_unistd +#define Uses_fcntl +#define Uses_stdlib +#define Uses_sys_stat + +#include + +// I delay the check to generate as much dependencies as possible +#if defined(TVOS_UNIX) && defined(TVOSf_QNXRtP) + +#include +#include +#include +#include + +#include +#include +#include + +TScreen* TV_QNXRtPDriverCheck() +{ + TScreenQNXRtP* drv=new TScreenQNXRtP(); + + if (!TScreen::initialized) + { + delete drv; + + return 0; + } + + return drv; +} + +int TScreenQNXRtP::old_col=-1; +int TScreenQNXRtP::old_fore=-1; +int TScreenQNXRtP::old_back=-1; +int TScreenQNXRtP::force_redraw=0; +cc_t TScreenQNXRtP::oldKeys[5]; +struct termios TScreenQNXRtP::old_term; +struct termios TScreenQNXRtP::new_term; + +TScreenQNXRtP::TScreenQNXRtP() +{ + int i; + int len; + + SpecialKeysDisable(fileno(stdin)); + + if (!isatty(fileno(stdout))) + { + fprintf(stderr,"\r\n"); + fprintf(stderr,_("Error! %s"),_("that's an interactive application, don't redirect stdout. " + "If you want to collect information redirect stderr like this: " + "program 2> file")); + fprintf(stderr,"\r\n"); + return; + } + + tty_fd=fileno(stdout); + + tcgetattr(fileno(stdout), &old_term); + + // Don't need special rights anymore + seteuid(getuid()); + setegid(getgid()); + + initialized=1; + + if (dCB) + { + dCB(); + } + + TDisplayQNXRtP::Init(); + + TScreen::Resume=Resume; + TScreen::Suspend=Suspend; + TScreen::setCrtData=setCrtData; + TScreen::setVideoMode=setVideoMode; + TScreen::setVideoModeExt=setVideoModeExt; + TScreen::getCharacters=getCharacters; + TScreen::getCharacter=getCharacter; + TScreen::setCharacter=setCharacter; + TScreen::setCharacters=setCharacters; + TScreen::System_p=System; + + TGKeyQNXRtP::Init(); + + THWMouseQNXRtP::Init(); + + // Added by SET: + // Look for user settings + optSearch("AppCP",forcedAppCP); + optSearch("ScrCP",forcedScrCP); + optSearch("InpCP",forcedInpCP); + // User settings have more priority than detected settings + codePage=new TVCodePage(forcedAppCP!=-1 ? forcedAppCP : TVCodePage::PC437, + forcedScrCP!=-1 ? forcedScrCP : TVCodePage::PC437, + forcedInpCP!=-1 ? forcedInpCP : TVCodePage::PC437); + SetDefaultCodePages(TVCodePage::PC437,TVCodePage::PC437,TVCodePage::PC437); + + suspended=0; + + startupCursor=getCursorType(); + screenMode=startupMode=getCrtMode(); + + screenWidth=GetCols(); + screenHeight=GetRows(); + + screenBuffer=new ushort[screenWidth * screenHeight]; + + len=screenWidth*screenHeight; + + for (i=0; i_flags &= ~_ISPAD; + + TScreenQNXRtP::SendToTerminal(tparm(set_attributes, 0, 0, 0, 0, 0, 0, 0, 0, 0)); + + if (!suspended) + { + clear(); + RestoreGTables(); + refresh(); + resetterm(); + echo(); + endwin(); + } + + tcsetattr(fileno(stdout), TCSANOW, &old_term); + + if (!suspended) + { + RestoreScreen(); + suspended=1; + } + + if (screenBuffer) + { + DeleteArray(screenBuffer); + screenBuffer=NULL; + } + + SpecialKeysRestore(fileno(stdin)); +} + +void TScreenQNXRtP::Resume() +{ + setVideoMode(screenMode); + tcsetattr(tty_fd, TCSANOW, &new_term); + SetGTables(); + doupdate(); +} + +void TScreenQNXRtP::Suspend() +{ + char out[0x40], *p = out; + + old_col = old_back = old_fore = -1; + + setCursorType(startupCursor); + RestoreGTables(); + + mapColor(p, 0x07); // White (fg) on black (bg). + safeput(p, "\x0C"); // clear screen (QNX RtP specific). + *p=0x00; + printf("%s", out); // Execute. + fflush(stdout); + + endwin(); + tcsetattr(tty_fd, TCSANOW, &old_term); + RestoreScreen(); +} + +void TScreenQNXRtP::setCrtData() +{ + screenMode =getCrtMode(); + screenWidth =getCols(); + screenHeight=getRows(); + hiResScreen =Boolean(screenHeight > 25); + cursorLines =getCursorType(); + setCursorType(0); +} + +void TScreenQNXRtP::setVideoMode(ushort mode) +{ + int oldWidth=screenWidth; + int oldHeight=screenHeight; + + setCrtMode(mode); + setCrtData(); + + if (screenWidth!=oldWidth || screenHeight!=oldHeight || !screenBuffer) + { + if (screenBuffer) + { + DeleteArray(screenBuffer); + screenBuffer=NULL; + } + screenBuffer = new ushort[screenWidth*screenHeight]; + } + memset(screenBuffer, 0, screenWidth*screenHeight*sizeof(ushort)); +} + +void TScreenQNXRtP::setVideoModeExt(char* mode) +{ + int oldWidth=screenWidth; + int oldHeight=screenHeight; + + setCrtModeExt(mode); + setCrtData(); + + if (screenWidth!=oldWidth || screenHeight!=oldHeight || !screenBuffer) + { + if (screenBuffer) + { + DeleteArray(screenBuffer); + screenBuffer=NULL; + } + screenBuffer = new ushort[screenWidth*screenHeight]; + } + memset(screenBuffer, 0, screenWidth*screenHeight*sizeof(ushort)); +} + +void TScreenQNXRtP::getCharacters(unsigned offset, ushort* buf, unsigned count) +{ + memcpy(buf, screenBuffer+offset, count*sizeof(ushort)); +} + +ushort TScreenQNXRtP::getCharacter(unsigned dst) +{ + ushort src; + + getCharacters(dst, &src, 1); + + return src; +} + +void TScreenQNXRtP::setCharacters(unsigned dst, ushort* src, unsigned len) +{ + ushort *old = screenBuffer + dst; + ushort *old_right = old + len - 1; + ushort *src_right = src + len - 1; + + if (!force_redraw) + { + while (len > 0 && *old == *src) + { + dst++; + len--; + old++; + src++; + } + while (len > 0 && *old_right == *src_right) + { + len--; + old_right--; + src_right--; + } + } + + if (len > 0) + { + writeBlock(dst, len, old, src); + } +} + +void TScreenQNXRtP::setCharacter(unsigned offset, ushort value) +{ + setCharacters(offset, &value, 1); +} + +int TScreenQNXRtP::System(const char *command, pid_t* pidChild, int in, + int out, int err) +{ + char *argv[4]; + + if (!pidChild) + { + // If the caller asks for redirection replace the requested handles + if (in!=-1) + dup2(in,STDIN_FILENO); + if (out!=-1) + dup2(out,STDOUT_FILENO); + if (err!=-1) + dup2(err,STDERR_FILENO); + return system(command); + } + + pid_t cpid=fork(); + + if (cpid==0) + { + if (setsid()==-1) + { + _exit(127); + } + + // If the caller asks for redirection replace the requested handles + if (in!=-1) + dup2(in,STDIN_FILENO); + if (out!=-1) + dup2(out,STDOUT_FILENO); + if (err!=-1) + dup2(err,STDERR_FILENO); + + argv[0]=getenv("SHELL"); + if (!argv[0]) + { + argv[0]="/bin/sh"; + } + argv[1]="-c"; + argv[2]=(char *)command; + argv[3]=0; + execvp(argv[0],argv); + _exit(127); + } + + if (cpid==-1) + { + *pidChild=0; + + return system(command); + } + + *pidChild=cpid; + + return 0; +} + +void TScreenQNXRtP::SpecialKeysDisable(int fd) +{ + struct termios terminal; + + tcgetattr(fd, &terminal); + oldKeys[0]=terminal.c_cc[VSUSP]; + oldKeys[1]=terminal.c_cc[VSTART]; + oldKeys[2]=terminal.c_cc[VSTOP]; + oldKeys[3]=terminal.c_cc[VQUIT]; + oldKeys[4]=terminal.c_cc[VINTR]; + terminal.c_cc[VSUSP] =0; + terminal.c_cc[VSTART]=0; + terminal.c_cc[VSTOP] =0; + terminal.c_cc[VQUIT] =0; + terminal.c_cc[VINTR] =0; + tcsetattr(fd, TCSANOW, &terminal); +} + +void TScreenQNXRtP::SpecialKeysRestore(int fd) +{ + struct termios terminal; + + tcgetattr(fd, &terminal); + terminal.c_cc[VSUSP] =oldKeys[0]; + terminal.c_cc[VSTART]=oldKeys[1]; + terminal.c_cc[VSTOP] =oldKeys[2]; + terminal.c_cc[VQUIT] =oldKeys[3]; + terminal.c_cc[VINTR] =oldKeys[4]; + tcsetattr(fd, TCSANOW, &terminal); +} + +void TScreenQNXRtP::StartNCurses() +{ + initscr(); + stdscr->_flags |= _ISPAD; + keypad(stdscr, TRUE); + cbreak(); + noecho(); + nonl(); + + if (has_colors()) + { + start_color(); + } + + refresh(); + + timeout(0); + + SetGTables(); + + TScreen::screenMode = TScreen::smCO80; + + tcgetattr(tty_fd, &new_term); + + signal(SIGWINCH, sigWindowSizeChanged); + + ESCDELAY=1; +} + +void TScreenQNXRtP::SetGTables() +{ + printf("\x0F"); // Select GL to G0 + printf("\x1B""\x7E"); // Select GR to G1 + printf("\x1B""\x28""\x42"); // Select G0 to ASCII charset. + printf("\x1B""\x29""\x3C"); // Select G1 to supplement charset. + fflush(stdout); +} + +void TScreenQNXRtP::RestoreGTables() +{ + printf("\x0F"); // Select GL to G0 + printf("\x1B""\x7E"); // Select GR to G1 + printf("\x1B""\x28""\x42"); // Select G0 to ASCII charset. + printf("\x1B""\x29""\x30"); // Select G1 to special charset. + fflush(stdout); +} + +void TScreenQNXRtP::sigWindowSizeChanged(int sig) +{ + TScreenQNXRtP::windowSizeChanged=1; + signal(sig, sigWindowSizeChanged); +} + +void TScreenQNXRtP::SendToTerminal(const char* const value) +{ + if (!value) + { + return; + } + + printf(value); + fflush(stdout); +} + +void TScreenQNXRtP::RestoreScreen() +{ + char b[256]; + char* p=b; + + mapColor(p, 0x07); + *p=0; + + SendToTerminal(b); + + SendToTerminal(clear_screen); +} + +void TScreenQNXRtP::mapColor(char* &p, int col) +{ + int back; + int fore; + static char map[] = {0, 4, 2, 6, 1, 5, 3, 7}; + + if (col == old_col) + { + return; + } + + old_col = col; + + back = (col >> 4) & 7; + fore = col & 15; + + if (fore!=old_fore && back!=old_back) + { + sprintf(p, "\x1B""[%d;%d;%dm", fore > 7 ? 1 : 22, 30 + map[fore & 7], 40 + map[back]); + old_fore = fore; + old_back = back; + } + else + { + if (fore!=old_fore) + { + sprintf(p,"\x1B""[%d;%dm", fore > 7 ? 1 : 22, 30 + map[fore & 7]); + old_fore = fore; + } + else + { + sprintf(p,"\x1B""[%dm", 40 + map[back]); + old_back = back; + } + } + p+=strlen(p); +} + +void TScreenQNXRtP::writeBlock(int dst, int len, ushort *old, ushort *src) +{ + char out[4096]; + char *p = out; + int col = -1; + int PCTable=-1; + + safeput(p, tparm(cursor_address, dst / TScreen::screenWidth, dst % TScreen::screenWidth)); + p-=4; + safeput(p, "\x1B""[?7l"); + + while (len-- > 0) + { + int code = *src & 0xff; + int newcol = *src >> 8; + + *old++ = *src++; + if (col == -1 || col != newcol) + { + col = newcol; + mapColor(p, col); + } + + if (code<0x80) + { + if (PCTable!=0) + { + PCTable=0; + safeput(p, "\x1B""[11m"); + } + } + else + { + if (PCTable!=1) + { + PCTable=1; + safeput(p, "\x1B""[12m"); + } + } + + if (code==0x1B) + { + safeput(p, "\x1B""[10m"); + PCTable=-1; + *p++ = '-'; + } + else + { + *p++ = code; + } + + if (p > out+4000) + { + write(tty_fd, out, p-out); + p = out; + } + } + + safeput(p, "\x1B""[10m"); + PCTable=-1; + + safeput(p, "\x1B""[?7h"); + safeput(p, tparm(cursor_address, cur_y, cur_x)); + p-=4; + + do { + write(tty_fd, out, p-out); + } while(0); +} + +#else + + // Here to generate the dependencies in RHIDE + #include + #include + +#endif // TVOS_UNIX && TVOSf_QNXRtP diff --git a/tvision/classes/tapplica.cc b/tvision/classes/tapplica.cc new file mode 100644 index 0000000..b928720 --- /dev/null +++ b/tvision/classes/tapplica.cc @@ -0,0 +1,178 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_stdio +#define Uses_TEventQueue +#define Uses_TScreen +#define Uses_TObject +#define Uses_TMouse +#define Uses_TApplication +#include + +static TEventQueue *teq = 0; + +#if 0 /************** Disabled ************/ +#ifdef TVCompf_djgpp +#include + +#define REGS __dpmi_regs +#define INTR(nr,r) __dpmi_int(nr,&r) + +#define AX r.x.ax +#define BX r.x.bx +#define CX r.x.cx +#define DX r.x.dx +#define ES r.x.es + +static int mouse_buffer_segment; +static int mouse_buffer_selector; +static int mouse_buffer_size; +static int mouse_buffer_allocated = 0; + +#endif + +static void restore_mouse_state() +{ +#ifdef TVCompf_djgpp + REGS r; + if (mouse_buffer_allocated) + { + AX = 0x0017; + BX = mouse_buffer_size; + ES = mouse_buffer_segment; + DX = 0; + INTR(0x33,r); + } +#endif +} + +static void save_mouse_state() +{ +#ifdef TVCompf_djgpp + REGS r; + if (!mouse_buffer_allocated) + { + AX = 0x0015; + INTR(0x33,r); + mouse_buffer_size = BX; + mouse_buffer_segment = __dpmi_allocate_dos_memory( + (mouse_buffer_size+15)>>4, + &mouse_buffer_selector); + if (mouse_buffer_segment != -1) + mouse_buffer_allocated = 1; + } + if (mouse_buffer_allocated) + { + AX = 0x0016; + BX = mouse_buffer_size; + ES = mouse_buffer_segment; + DX = 0; + INTR(0x33,r); + } +#endif +} +#endif /************** Disabled ************/ + + +/************** Disabled ************/ +#if 0 +static int my_mouse_buffer_segment; +static int my_mouse_buffer_selector; +static int my_mouse_buffer_size; +static int my_mouse_buffer_allocated = 0; + +static void restore_my_mouse_state() +{ + REGS r; + if (my_mouse_buffer_allocated) + { + AX = 0x0017; + BX = my_mouse_buffer_size; + ES = my_mouse_buffer_segment; + DX = 0; + INTR(0x33,r); + } +} + +static void save_my_mouse_state() +{ + REGS r; + if (!my_mouse_buffer_allocated) + { + AX = 0x0015; + INTR(0x33,r); + my_mouse_buffer_size = BX; + my_mouse_buffer_segment = __dpmi_allocate_dos_memory( + (my_mouse_buffer_size+15)>>4, + &my_mouse_buffer_selector); + if (my_mouse_buffer_segment != -1) + my_mouse_buffer_allocated = 1; + } + if (my_mouse_buffer_allocated) + { + AX = 0x0016; + BX = my_mouse_buffer_size; + ES = my_mouse_buffer_segment; + DX = 0; + INTR(0x33,r); + } +} +#endif /************** Disabled ************/ + +void TApplication::resume() +{ + #if 0 + save_mouse_state(); + #endif + TScreen::resume(); + TEventQueue::resume(); + #if 0 + restore_my_mouse_state(); + #endif + resetIdleTime(); // Don't count this time +} + +void TApplication::suspend() +{ + #if 0 + save_my_mouse_state(); + #endif + TEventQueue::suspend(); + TScreen::suspend(); + #if 0 + restore_mouse_state(); + #endif +} + +void initHistory(); +void doneHistory(); + +TApplication::TApplication() : + TProgInit( &TApplication::initStatusLine, + &TApplication::initMenuBar, + &TApplication::initDeskTop + ) +{ + if (!teq) + teq = new TEventQueue(); + initHistory(); +} + +TApplication::~TApplication() +{ + doneHistory(); + delete teq; + teq = 0; +} + diff --git a/tvision/classes/tbackgro.cc b/tvision/classes/tbackgro.cc new file mode 100644 index 0000000..9d3f621 --- /dev/null +++ b/tvision/classes/tbackgro.cc @@ -0,0 +1,76 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#define Uses_TBackground +#define Uses_TDrawBuffer +#define Uses_opstream +#define Uses_ipstream +#define Uses_TStreamableClass +#define Uses_TPalette +#define Uses_TScreen +#define Uses_TDeskTop +#include + +#define cpBackground "\x01" // background palette + +TBackground::TBackground( const TRect& bounds, char aPattern ) : + TView(bounds), + pattern( aPattern ) +{ + growMode = gfGrowHiX | gfGrowHiY; +} + +void TBackground::draw() +{ + TDrawBuffer b; + + char ch = pattern; + if( TScreen::avoidMoire && ch == TDeskTop::defaultBkgrnd ) + ch = TView::noMoireFill; + b.moveChar( 0, ch, getColor(0x01), size.x ); + writeLine( 0, 0, size.x, size.y, b ); +} + +TPalette& TBackground::getPalette() const +{ + static TPalette palette( cpBackground, sizeof( cpBackground )-1 ); + return palette; +} + +#if !defined( NO_STREAM ) + +void TBackground::write( opstream& os ) +{ + TView::write( os ); + os << pattern; +} + +void *TBackground::read( ipstream& is ) +{ + TView::read( is ); + is >> pattern; + return this; +} + +TStreamable *TBackground::build() +{ + return new TBackground( streamableInit ); +} + +TBackground::TBackground( StreamableInit ) : TView( streamableInit ) +{ +} + +#endif // NO_STREAM + + diff --git a/tvision/classes/tbutton.cc b/tvision/classes/tbutton.cc new file mode 100644 index 0000000..7b2b884 --- /dev/null +++ b/tvision/classes/tbutton.cc @@ -0,0 +1,378 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Added callback, code page stuff and various details by Salvador Eduardo Tropea. +Added new class TButtonRef by Salvador Eduardo Tropea. +Added i18n support by Salvador Eduardo Tropea. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_ctype +#define Uses_string +#define Uses_TButton +#define Uses_TDrawBuffer +#define Uses_TEvent +#define Uses_TRect +#define Uses_TGroup +#define Uses_opstream +#define Uses_ipstream +#define Uses_TPalette +#define Uses_TGKey +#define Uses_TScreen +#include + +/* SET: F*#$%! why these values are defined here!!! +const ushort + cmGrabDefault = 61, + cmReleaseDefault = 62; + + Moved to views.h +*/ + +#define cpButton "\x0A\x0B\x0C\x0D\x0E\x0E\x0E\x0F" + +TButton::TButton( const TRect& bounds, + const char *aTitle, + ushort aCommand, + ushort aFlags) : + TView( bounds ), + title( newStr( aTitle ) ), + intlTitle( NULL ), + command( aCommand ), + flags( aFlags ), + amDefault( Boolean( (aFlags & bfDefault) != 0 ) ) +{ + options |= ofSelectable | ofFirstClick | ofPreProcess | ofPostProcess; + eventMask |= evBroadcast; + if( !commandEnabled(aCommand) ) + state |= sfDisabled; + callBack=0; + // This class can be "Braille friendly" + if (TScreen::getShowCursorEver()) + state |= sfCursorVis; +} + +TButton::~TButton() +{ + DeleteArray((char *)title); // SET + TVIntl::freeSt(intlTitle); +} + + +void TButton::draw() +{ + drawState(False); +} + +void TButton::drawTitle( TDrawBuffer &b, + int s, + int i, + ushort cButton, + Boolean down + ) +{ + int l, scOff; + const char *theTitle = getText(); + if( (flags & bfLeftJust) != 0 ) + l = 1; + else + { + l = (s - cstrlen(theTitle) - 1)/2; + if( l < 1 ) + l = 1; + } + b.moveCStr( i+l, theTitle, cButton ); + + if( showMarkers == True && !down ) + { + if( (state & sfSelected) != 0 ) + scOff = 0; + else if( amDefault ) + scOff = 2; + else + scOff = 4; + b.putChar( 0, specialChars[scOff] ); + b.putChar( s, specialChars[scOff+1] ); + } + if( (state & sfActive) && (state & sfSelected) ) + { + setCursor( i+l-1 , 0 ); + resetCursor(); + } +} + +void TButton::drawState(Boolean down) +{ + ushort cButton, cShadow; + char ch = ' '; + int i; + TDrawBuffer b; + + if( (state & sfDisabled) != 0 ) + cButton = getColor(0x0404); + else + { + cButton = getColor(0x0501); + if( (state & sfActive) != 0 ) + { + if( (state & sfSelected) != 0 ) + cButton = getColor(0x0703); + else if( amDefault ) + cButton = getColor(0x0602); + } + } + cShadow = getColor(8); + int s = size.x-1; + int T = size.y / 2 - 1; + + for( int y = 0; y <= size.y-2; y++ ) + { + b.moveChar( 0, ' ', cButton, size.x ); + b.putAttribute( 0, cShadow ); + if( down ) + { + b.putAttribute( 1, cShadow ); + i = 2; + } + else + { + b.putAttribute( s, cShadow ); + if( showMarkers == False ) + { + if( y == 0 ) + b.putChar( s, shadows[0] ); + else + b.putChar( s, shadows[1] ); + ch = shadows[2]; + } + i = 1; + } + + if( y == T && title != 0 ) + drawTitle( b, s, i, cButton, down ); + + if( showMarkers && !down ) + { + b.putChar( 1, markers[0] ); + b.putChar( s-1, markers[1] ); + } + writeLine( 0, y, size.x, 1, b ); + } + b.moveChar( 0, ' ', cShadow, 2 ); + b.moveChar( 2, ch, cShadow, s-1 ); + writeLine( 0, size.y-1, size.x, 1, b ); +} + +TPalette& TButton::getPalette() const +{ + static TPalette palette( cpButton, sizeof( cpButton )-1 ); + return palette; +} + +void TButton::handleEvent( TEvent& event ) +{ + TPoint mouse; + TRect clickRect; + Boolean down = False; + char c = hotKey( getText() ); + + clickRect = getExtent(); + clickRect.a.x++; + clickRect.b.x--; + clickRect.b.y--; + + if( event.what == evMouseDown ) + { + mouse = makeLocal( event.mouse.where ); + if( !clickRect.contains(mouse) ) + clearEvent( event ); + } + TView::handleEvent(event); + + switch( event.what ) + { + case evMouseDown: + clickRect.b.x++; + do { + mouse = makeLocal( event.mouse.where ); + if( down != clickRect.contains( mouse ) ) + { + down = Boolean( !down ); + drawState( down ); + } + } while( mouseEvent( event, evMouseMove ) ); + if( down ) + { + press(); + drawState( False ); + } + clearEvent( event ); + break; + + case evKeyDown: + if( event.keyDown.keyCode == TGKey::GetAltCode(c) || + ( owner->phase == phPostProcess && + c != 0 && + TGKey::CompareASCII(uctoupper(event.keyDown.charScan.charCode),c) + //uctoupper(event.keyDown.charScan.charCode) == c + ) || + ( (state & sfFocused) != 0 && + event.keyDown.charScan.charCode == ' ' + ) + ) + { + press(); + clearEvent( event ); + } + break; + + case evBroadcast: + switch( event.message.command ) + { + case cmDefault: + if( amDefault && !(state & sfDisabled) ) + { + press(); + clearEvent(event); + } + break; + + case cmGrabDefault: + case cmReleaseDefault: + if( (flags & bfDefault) != 0 ) + { + amDefault = Boolean(event.message.command == cmReleaseDefault); + drawView(); + } + break; + + case cmCommandSetChanged: + if (((state & sfDisabled) && commandEnabled(command)) || + (!(state & sfDisabled) && !commandEnabled(command))) + { + setState(sfDisabled,Boolean(!commandEnabled(command))); + drawView(); + } + break; + } + break; + } +} + +void TButton::makeDefault( Boolean enable ) +{ + if( (flags & bfDefault) == 0 ) + { + message( owner, + evBroadcast, + (enable == True) ? cmGrabDefault : cmReleaseDefault, + this + ); + amDefault = enable; + drawView(); + } +} + +void TButton::setState( ushort aState, Boolean enable ) +{ + TView::setState(aState, enable); + if( aState & (sfSelected | sfActive) ) + { + if(!enable) + { // BUG FIX - EFW - Thu 10/19/95 + state &= ~sfFocused; + makeDefault(False); + } + drawView(); + } + if( (aState & sfFocused) != 0 ) + makeDefault( enable ); +} + +void TButton::press() +{ + message(owner,evBroadcast,cmRecordHistory,0); + if (flags & bfBroadcast) + message(owner,evBroadcast,command,this); + else + { + if (callBack) + {// SET: That's really useful + int ret=callBack(command,cbData); + if (ret==btcbEndModal && owner) + owner->endModal(command); + } + else + { + TEvent e; + e.what=evCommand; + e.message.command=command; + e.message.infoPtr=this; + putEvent(e); + } + } +} + +#if !defined( NO_STREAM ) + +void TButton::write( opstream& os ) +{ + TView::write( os ); + os.writeString( title ); + os << command << flags << (int)amDefault; +} + +void *TButton::read( ipstream& is ) +{ + TView::read( is ); + title = is.readString(); + intlTitle = NULL; + int temp; + is >> command >> flags >> temp; + amDefault = Boolean(temp); + if( TButton::commandEnabled( command ) ) + state &= ~sfDisabled; + else + state |= sfDisabled; + return this; +} + +TStreamable *TButton::build() +{ + return new TButton( streamableInit ); +} + + +/**[txh]******************************************************************** + + Description: + This class is just like TButton but the title of the button is a reference +and not a copy of the one passed by the user. It allows changes from the +application side to be reflected in the button with a simple redraw. That's +*very* useful for remappings. + +***************************************************************************/ + +TButtonRef::TButtonRef(const TRect& bounds, const char *aTitle, + ushort aCommand, ushort aFlags) : + TButton(bounds,aTitle,aCommand,aFlags) +{ + DeleteArray((char *)title); + title=aTitle; +} + +TButtonRef::~TButtonRef() +{ + title=NULL; +} + +#endif // NO_STREAM + diff --git a/tvision/classes/tchdirdi.cc b/tvision/classes/tchdirdi.cc new file mode 100644 index 0000000..2f8aff5 --- /dev/null +++ b/tvision/classes/tchdirdi.cc @@ -0,0 +1,216 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Vadim Beloborodov to be used on WIN32 console +Modified by Salvador E. Tropea: added i18n support. Horizontal scroll bar. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_ctype +#define Uses_stdio +#define Uses_string +#define Uses_unistd +#define Uses_chdir + +#define Uses_MsgBox +#define Uses_TChDirDialog +#define Uses_TRect +#define Uses_TInputLine +#define Uses_T1Label +#define Uses_THistory +#define Uses_TScrollBar +#define Uses_TDirListBox +#define Uses_TButton +#define Uses_TEvent +#define Uses_TDirEntry +#define Uses_TDirCollection +#define Uses_TChDirDialog +#define Uses_opstream +#define Uses_ipstream +#define Uses_TStreamableClass +#include + +TChDirDialog::TChDirDialog( ushort opts, ushort histId ) : + TWindowInit( &TChDirDialog::initFrame ) + , TDialog( TRect( 16, 2, 64, 21 ), __("Change Directory") ) +{ + options |= ofCentered; + + dirInput = new TInputLine( TRect( 3, 3, 30, 4 ), FILENAME_MAX ); + insert( dirInput ); + insert( new T1Label( 2, 2, __("Directory ~n~ame"), dirInput )); + insert( new THistory( TRect( 30, 3, 33, 4 ), dirInput, histId ) ); + + TScrollBar *sbv = new TScrollBar( TRect( 32, 6, 33, 16 ) ); + insert( sbv ); + // SET: Looks like original authors never had deep directory structures ... + // So I added a horizontal scroll bar. + TScrollBar *sbh = new TScrollBar( TRect( 3, 16, 32, 17 ) ); + sbh->setRange( 0, PATH_MAX ); + sbh->setStep( 28, 1 ); + insert( sbh ); + dirList = new TDirListBox( TRect( 3, 6, 32, 16 ), sbv, sbh ); + insert( dirList ); + insert( new T1Label( 2, 5, __("Directory ~t~ree"), dirList )); + + okButton = new TButton( TRect( 35, 6, 45, 8 ), __("~O~K"), cmOK, bfDefault ); + insert( okButton ); + chDirButton = new TButton( TRect( 35, 9, 45, 11 ), __("~C~hdir"), cmChangeDir, bfNormal ); + insert( chDirButton ); + insert( new TButton( TRect( 35, 12, 45, 14 ), __("~R~evert"), cmRevert, bfNormal ) ); + if( (opts & cdHelpButton) != 0 ) + insert( new TButton( TRect( 35, 15, 45, 17 ), __("Help"), cmHelp, bfNormal ) ); + if( (opts & cdNoLoadDir) == 0 ) + setUpDialog(); + selectNext( False ); +} + +static inline +int changeDir( const char *path ) +{ +#if 0 // DJGPP can handle chdir also over drives + if( path[1] == ':' ) + setdisk( uctoupper(path[0]) - 'A' ); +#endif + return chdir( path ); +} + +uint32 TChDirDialog::dataSize() +{ + return 0; +} + +void TChDirDialog::shutDown() +{ + dirList = 0; + dirInput = 0; + okButton = 0; + chDirButton = 0; + TDialog::shutDown(); +} + +void TChDirDialog::getData( void * ) +{ +} + +void TChDirDialog::handleEvent( TEvent& event ) +{ + TDialog::handleEvent( event ); + switch( event.what ) + { + case evCommand: + { + char curDir[PATH_MAX]; + switch( event.message.command ) + { + case cmRevert: + CLY_GetCurDirSlash(curDir); + break; + case cmChangeDir: + { + TDirEntry *p = dirList->list()->at( dirList->focused ); + strcpy( curDir, p->dir() ); + #ifdef CLY_HaveDriveLetters + if( strcmp( curDir, _("Drives") ) == 0 ) + // Go and get the drive names + break; + if( !driveValid( curDir[0] ) ) + // Invalid drive, don't change + return; + #endif + // Ensure it have a DIRSEPARATOR at the end + if( curDir[strlen(curDir)-1] != DIRSEPARATOR ) + strcat( curDir, DIRSEPARATOR_ ); + // Go and get the directories + break; + } + case cmDirSelection: + chDirButton->makeDefault((Boolean)(event.message.infoPtr!=NULL)); + return; // Do not use break here ! + default: + return; + } + dirList->newDirectory( curDir ); + #if CLY_HaveDriveLetters + // Let the last dirsep only if it is X:/ + int len = strlen( curDir ); + if( len > 3 && curDir[len-1] == DIRSEPARATOR ) + curDir[len-1] = EOS; + #endif + dirInput->setDataFromStr(curDir); + dirInput->drawView(); + dirList->select(); + clearEvent( event ); + } + default: + break; + } +} + +void TChDirDialog::setData( void * ) +{ +} + +void TChDirDialog::setUpDialog() +{ + if( dirList != 0 ) + { + char curDir[PATH_MAX]; + CLY_GetCurDirSlash( curDir ); + dirList->newDirectory( curDir ); + if( dirInput != 0 ) + { + #if CLY_HaveDriveLetters + int len = strlen( curDir ); + if( len > 3 && curDir[len-1] == DIRSEPARATOR ) + curDir[len-1] = EOS; + #endif + dirInput->setDataFromStr(curDir); + dirInput->drawView(); + } + } +} + +Boolean TChDirDialog::valid( ushort command ) +{ + if ( command != cmOK ) + return True; + if( changeDir( (const char *)dirInput->getData() ) != 0 ) + { + messageBox( __("Invalid directory"), mfError | mfOKButton ); + return False; + } + return True; +} + +#if !defined( NO_STREAM ) + +void TChDirDialog::write( opstream& os ) +{ + TDialog::write( os ); + os << dirList << dirInput << okButton << chDirButton; +} + +void *TChDirDialog::read( ipstream& is ) +{ + TDialog::read( is ); + is >> dirList >> dirInput >> okButton >> chDirButton; + setUpDialog(); + return this; +} + +TStreamable *TChDirDialog::build() +{ + return new TChDirDialog( streamableInit ); +} + +#endif // NO_STREAM + diff --git a/tvision/classes/tcheckbo.cc b/tvision/classes/tcheckbo.cc new file mode 100644 index 0000000..deb3d61 --- /dev/null +++ b/tvision/classes/tcheckbo.cc @@ -0,0 +1,59 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Added TCheckBoxes32 and code page stuff by Salvador Eduardo Tropea. + + * + * + */ + +#define Uses_TCheckBoxes +#include + +void TCheckBoxes::draw() +{ + drawBox( button, 'X' ); +} + +Boolean TCheckBoxes::mark(int item) +{ + return Boolean( (value & (1 << item)) != 0 ); +} + +void TCheckBoxes::press(int item) +{ + value = value^(1 << item); + TCluster::press(item); +} + +uint32 TCheckBoxes32::dataSize() +{ + return 4; +} + +#if !defined( NO_STREAM ) + +TStreamable *TCheckBoxes::build() +{ + return new TCheckBoxes( streamableInit ); +} + +TCheckBoxes::TCheckBoxes( StreamableInit ) : TCluster( streamableInit ) +{ +} + +TStreamable *TCheckBoxes32::build() +{ + return new TCheckBoxes32( streamableInit ); +} + +TCheckBoxes32::TCheckBoxes32( StreamableInit ) : TCheckBoxes( streamableInit ) +{ +} + +#endif // NO_STREAM diff --git a/tvision/classes/tclrdisp.cc b/tvision/classes/tclrdisp.cc new file mode 100644 index 0000000..07107de --- /dev/null +++ b/tvision/classes/tclrdisp.cc @@ -0,0 +1,102 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_string + +#define Uses_TKeys +#define Uses_TColorDisplay +#define Uses_TEvent +#define Uses_TDrawBuffer +#define Uses_TGroup +#define Uses_TRect +#define Uses_opstream +#define Uses_ipstream +#include + +TColorDisplay::TColorDisplay( const TRect& bounds, const char *aText ) : + TView( bounds ), + color( 0 ), + text( newStr( aText ) ) +{ + eventMask |= evBroadcast; +} + +TColorDisplay::~TColorDisplay() +{ + DeleteArray((char *)text); +} + +void TColorDisplay::draw() +{ + uchar c = *color; + if( c == 0 ) + c = errorAttr; + const int len = strlen( text ); + TDrawBuffer b; + for( int i = 0; i <= size.x/len; i++ ) + b.moveStr( i*len, text, c ); + writeLine( 0, 0, size.x, size.y, b ); +} + +void TColorDisplay::handleEvent( TEvent& event ) +{ + TView::handleEvent( event ); + if( event.what == evBroadcast ) + switch( event.message.command ) + { + case cmColorBackgroundChanged: + *color = (*color & 0x0F) | ((event.message.infoLong << 4) & 0xF0); + drawView(); + break; + + case cmColorForegroundChanged: + *color = (*color & 0xF0) | (event.message.infoLong & 0x0F); + drawView(); + } +} + +void TColorDisplay::setColor( uchar *aColor ) +{ + color = aColor; + message( owner, evBroadcast, cmColorSet, (void *)(uipointer)(*color) ); + drawView(); +} + +#if !defined( NO_STREAM ) + +void TColorDisplay::write( opstream& os ) +{ + TView::write( os ); + os.writeString( text ); +} + +void *TColorDisplay::read( ipstream& is ) +{ + TView::read( is ); + text = is.readString(); + color = 0; + return this; +} + +TStreamable *TColorDisplay::build() +{ + return new TColorDisplay( streamableInit ); +} + +TColorDisplay::TColorDisplay( StreamableInit ) : TView( streamableInit ) +{ +} + +#endif + diff --git a/tvision/classes/tcluster.cc b/tvision/classes/tcluster.cc new file mode 100644 index 0000000..91a63c0 --- /dev/null +++ b/tvision/classes/tcluster.cc @@ -0,0 +1,408 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Added palette color and draw code for disabled clusters by Salvador E. Tropea +Added TSItem::append by Salvador E. Tropea + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +//#define Uses_stdio +#define Uses_ctype +#define Uses_string +#define Uses_TKeys +#define Uses_TCluster +#define Uses_TDrawBuffer +#define Uses_TEvent +#define Uses_TPoint +#define Uses_TSItem +#define Uses_TStringCollection +#define Uses_TGroup +#define Uses_opstream +#define Uses_ipstream +#define Uses_TPalette +#define Uses_TGKey +#include + +class TStringCollectionCIntl : public TStringCollection +{ +public: + TStringCollectionCIntl( ccIndex aLimit, ccIndex aDelta ) : + TStringCollection(aLimit,aDelta) {} + virtual void freeItem( void* item ); + stTVIntl *atI( ccIndex item ) { return (stTVIntl *)at(item); }; +}; + +void TStringCollectionCIntl::freeItem( void* item ) +{ + if( item ) + { + stTVIntl *p = (stTVIntl *)item; + if( p->translation ) + delete[] p->translation; + delete p; + } +} + + +#define cpCluster "\x10\x11\x12\x12\x1F" + +// SET: To report the movedTo and press as broadcasts, set it to 0 if you +// don't like it. +unsigned TCluster::extraOptions=ofBeVerbose; + +TCluster::TCluster( const TRect& bounds, TSItem *aStrings ) : + TView(bounds), + value( 0 ), + sel( 0 ) +{ + options |= ofSelectable | ofFirstClick | ofPreProcess | ofPostProcess | + extraOptions; + int i = 0; + TSItem *p; + for( p = aStrings; p != 0; p = p->next ) + i++; + + strings = new TStringCollection( i, 0 ); + intlStrings = new TStringCollectionCIntl( i, 0 ); + + while( aStrings != 0 ) + { + p = aStrings; + strings->atInsert( strings->getCount(), newStr(aStrings->value) ); + intlStrings->atInsert( intlStrings->getCount(), TVIntl::emptySt() ); + aStrings = aStrings->next; + delete(p); + } + + setCursor( 2, 0 ); + showCursor(); +} + +TCluster::~TCluster() +{ + CLY_destroy( (TCollection *)strings ); + CLY_destroy( (TCollection *)intlStrings ); +} + +const char *TCluster::getItemText( ccIndex item ) +{ + const char *key = (const char *)strings->at( item ); + stTVIntl *cache = intlStrings->atI( item ); + //printf("getText(%s,...) [%d]\n",key,item); + return TVIntl::getText( key, cache ); +} + +uint32 TCluster::dataSize() +{ + // I have changed value from ushort to uint32, but to be compatible + // I set dataSize to 2. + // SET: I added TRadioButtons32 and TCheckBox32 + return sizeof(ushort); +} + +void TCluster::drawBox( const char *icon, char marker) +{ + TDrawBuffer b; + ushort color; + + ushort cNorm = state & sfDisabled ? getColor( 0x0505 ) : getColor( 0x0301 ); + ushort cSel = getColor( 0x0402 ); + for( int i = 0; i <= size.y; i++ ) + { + for( int j = 0; j <= (strings->getCount()-1)/size.y + 1; j++ ) + { + int cur = j * size.y + i; + int col = column( cur ); + if ( ( cur < strings->getCount() ) && + (col+cstrlen(getItemText(cur))+5 < maxViewWidth) && + (colgetCount()-1; + movedTo(sel); + drawView(); + clearEvent(event); + } + break; + + case kbDown: + if( (state & sfFocused) != 0 ) + { + if( ++sel >= strings->getCount() ) + sel = 0; + movedTo(sel); + drawView(); + clearEvent(event); + } + break; + case kbRight: + if( (state & sfFocused) != 0 ) + { + sel += size.y; + if( sel >= strings->getCount() ) + { + sel = (sel + 1) % size.y; + if( sel >= strings->getCount() ) + sel = 0; + } + movedTo(sel); + drawView(); + clearEvent(event); + } + break; + case kbLeft: + if( (state & sfFocused) != 0 ) + { + if( sel > 0 ) + { + sel -= size.y; + if( sel < 0 ) + { + sel = ((strings->getCount()+size.y-1) /size.y)*size.y + sel - 1; + if( sel >= strings->getCount() ) + sel = strings->getCount()-1; + } + } + else + sel = strings->getCount()-1; + movedTo(sel); + drawView(); + clearEvent(event); + } + break; + default: + for( int i = 0; i < strings->getCount(); i++ ) + { + char c = hotKey( getItemText(i) ); + if( TGKey::GetAltCode(c) == event.keyDown.keyCode || + ( ( owner->phase == phPostProcess || + (state & sfFocused) != 0 + ) && + c != 0 && + TGKey::CompareASCII(uctoupper(event.keyDown.charScan.charCode),c) + ) + ) + { + select(); + sel = i; + movedTo(sel); + press(sel); + drawView(); + clearEvent(event); + return; + } + } + if( event.keyDown.charScan.charCode == ' ' && + (state & sfFocused) != 0 + ) + { + press(sel); + drawView(); + clearEvent(event); + } + } +} + +void TCluster::setData(void * rec) +{ + memcpy(&value,rec,dataSize()); + drawView(); +} + +void TCluster::setState( ushort aState, Boolean enable ) +{ + TView::setState( aState, enable ); + if( aState == sfSelected || aState == sfDisabled ) + drawView(); +} + +Boolean TCluster::mark( int ) +{ + return False; +} + +void TCluster::movedTo( int /*item*/ ) +{ + if (owner && (options & ofBeVerbose)) + message(owner,evBroadcast,cmClusterMovedTo,this); +} + +void TCluster::press( int /*item*/ ) +{ + if (owner && (options & ofBeVerbose)) + message(owner,evBroadcast,cmClusterPress,this); +} + +int TCluster::column( int item ) +{ + if( item < size.y ) + return 0; + else + { + int width = 0; + int col = -6; + int l = 0; + for( int i = 0; i <= item; i++ ) + { + if( i % size.y == 0 ) + { + col += width + 6; + width = 0; + } + + if( i < strings->getCount() ) + l = cstrlen( getItemText(i) ); + if( l > width ) + width = l; + } + return col; + } +} + +int TCluster::findSel( TPoint p ) +{ + TRect r = getExtent(); + if( !r.contains(p) ) + return -1; + else + { + int i = 0; + while( p.x >= column( i + size.y ) ) + i += size.y; + int s = i + p.y; + if( s >= strings->getCount() ) + return -1; + else + return s; + } +} + +int TCluster::row( int item ) +{ + return item % size.y; +} + +/**[txh]******************************************************************** + + Description: + Appends the provided TMenuItem at the end of the chain.@* + Coded by SET. That's a mix between Dean Wakerley and TVTools ideas. + +***************************************************************************/ + +void TSItem::append( TSItem *aNext ) +{ + TSItem *item = this; + for ( ; item->next; item = item->next ); + item->next = aNext; +} + +#if !defined( NO_STREAM ) +void TCluster::write( opstream& os ) +{ + TView::write( os ); + os << value << sel << strings; +} + +void *TCluster::read( ipstream& is ) +{ + TView::read( is ); + is >> value >> sel >> strings; + setCursor( 2, 0 ); + showCursor(); + return this; +} + +TStreamable *TCluster::build() +{ + return new TCluster( streamableInit ); +} + +TCluster::TCluster( StreamableInit ) : TView( streamableInit ) +{ +} +#endif // NO_STREAM + diff --git a/tvision/classes/tcollect.cc b/tvision/classes/tcollect.cc new file mode 100644 index 0000000..65ad764 --- /dev/null +++ b/tvision/classes/tcollect.cc @@ -0,0 +1,44 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#define Uses_opstream +#define Uses_ipstream +#define Uses_TCollection +#include + +#if !defined( NO_STREAM ) + +void TCollection::write( opstream& os ) +{ + os << count << limit << delta; + for( ccIndex idx = 0; idx < count; idx++ ) + writeItem( items[idx], os ); +} + +void *TCollection::read( ipstream& is ) +{ + int limit; + is >> count >> limit >> delta; + limit = 0; + setLimit(limit); + for( ccIndex idx = 0; idx < count; idx++ ) + items[idx] = readItem( is ); + return this; +} + +TCollection::TCollection( StreamableInit ) +{ +} + +#endif // NO_STREAM + diff --git a/tvision/classes/tcolordi.cc b/tvision/classes/tcolordi.cc new file mode 100644 index 0000000..6d48326 --- /dev/null +++ b/tvision/classes/tcolordi.cc @@ -0,0 +1,184 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Salvador E. Tropea: added i18n support, enlarged the dialog, +horizontal scroll bar in items, etc. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_string + +#define Uses_TKeys +#define Uses_TColorSelector +#define Uses_TMonoSelector +#define Uses_TColorDisplay +#define Uses_TColorItem +#define Uses_TColorItemList +#define Uses_TColorGroup +#define Uses_TColorGroupList +#define Uses_TColorDialog +#define Uses_TEvent +#define Uses_TDrawBuffer +#define Uses_TGroup +#define Uses_TScrollBar +#define Uses_T1Label +#define Uses_TButton +#define Uses_TRect +#define Uses_opstream +#define Uses_ipstream +#define Uses_TPalette +#define Uses_TScreen +// For the "Try" button: +#define Uses_TProgram +#define Uses_TDeskTop +#include + +TColorDialog::TColorDialog( TPalette *aPalette, TColorGroup *aGroups ): + TWindowInit( &TColorDialog::initFrame ) + , TDialog( TRect( 0, 0, 77, 18 ), __("Colors") ) +{ + options |= ofCentered; + pal = aPalette; + + TScrollBar *sb = new TScrollBar( TRect( 31, 3, 32, 14 ) ); + insert( sb ); + + groups = new TColorGroupList( TRect( 3, 3, 31, 14 ), sb, aGroups); + insert( groups ); + insert( new T1Label( 2, 2, __("~G~roup"), groups ) ); + + sb = new TScrollBar( TRect( 57, 3, 58, 13 ) ); + insert( sb ); + TScrollBar *sbH = new TScrollBar( TRect( 34, 13, 57, 14 ) ); + sbH->setParams(0,0,40,5,1); + insert( sbH ); + + TView *p = new TColorItemList( TRect( 34, 3, 57, 13 ), sb, aGroups->items, sbH ); + insert( p ); + insert( new T1Label( 33, 2, __("~I~tem"), p ) ); + + forSel = new TColorSelector( TRect( 61, 3, 73, 7 ), + TColorSelector::csForeground ); + insert( forSel ); + forLabel = new T1Label( 61, 2, __("~F~oreground"), forSel ); + insert( forLabel ); + + int ib = TScreen::getBlinkState() ? 0 : 2; + + bakSel = new TColorSelector( TRect( 61, 9, 73, 11 + ib), + TColorSelector::csBackground ); + insert( bakSel ); + bakLabel = new T1Label( 61, 8, __("~B~ackground"), bakSel ); + insert( bakLabel ); + + display = new TColorDisplay( TRect( 60, 12 + ib, 74, 14 + ib), + _("Text ") ); + insert( display ); + + monoSel = new TMonoSelector( TRect( 60, 3, 75, 7 ) ); + monoSel->hide(); + insert( monoSel ); + monoLabel = new T1Label( 59, 2, __("Color"), monoSel ); + monoLabel->hide(); + insert( monoLabel ); + + if( aGroups != 0 && aGroups->items != 0 && pal) + display->setColor( (uchar *)&pal->data[ aGroups->items->index ] ); + + insert( new TButton( TRect( 31 - 10*ib, 15, 44 - 10*ib, 17 ), + __("~T~ry"), cmTryColors, bfNormal ) ); + insert( new TButton( TRect( 46 - 10*ib, 15, 59 - 10*ib, 17 ), + __("~O~K"), cmOK, bfDefault ) ); + insert( new TButton( TRect( 61 - 10*ib, 15, 74 - 10*ib, 17 ), + __("Cancel"), + cmCancel, + bfNormal ) ); + selectNext( False ); +} + +TColorDialog::~TColorDialog() +{ +} + +void TColorDialog::handleEvent( TEvent& event ) +{ + TDialog::handleEvent( event ); + if( event.what==evBroadcast && event.message.command==cmNewColorIndex ) + display->setColor( (uchar *)&pal->data[event.message.infoLong] ); + else + // SET: Added this button to test the colors without pressing OK. + if (event.what==evCommand && event.message.command==cmTryColors) + { // That's a new broadcast, I used it for the editor because the + // colors are cached. + message(TProgram::deskTop,evBroadcast,cmUpdateColorsChanged,0); + TProgram::application->CLY_Redraw(); + } +} + +uint32 TColorDialog::dataSize() +{ + return *pal->data + 1; +} + +void TColorDialog::getData( void *rec ) +{ + memcpy( rec, pal->data, *pal->data+1 ); +} + +void TColorDialog::setData( void *rec) +{ + TPalette *p = (TPalette *)rec; + + memcpy( pal->data, p->data, *p->data+1 ); + display->setColor( (uchar *)&pal->data[1] ); + groups->focusItem( 0 ); + if( showMarkers ) + { + forLabel->hide(); + forSel->hide(); + bakLabel->hide(); + bakSel->hide(); + monoLabel->show(); + monoSel->show(); + } + groups->select(); +} + +#if !defined( NO_STREAM ) +void TColorDialog::write( opstream& os ) +{ + TDialog::write( os ); + os << display << groups << forLabel << forSel + << bakLabel << bakSel << monoLabel << monoSel; +} + +void *TColorDialog::read( ipstream& is ) +{ + TDialog::read( is ); + is >> display >> groups >> forLabel >> forSel + >> bakLabel >> bakSel >> monoLabel >> monoSel; + pal = 0; + return this; +} + +TStreamable *TColorDialog::build() +{ + return new TColorDialog( streamableInit ); +} + +TColorDialog::TColorDialog( StreamableInit ) : + TWindowInit( &TColorDialog::initFrame ) + , TDialog( streamableInit ) +{ +} + +#endif // NO_STREAM + diff --git a/tvision/classes/tcolorgr.cc b/tvision/classes/tcolorgr.cc new file mode 100644 index 0000000..b01dd4b --- /dev/null +++ b/tvision/classes/tcolorgr.cc @@ -0,0 +1,224 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Salvador E. Tropea for i18n support. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_string + +#define Uses_TKeys +#define Uses_TColorItem +#define Uses_TColorGroup +#define Uses_TColorGroupList +#define Uses_TGroup +#define Uses_TRect +#define Uses_opstream +#define Uses_ipstream +#include + +TColorGroup::TColorGroup( const char *nm, TColorItem *itm, TColorGroup *nxt ) +{ + items = itm; + next = nxt; + name = newStr( nm ); + cacheName = NULL; +} + +TColorGroup::~TColorGroup() +{ + DeleteArray((char *)name); + TVIntl::freeSt(cacheName); +} + +TColorGroup& operator + ( TColorGroup& g, TColorItem& i ) +{ + TColorGroup *grp = &g; + while( grp->next != 0 ) + grp = grp->next; + + if( grp->items == 0 ) + grp->items = &i; + else + { + TColorItem *cur = grp->items; + while( cur->next != 0 ) + cur = cur->next; + cur->next = &i; + } + return g; +} + +TColorGroup& operator + ( TColorGroup& g1, TColorGroup& g2 ) +{ + TColorGroup *cur = &g1; + while( cur->next != 0 ) + cur = cur->next; + cur->next = &g2; + return g1; +} + + +TColorGroupList::TColorGroupList( const TRect& bounds, + TScrollBar *aScrollBar, + TColorGroup *aGroups + ) : + TListViewer( bounds, 1, 0, aScrollBar ), + groups( aGroups ) +{ + int i = 0; + while( aGroups != 0 ) + { + aGroups = aGroups->next; + i++; + } + setRange(i); +} + +static void freeItems( TColorItem *curItem ) +{ + while( curItem != 0 ) + { + TColorItem *p = curItem; + curItem = curItem->next; + delete(p); + } +} + +static void freeGroups( TColorGroup *curGroup ) +{ + while( curGroup != 0 ) + { + TColorGroup *p = curGroup; + freeItems( curGroup->items ); + curGroup = curGroup->next; + delete(p); + } +} + +TColorGroupList::~TColorGroupList() +{ + freeGroups( groups ); +} + +void TColorGroupList::focusItem( ccIndex item ) +{ + TListViewer::focusItem( item ); + TColorGroup *curGroup = groups; + while( item-- > 0 ) + curGroup = curGroup->next; + message( owner, evBroadcast, cmNewColorItem, curGroup->items); +} + +void TColorGroupList::getText( char *dest, ccIndex item, short maxChars ) +{ + TColorGroup *curGroup = groups; + while( item-- > 0 ) + curGroup = curGroup->next; + strncpy( dest, TVIntl::getText(curGroup->name,curGroup->cacheName), maxChars ); + dest[maxChars] = '\0'; +} + +#if !defined( NO_STREAM ) +void TColorGroupList::writeItems( opstream& os, TColorItem *items ) +{ + short count = 0; + TColorItem *cur; + + for( cur = items; cur != 0; cur = cur->next ) + count++; + + os << count; + + for( cur = items; cur != 0; cur = cur->next ) + { + os.writeString( cur->name ); + os << cur->index; + } +} + +void TColorGroupList::writeGroups( opstream& os, TColorGroup *groups ) +{ + short count = 0; + TColorGroup *cur; + + for( cur = groups; cur != 0; cur = cur->next ) + count++; + + os << count; + + for( cur = groups; cur != 0; cur = cur->next ) + { + os.writeString( cur->name ); + writeItems( os, cur->items ); + } +} + +void TColorGroupList::write( opstream& os ) +{ + TListViewer::write( os ); + writeGroups( os, groups ); +} + +TColorItem *TColorGroupList::readItems( ipstream& is ) +{ + short count; + is >> count; + TColorItem *items = 0; + TColorItem **cur = &items; + while( count-- > 0 ) + { + const char *nm = is.readString(); + uchar index; + is >> index; + *cur = new TColorItem( nm, index ); + cur = &((*cur)->next); + } + *cur = 0; + return items; +} + +TColorGroup *TColorGroupList::readGroups( ipstream& is ) +{ + short count; + is >> count; + TColorGroup *groups = 0; + TColorGroup **cur = &groups; + while( count-- > 0 ) + { + const char *nm = is.readString(); + TColorItem *grp = readItems( is ); + *cur = new TColorGroup( nm, grp ); + cur = &((*cur)->next); + } + *cur = 0; + return groups; +} + +void *TColorGroupList::read( ipstream& is ) +{ + TListViewer::read( is ); + groups = readGroups( is ); + return this; +} + +TStreamable *TColorGroupList::build() +{ + return new TColorGroupList( streamableInit ); +} + +TColorGroupList::TColorGroupList( StreamableInit ) : + TListViewer( streamableInit ) +{ +} + +#endif // NO_STREAM + diff --git a/tvision/classes/tcolorit.cc b/tvision/classes/tcolorit.cc new file mode 100644 index 0000000..1545ca5 --- /dev/null +++ b/tvision/classes/tcolorit.cc @@ -0,0 +1,118 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Salvador E. Tropea for i18n support. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_string + +#define Uses_TKeys +#define Uses_TColorItem +#define Uses_TColorItemList +#define Uses_TEvent +#define Uses_TGroup +#define Uses_TRect +#define Uses_opstream +#define Uses_ipstream +#include + +TColorItem::TColorItem( const char *nm, uchar idx, TColorItem *nxt ) +{ + index = idx; + next = nxt; + name = newStr( nm ); + cacheName = NULL; +} + +TColorItem::~TColorItem() +{ + DeleteArray((char *)name); + TVIntl::freeSt(cacheName); +} + +TColorItem& operator + ( TColorItem& i1, TColorItem& i2 ) +{ + TColorItem *cur = &i1; + while( cur->next != 0 ) + cur = cur->next; + cur->next = &i2; + return i1; +} + +TColorItemList::TColorItemList( const TRect& bounds, + TScrollBar *aScrollBar, + TColorItem *aItems, + TScrollBar *aHScrollBar + ) : + TListViewer( bounds, 1, aHScrollBar, aScrollBar ), + items( aItems ) +{ + eventMask |= evBroadcast; + int i = 0; + while( aItems != 0 ) + { + aItems = aItems->next; + i++; + } + setRange( i ); +} + +void TColorItemList::focusItem( ccIndex item ) +{ + TListViewer::focusItem( item ); + TColorItem *curItem = items; + while( item-- > 0 ) + curItem = curItem->next; + message( owner, evBroadcast, cmNewColorIndex, (void *)(uipointer)(curItem->index)); +} + +void TColorItemList::getText( char *dest, ccIndex item, short maxChars ) +{ + TColorItem *curItem = items; + while( item-- > 0 ) + curItem = curItem->next; + strncpy( dest, TVIntl::getText(curItem->name,curItem->cacheName), maxChars ); + dest[maxChars] = '\0'; +} + +void TColorItemList::handleEvent( TEvent& event ) +{ + TListViewer::handleEvent( event ); + if( event.what == evBroadcast && event.message.command == cmNewColorItem ) + { + items = (TColorItem *)event.message.infoPtr; + TColorItem *curItem = items; + int i = 0; + while( curItem != 0 ) + { + curItem = curItem->next; + i++; + } + setRange( i ); + focusItem( 0 ); + drawView(); + } +} + +#if !defined( NO_STREAM ) +TStreamable *TColorItemList::build() +{ + return new TColorItemList( streamableInit ); +} + +TColorItemList::TColorItemList( StreamableInit ) : + TListViewer( streamableInit ) +{ +} + +#endif // NO_STREAM + diff --git a/tvision/classes/tcolorse.cc b/tvision/classes/tcolorse.cc new file mode 100644 index 0000000..f9b9b0d --- /dev/null +++ b/tvision/classes/tcolorse.cc @@ -0,0 +1,187 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_string + +#define Uses_TKeys +#define Uses_TColorSelector +#define Uses_TEvent +#define Uses_TDrawBuffer +#define Uses_TRect +#define Uses_TView +#define Uses_TGroup +#define Uses_opstream +#define Uses_ipstream +#include + +TColorSelector::TColorSelector( const TRect& bounds, ColorSel aSelType ) : + TView( bounds ) +{ + options |= ofSelectable | ofFirstClick | ofFramed; + eventMask |= evBroadcast; + selType = aSelType; + color = 0; +} + +void TColorSelector::draw() +{ + TDrawBuffer b; + b.moveChar( 0, ' ', 0x70, size.x ); + for(int i = 0; i <= size.y; i++ ) + { + if( i < 4 ) + { + for( int j = 0; j < 4; j++ ) + { + int c = i*4+j; + b.moveChar( j*3, icon, c, 3 ); + if( c == color ) + { + b.putChar( j*3+1, mark ); + if( c == 0 ) + b.putAttribute( j*3+1, 0x70 ); + } + } + } + writeLine( 0, i, size.x, 1, b ); + } +} + +void TColorSelector::colorChanged() +{ + int msg; + if( selType == csForeground ) + msg = cmColorForegroundChanged; + else + msg = cmColorBackgroundChanged; + message( owner, evBroadcast, msg, (void *)(uipointer)color ); +} + +void TColorSelector::handleEvent( TEvent& event ) +{ + const int width = 4; + uchar oldColor = color; +#if 0 + int maxCol = (selType == csBackground) ? 7 : 15; +#else + int maxCol = size.y == 2 ? 7 : 15; +#endif + + TView::handleEvent( event ); + + switch( event.what ) + { + + case evMouseDown: + do { + if( mouseInView( event.mouse.where ) ) + { + TPoint mouse = makeLocal( event.mouse.where ); + color = mouse.y*4 + mouse.x/3; + } + else + color = oldColor; + colorChanged(); + drawView(); + } while( mouseEvent( event, evMouseMove ) ); + break; + + case evKeyDown: + + switch( ctrlToArrow( event.keyDown.keyCode ) ) + { + case kbLeft: + if( color > 0 ) + color--; + else + color = maxCol; + break; + + case kbRight: + if( color < maxCol ) + color++; + else + color = 0; + break; + + case kbUp: + if( color > width-1 ) + color -= width; + else if( color == 0 ) + color = maxCol; + else + color += maxCol - width; + break; + + case kbDown: + if( color < maxCol - (width-1) ) + color += width; + else if( color == maxCol ) + color = 0; + else + color -= maxCol - width; + break; + + default: + return; + } + break; + + case evBroadcast: + if( event.message.command == cmColorSet ) + { + if( selType == csBackground ) + color = event.message.infoLong >> 4; + else + color = event.message.infoLong & 0x0F; + drawView(); + return ; + } + else + return; + default: + return ; + } + drawView(); + colorChanged(); + clearEvent( event ); +} + +#if !defined( NO_STREAM ) +void TColorSelector::write( opstream& os ) +{ + TView::write( os ); + os << color << (short)selType; +} + +void *TColorSelector::read( ipstream& is ) +{ + short temp; + TView::read( is ); + is >> color >> temp; + selType = ColorSel(temp); + return this; +} + +TStreamable *TColorSelector::build() +{ + return new TColorSelector( streamableInit ); +} + +TColorSelector::TColorSelector( StreamableInit ) : TView( streamableInit ) +{ +} + +#endif // NO_STREAM + diff --git a/tvision/classes/tcommand.cc b/tvision/classes/tcommand.cc new file mode 100644 index 0000000..27edc8f --- /dev/null +++ b/tvision/classes/tcommand.cc @@ -0,0 +1,267 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#define Uses_TCommandSet +#define Uses_string +#include + +#include + +#define MAX_COMMANDS (32 * 2048) /* 65536 commands */ +#define COMMANDS_COUNT (MAX_COMMANDS / 32) +#define COMMANDS_SIZE (COMMANDS_COUNT * 4) + +static +uint32 masks[32] = +{ + 0x00000001, + 0x00000002, + 0x00000004, + 0x00000008, + 0x00000010, + 0x00000020, + 0x00000040, + 0x00000080, + 0x00000100, + 0x00000200, + 0x00000400, + 0x00000800, + 0x00001000, + 0x00002000, + 0x00004000, + 0x00008000, + 0x00010000, + 0x00020000, + 0x00040000, + 0x00080000, + 0x00100000, + 0x00200000, + 0x00400000, + 0x00800000, + 0x01000000, + 0x02000000, + 0x04000000, + 0x08000000, + 0x10000000, + 0x20000000, + 0x40000000, + 0x80000000 +}; + +const uint32 fullMask=0xFFFFFFFF; + +static inline +int loc( int cmd ) +{ + return cmd / 32; +} + +static inline +uint32 mask( int cmd ) +{ + return masks[ cmd & 0x1F ]; +} + +static inline +uint32 rest( int cmd ) +{ + return cmd & 0x1F; +} + +TCommandSet::TCommandSet() +{ + cmds = (uint32 *)calloc(COMMANDS_COUNT,4); +} + +void TCommandSet::enableAllCommands() +{ + memset(cmds,0xFF,COMMANDS_SIZE); +} + +TCommandSet::~TCommandSet() +{ + free(cmds); +} + +TCommandSet::TCommandSet( const TCommandSet& tc ) +{ + cmds = (uint32 *)malloc(COMMANDS_SIZE); + memcpy(cmds,tc.cmds,COMMANDS_SIZE); +} + +TCommandSet& TCommandSet::operator = (const TCommandSet& tc) +{ + memcpy(cmds,tc.cmds,COMMANDS_SIZE); + return *this; +} + +Boolean TCommandSet::has( int cmd ) +{ + return Boolean( (cmd >= MAX_COMMANDS ) || + (cmds[ loc( cmd ) ] & mask( cmd )) != 0 ); +} + +void TCommandSet::disableCmd( int cmd ) +{ + if (cmd < MAX_COMMANDS) + cmds[ loc( cmd ) ] &= ~mask( cmd ); +} + +void TCommandSet::enableCmd( const TCommandSet& tc ) +{ + for( int i = 0; i < COMMANDS_COUNT; i++ ) + cmds[i] |= tc.cmds[i]; +} + +void TCommandSet::disableCmd( const TCommandSet& tc ) +{ + for( int i = 0; i < COMMANDS_COUNT; i++ ) + cmds[i] &= ~(tc.cmds[i]); +} + +void TCommandSet::enableCmd( int cmd ) +{ + if (cmd < MAX_COMMANDS) + cmds[ loc( cmd ) ] |= mask( cmd ); +} + +/**[txh]******************************************************************** + + Description: + Enable a range of contiguous commands. As an example: my editor have more +than 128 commands, it means just 4 longs and not 128 calls! SET.@p + Start is included but not end. + +***************************************************************************/ + +void TCommandSet::enableCmd( int cmdStart, int cmdEnd ) +{ + if (cmdEndcmdStart) + { + int pStart=loc(cmdStart); + uint32 rStart=mask(cmdStart); + int pEnd=loc(cmdEnd); + uint32 rEnd=mask(cmdEnd); + uint32 i; + int j; + + // Both in the same word + if (pStart==pEnd) + { + for (i=rStart; i!=rEnd; i<<=1) + cmds[pStart]|=i; + return; + } + // Not all of the pStart must be set + if (rStart!=1) + { + for (i=rStart; i; i<<=1) + cmds[pStart]|=i; + pStart++; + } + // Set the words in the middle + for (j=pStart; jcmdStart) + { + int pStart=loc(cmdStart); + uint32 rStart=mask(cmdStart); + int pEnd=loc(cmdEnd); + uint32 rEnd=mask(cmdEnd); + uint32 i; + int j; + + // Both in the same word + if (pStart==pEnd) + { + for (i=rStart; i!=rEnd; i<<=1) + cmds[pStart]&=~i; + return; + } + // Not all of the pStart must be set + if (rStart!=1) + { + for (i=rStart; i; i<<=1) + cmds[pStart]&=~i; + pStart++; + } + // Set the words in the middle + for (j=pStart; j + +#define Uses_TDeskTop +#define Uses_TRect +#define Uses_TPoint +#define Uses_TEvent +#define Uses_TBackground +#define Uses_opstream +#define Uses_ipstream +#define Uses_TScreen +#define Uses_TVCodePage +#include + +TDeskInit::TDeskInit( TBackground *(*cBackground)( TRect ) ) : + createBackground( cBackground ) +{ +} + +TDeskTop::TDeskTop( const TRect& bounds ) : + TDeskInit( &TDeskTop::initBackground ) + , TGroup(bounds) +{ + growMode = gfGrowHiX | gfGrowHiY; + + TScreen::setCursorPos( bounds.a.x , bounds.b.y ); + + if( createBackground != 0 && + (background = createBackground( getExtent() )) != 0 ) + insert( background ); +} + +void TDeskTop::shutDown() +{ + background = 0; + TGroup::shutDown(); +} + +inline Boolean Tileable( TView *p ) +{ + return Boolean( (p->options & ofTileable) != 0 && (p->state & sfVisible) != 0 ); +} + +static short cascadeNum; +static TView *lastView; + +void doCount( TView* p, void * ) +{ + if( Tileable( p ) ) + { + cascadeNum++; + lastView = p; + } +} + +void doCascade( TView* p, void *r ) +{ + if( Tileable( p ) && cascadeNum >= 0 ) + { + TRect NR = *(TRect *)r; + NR.a.x += cascadeNum; + NR.a.y += cascadeNum; + p->locate( NR ); + cascadeNum--; + } +} + +void TDeskTop::cascade( const TRect &r ) +{ + TPoint min, max; + cascadeNum = 0; + forEach( doCount, 0 ); + if( cascadeNum > 0 ) + { + lastView->sizeLimits( min, max ); + if( (min.x > r.b.x - r.a.x - cascadeNum) || + (min.y > r.b.y - r.a.y - cascadeNum) ) + tileError(); + else + { + cascadeNum--; + lock(); + forEach( doCascade, (void *)&r ); + unlock(); + } + } +} + +void TDeskTop::handleEvent(TEvent& event) +{ + if( (event.what == evBroadcast) && (event.message.command == cmReleasedFocus) ) + // SET: Move the cursor away, hopefully we will have a status bar. + // Helps Braille Terminals to know the object lost the focus. + TScreen::setCursorPos( origin.x , origin.y + size.y ); + TGroup::handleEvent( event ); + if( event.what == evBroadcast && event.message.command == cmUpdateCodePage && + background ) + background->changePattern(TVCodePage::RemapChar( + TDeskTop::odefaultBkgrnd, + (ushort *)event.message.infoPtr)); + + if( event.what == evCommand ) + { + switch( event.message.command ) + { + case cmNext: + if (valid(cmReleasedFocus)) + selectNext( False ); + break; + case cmPrev: + if (valid(cmReleasedFocus)) + current->putInFrontOf( background ); + break; + default: + return; + } + clearEvent( event ); + } +} + +TBackground *TDeskTop::initBackground( TRect r ) +{ + return new TBackground( r, defaultBkgrnd ); +} + +// SET: made static and used unsigned instead of short. +// It calculates the square root truncating the decimals. +static +unsigned iSqr( unsigned i ) +{ + unsigned res1 = 2; + unsigned res2 = i/res1; + while( abs( res1 - res2 ) > 1 ) + { + res1 = (res1 + res2)/2; + res2 = i/res1; + } + return res1 < res2 ? res1 : res2; +} + +void mostEqualDivisors(int n, int& x, int& y) +{ + int i; + + i = iSqr( n ); + if( n % i != 0 ) + if( n % (i+1) == 0 ) + i++; + if( i < (n/i) ) + i = n/i; + + x = n/i; + y = i; +} + +// SET: All to ints, they are the best type for any compiler +static int numCols, numRows, numTileable, leftOver, tileNum; + +void doCountTileable( TView* p, void * ) +{ + if( Tileable( p ) ) + numTileable++; +} + +int dividerLoc( int lo, int hi, int num, int pos) +{ + return int(long(hi-lo)*pos/long(num)+lo); +} + +TRect calcTileRect( int pos, const TRect &r ) +{ + int x, y; + TRect nRect; + + int d = (numCols - leftOver) * numRows; + if( pos < d ) + { + x = pos / numRows; + y = pos % numRows; + } + else + { + x = (pos-d)/(numRows+1) + (numCols-leftOver); + y = (pos-d)%(numRows+1); + } + nRect.a.x = dividerLoc( r.a.x, r.b.x, numCols, x ); + nRect.b.x = dividerLoc( r.a.x, r.b.x, numCols, x+1 ); + if( pos >= d ) + { + nRect.a.y = dividerLoc(r.a.y, r.b.y, numRows+1, y); + nRect.b.y = dividerLoc(r.a.y, r.b.y, numRows+1, y+1); + } + else + { + nRect.a.y = dividerLoc(r.a.y, r.b.y, numRows, y); + nRect.b.y = dividerLoc(r.a.y, r.b.y, numRows, y+1); + } + return nRect; +} + +void doTile( TView* p, void *lR ) +{ + if( Tileable( p ) ) + { + TRect r = calcTileRect( tileNum, *(const TRect *)lR ); + p->locate(r); + tileNum--; + } +} + +void TDeskTop::tile( const TRect& r ) +{ + numTileable = 0; + forEach( doCountTileable, 0 ); + if( numTileable > 0 ) + { + // SET: This trick makes the partitions in the reverse order + if( getOptions() & dsktTileVertical ) + mostEqualDivisors( numTileable, numRows, numCols ); + else + mostEqualDivisors( numTileable, numCols, numRows ); + if( ( (r.b.x - r.a.x)/numCols == 0 ) || + ( (r.b.y - r.a.y)/numRows == 0) ) + tileError(); + else + { + leftOver = numTileable % numCols; + tileNum = numTileable - 1; + lock(); + forEach( doTile, (void *)&r ); + unlock(); + } + } +} + +void TDeskTop::tileError() +{ +} + +// SET: TViews will ask us if that's good time to draw cursor changes +Boolean TDeskTop::canShowCursor() +{ + return lockFlag ? False : True; +} + +// SET: If nobody will recover the focus move the cursor to the status line +ushort TDeskTop::execView( TView *p ) +{ + ushort ret=TGroup::execView(p); + if (p && !current) + TScreen::setCursorPos(0,TScreen::screenHeight-1); + return ret; +} + +#if !defined( NO_STREAM ) +TStreamable *TDeskTop::build() +{ + return new TDeskTop( streamableInit ); +} + +TDeskTop::TDeskTop( StreamableInit ) : + TDeskInit( NULL ) + , TGroup( streamableInit ) +{ +} +#endif // NO_STREAM + diff --git a/tvision/classes/tdialog.cc b/tvision/classes/tdialog.cc new file mode 100644 index 0000000..ede375e --- /dev/null +++ b/tvision/classes/tdialog.cc @@ -0,0 +1,108 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#define Uses_TKeys +#define Uses_TDialog +#define Uses_TEvent +#define Uses_TPalette +#define Uses_TApplication +#include + +#define cpDialog "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F"\ + "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F" + +TDialog::TDialog( const TRect& bounds, const char *aTitle ) : + TWindowInit( &TDialog::initFrame ) + , TWindow( bounds, aTitle, wnNoNumber ) +{ + growMode = 0; + flags = wfMove | wfClose; +} + +TPalette& TDialog::getPalette() const +{ + static TPalette palette1( cpDialog, sizeof( cpDialog )-1 ); + static TPalette palette2( 0, 0 ); + + // Avoid returning the palette if the dialog isn't inserted on the + // desktop or the application. Example: a dialog inside another. + if ( (owner == (TGroup*)TApplication::deskTop) || + (owner == (TGroup*)TApplication::application) + ) return palette1; + return palette2; +} + +void TDialog::handleEvent(TEvent& event) +{ + TWindow::handleEvent(event); + switch (event.what) + { + case evKeyDown: + switch (event.keyDown.keyCode) + { + case kbEsc: + event.what = evCommand; + event.message.command = cmCancel; + event.message.infoPtr = 0; + putEvent(event); + clearEvent(event); + break; + case kbEnter: + event.what = evBroadcast; + event.message.command = cmDefault; + event.message.infoPtr = 0; + putEvent(event); + clearEvent(event); + break; + } + break; + + case evCommand: + switch( event.message.command ) + { + case cmOK: + case cmCancel: + case cmYes: + case cmNo: + if( (state & sfModal) != 0 ) + { + endModal(event.message.command); + clearEvent(event); + } + break; + } + break; + } +} + +Boolean TDialog::valid( ushort command ) +{ + if( command == cmCancel ) + return True; + else + return TGroup::valid( command ); +} + +#if !defined( NO_STREAM ) +TStreamable *TDialog::build() +{ + return new TDialog( streamableInit ); +} + +TDialog::TDialog( StreamableInit ) : + TWindowInit( 0 ) + , TWindow( streamableInit ) +{ +} +#endif // NO_STREAM + diff --git a/tvision/classes/tdircoll.cc b/tvision/classes/tdircoll.cc new file mode 100644 index 0000000..4bb39fd --- /dev/null +++ b/tvision/classes/tdircoll.cc @@ -0,0 +1,40 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#define Uses_TDirCollection +#define Uses_TDirEntry +#define Uses_opstream +#define Uses_ipstream +#include + +#if !defined( NO_STREAM ) +TStreamable *TDirCollection::build() +{ + return new TDirCollection( streamableInit ); +} + +void TDirCollection::writeItem( void *obj, opstream& os ) +{ + TDirEntry *item = (TDirEntry *)obj; + os.writeString( item->text() ); + os.writeString( item->dir() ); +} + +void *TDirCollection::readItem( ipstream& is ) +{ + const char *txt = is.readString(); + const char *dir = is.readString(); + return new TDirEntry( txt, dir ); +} +#endif // NO_STREAM + diff --git a/tvision/classes/tdirlist.cc b/tvision/classes/tdirlist.cc new file mode 100644 index 0000000..178114a --- /dev/null +++ b/tvision/classes/tdirlist.cc @@ -0,0 +1,537 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Vadim Beloborodov to be used on WIN32 console +Modified by Salvador E. Tropea: +* Changed to sort directory names. +* Added incremental directory search. +* Added horizontal scroll bar. +* Made cursor visible. +* Abstracted platform dependent detail, more things must be done. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#include +#define Uses_string +#define Uses_sys_stat +#define Uses_TDirListBox +#define Uses_TEvent +#define Uses_TDirCollection +#define Uses_TChDirDialog +#define Uses_TDirEntry +#define Uses_TButton +#define Uses_TStreamableClass +#define Uses_TStringCollection +#define Uses_TKeys +#define Uses_TVCodePage +#define Uses_TScrollBar +#if defined(TVCompf_djgpp) || defined(TVComp_BCPP) + #define Uses_dir // getdisk() +#endif +#include + +TDirListBox::TDirListBox( const TRect& bounds, TScrollBar *aVScrollBar, + TScrollBar *aHScrollBar ) : + TListBox( bounds, 1, aHScrollBar, aVScrollBar ), + cur( 0 ) +{ + *dir = EOS; + incPos = 0; + // SET: Now we use it for the incremental search + showCursor(); +} + +TDirListBox::~TDirListBox() +{ + CLY_destroy( list() ); +} + +void TDirListBox::draw() +{ + TListBox::draw(); + // SET: Put the cursor over the directory name. Also add an offset + // if we are doing an incremental search. BTW: It should help blind + // people. + if( focused >= 0 && focused < list()->getCount() ) + updateCursorPos(); +} + +void TDirListBox::getText( char *text, ccIndex item, short maxChars ) +{ + strncpy( text, list()->at(item)->text(), maxChars ); + text[maxChars] = '\0'; +} + +/**[txh]******************************************************************** + + Description: + This is a new member added to update the cursor position. Originaly this +class had no cursor. Now is used to show the incremental search state. + +***************************************************************************/ + +void TDirListBox::updateCursorPos() +{ + int x = list()->at( focused )->offset() + 1; + // Here we emulate the TSortedListBox behavior + if( incPos > 1 ) + x += incPos - 1; + if( hScrollBar ) + x -= hScrollBar->value; + if( x <= 0 ) + hideCursor(); + else + { + setCursor( x, focused - topItem ); + showCursor(); + } +} + +void TDirListBox::handleEvent( TEvent& event ) +{ + if( event.what == evMouseDown && event.mouse.doubleClick ) + { + event.what = evCommand; + event.message.command = cmChangeDir; + putEvent( event ); + clearEvent( event ); + return; + } + else if( event.what == evKeyDown ) + {// SET: Incremental directory search + if( event.keyDown.keyCode != kbEnter && + ( event.keyDown.charScan.charCode != 0 || + event.keyDown.keyCode == kbBack ) ) + { + if( event.keyDown.keyCode == kbBack ) + { + if( incPos > 0 ) + incPos--; + } + else + incremental[incPos++] = event.keyDown.charScan.charCode; + incremental[incPos] = 0; + TDirCollection *dirs = list(); + ccIndex c = dirs->getCount(); + ccIndex newFocus = -1; + if( focused < c && cur < c ) + { + int offset = strlen( dirs->at( cur )->dir() ) + 1; + if( focused > cur ) + // From focused + for( int i = focused; i < c; i++ ) + { + if( strncasecmp( dirs->at( i )->dir() + offset, + incremental, incPos ) == 0 ) + { + newFocus = i; + break; + } + } + // From beginning + for( int i = cur + 1; newFocus < 0 && i < c; i++ ) + { + if( strncasecmp( dirs->at( i )->dir() + offset, + incremental, incPos ) == 0 ) + newFocus = i; + } + if( newFocus < 0 ) + { + if( event.keyDown.keyCode != kbBack ) + incPos--; + if( TVCodePage::isAlNum( event.keyDown.charScan.charCode ) ) + { + clearEvent( event ); + return; + } + } + else + { + if( newFocus != focused ) + focusItem( newFocus ); + else + updateCursorPos(); + clearEvent( event ); + return; + } + } + } + } + ccIndex oldFocused = focused; + TListBox::handleEvent( event ); + // SET: Reset the incremental search if the user changed the focus + if( oldFocused != focused ) + { + incPos = 0; + updateCursorPos(); + } +} + +Boolean TDirListBox::isSelected( ccIndex item ) +{ + return Boolean( item == cur ); +} + +#ifndef CLY_HaveDriveLetters +// Mostly POSIX systems where drive letter doesn't exist + +void TDirListBox::showDrives( TDirCollection * ) +{ +} + +#else +// Mostly DOS and Win32 + +#if defined(TVCompf_djgpp) || defined(TVComp_BCPP) +#include +#else +#include +#include //_getdrive() +#define getdisk() (_getdrive()-1) +#endif + +void TDirListBox::showDrives( TDirCollection *dirs ) +{ + Boolean isFirst = True; + char oldc[5]; + strcpy( oldc, "0:"DIRSEPARATOR_ ); + // SET: We actually assume firstDir, middleDir and lastDir have the same + // len. Otherwise the list becomes unreadable. + // Doing this I replaced strcpy by memcpy and avoided continues strlen + // computations. + unsigned lenStr = strlen( firstDir ); + for( char c = 'a'; c <= 'z'; c++ ) + { + if( c < 'c' || driveValid( c ) ) + { + if( oldc[0] != '0' ) + { + char s[ 16 ]; + if( isFirst ) + { + isFirst = False; + memcpy( s, firstDir, lenStr ); + } + else + memcpy( s, middleDir, lenStr ); + s[ lenStr ] = oldc[0]; + s[ lenStr+1 ] = EOS; + dirs->insert( new TDirEntry( s, oldc, lenStr ) ); + } + if( c == getdisk() + 'a' ) + cur = dirs->getCount(); + oldc[0] = c; + } + } + if( oldc[0] != '0' ) + { + char s[ 16 ]; + memcpy( s, lastDir, lenStr ); + s[ lenStr ] = oldc[0]; + s[ lenStr+1 ] = EOS; + dirs->insert( new TDirEntry( s, oldc, lenStr ) ); + } + // SET: No need to scroll here + if( hScrollBar ) + hScrollBar->setRange( 0, 0 ); + // SET: Reset incremental search + incPos = 0; +} +#endif // CLY_HaveDriveLetters + + +/***************************************************************************** + char *SkipDriveName( const char *dir ) + This is a helper to skip the characters used by the drive letter in the +specified dir string. + Added by SET to make the code maintainable. +*****************************************************************************/ + +#ifndef CLY_HaveDriveLetters +// Mostly POSIX systems where drive letter doesn't exist + +// SET: Here we have to "skip" the drive name +#if !defined(TVOSf_QNX4) +static +char *SkipDriveName( char *dir ) +{ + return dir + 1; +} +#else +// Special case "//nodenumber/" +static +char *SkipDriveName( char *dir ) +{ + char *end; + + if( (*dir == '/') && (dir[1] == '/') ) + { + end = strchr( dir+2, DIRSEPARATOR ); + if( !end ) + end = dir + 1; // fallback to usual UNIX path. + else + end += 1; // split the //nodenumber/ string. + } + else + end = dir + 1; // usual UNIX path. + return end; +} +#endif // TVOSf_QNX4 + +#else +// Mostly DOS and Win32 + +static +char *SkipDriveName( char *dir ) +{ + return dir + 3; +} +#endif // CLY_HaveDriveLetters + +/***************************************************************************** + End of char *SkipDriveName( const char *dir ) +*****************************************************************************/ + +/***************************************************************************** + TStringCollection *ListDirectory( char *path, char *end ) + This is a helper to collect the directories found in path using "end" as +base to construct a mask. + Added by SET to make the code maintainable. +*****************************************************************************/ + +#if defined(TVOS_UNIX) || defined(TVCompf_Cygwin) +// POSIX solution using opendir and stat +#include + +static +TStringCollection *ListDirectory( char *path, char *end ) +{ + *end = 0; + TStringCollection *col = new TStringCollection( 10, 10 ); + + DIR *d = opendir( path ); + if( d ) + { + struct dirent *ent; + while( (ent = readdir(d)) != 0 ) + { + struct stat st; + strcpy( end, ent->d_name ); + stat( path, &st ); + if( S_ISDIR(st.st_mode) && strcmp(ent->d_name,".")!=0 && + strcmp(ent->d_name,"..")!=0 ) + col->insert( newStr( ent->d_name ) ); + } + closedir( d ); + } + return col; +} + +#else +#if !defined(TVCompf_djgpp) && !defined(TVComp_BCPP) +// MSVC Win32 solution. It uses _findfirst + +static +TStringCollection *ListDirectory( char *path, char *end ) +{ + strcpy( end, "*" ); + TStringCollection *col=new TStringCollection( 10, 10 ); + + _finddata_t ff; + long res = _findfirst( path, &ff ); + if( res != -1 ) + { + do + { + if( (ff.attrib & _A_SUBDIR) != 0 && ff.name[0] != '.' ) + col->insert( newStr( ff.name ) ); + } + while( _findnext( res, &ff )==0 ); + _findclose( res ); + } + return col; +} + +#else // DJGPP and BC++ +// DJGPP and BC++ solution. It uses findfirst + +#if 0 +extern "C" unsigned short ffattrib(struct ffblk *); +extern "C" char *ffname(struct ffblk *); +#define A(s) ffattrib(&s) +#define N(s) ffname(&s) +#else +#define A(s) s.ff_attrib +#define N(s) s.ff_name +#endif + +static +TStringCollection *ListDirectory( char *path, char *end ) +{ + strcpy( end, "*" ); + TStringCollection *col=new TStringCollection(10,10); + + ffblk ff; + int res = findfirst( path, &ff, FA_DIREC ); + while( res == 0 ) + { + if( (A(ff) & FA_DIREC) != 0 && N(ff)[0] != '.' ) + col->insert( newStr( N(ff) ) ); + res = findnext( &ff ); + } + return col; +} + +#undef A +#undef N +#endif +#endif // DJGPP + +/***************************************************************************** + End of TStringCollection *ListDirectory( char *path, char *end ) +*****************************************************************************/ + +void TDirListBox::showDirs( TDirCollection *dirs ) +{ + const int indentSize = 2; + int indent = indentSize; + + char buf[PATH_MAX*2]; + memset( buf, ' ', sizeof( buf ) ); + char *name = buf + PATH_MAX; + + // SET: Same here, we assume all separators have the same len + unsigned lenSep = strlen( pathDir ); + // The first ramification of the tree + char *org = name - lenSep; + strcpy( org, pathDir ); + + char *curDir = dir; + char *end = SkipDriveName( dir ); + char hold = *end; + *end = EOS; // mark end of drive name + strcpy( name, curDir ); + dirs->insert( new TDirEntry( org, name, lenSep ) ); + *end = hold; // restore full path + curDir = end; + + unsigned maxLen = 0; + while( (end = strchr( curDir, DIRSEPARATOR )) != 0 ) + { + *end = EOS; + unsigned lname = unsigned(end-curDir); + memcpy( name, curDir, lname ); + name[lname] = EOS; + lname += indent + lenSep; + if( lname > maxLen ) + maxLen = lname; + dirs->insert( new TDirEntry( org - indent, dir, indent + lenSep ) ); + *end = DIRSEPARATOR; + curDir = end + 1; + indent += indentSize; + } + + cur = dirs->getCount() - 1; + + end = strrchr( dir, DIRSEPARATOR ); + char path[PATH_MAX]; + strncpy( path, dir, size_t(end-dir+1) ); + end = path + unsigned(end-dir)+1; + + // SET: Insert them sorted + // SET: 1) collect them + TStringCollection *col = ListDirectory( path, end ); + + // SET: 2) insert sorted + Boolean isFirst = True; + int cnt = col->getCount(); + for( int j = 0; j < cnt; j++ ) + { + char *s = (char *) col->at(j); + unsigned ls = strlen( s ); + if( isFirst ) + { + memcpy( org, firstDir, lenSep ); + isFirst = False; + } + else + memcpy( org, middleDir, lenSep ); + memcpy( name, s, ls + 1 ); + memcpy( end , s, ls + 1 ); + ls += indent + lenSep; + if( ls > maxLen ) + maxLen = ls; + dirs->insert( new TDirEntry( org - indent, path, indent + lenSep ) ); + } + + // SET: Update hz scroll bar range + if( hScrollBar ) + hScrollBar->setRange( 0, maxLen - size.x + 1 ); + // SET: Reset incremental search + incPos = 0; + + CLY_destroy(col); + + char *p = dirs->at(dirs->getCount()-1)->text(); + char *i = strchr( p, graphics[0] ); + if( i == 0 ) + { + i = strchr( p, graphics[1] ); + if( i != 0 ) + *i = graphics[0]; + } + else + { + *(i+1) = graphics[2]; + *(i+2) = graphics[2]; + } +} + +void TDirListBox::newDirectory( const char *str ) +{ + strcpy( dir, str ); + TDirCollection *dirs = new TDirCollection( 5, 5 ); + #ifdef CLY_HaveDriveLetters + #if defined(TVCompf_djgpp) || defined(TVComp_BCPP) + // SET: Old programs created for original TV can pass backslashes here + // and the code in showDirs assumes they are all forward. + for (int i=0; dir[i]; i++) + { + if (dir[i]=='\\') + dir[i]='/'; + } + #endif + const char *drives = _("Drives"); + dirs->insert( new TDirEntry( drives, drives ) ); + if( strcmp( dir, drives ) == 0 ) + showDrives( dirs ); + else + #endif // CLY_HaveDriveLetters + showDirs( dirs ); + newList( dirs ); + focusItem( cur ); +} + +void TDirListBox::setState( ushort nState, Boolean enable ) +{ + TListBox::setState( nState, enable ); + if( (nState & sfFocused) != 0 ) + message(owner, evCommand, cmDirSelection, (void *)enable); +} + +#if !defined( NO_STREAM ) +TStreamable *TDirListBox::build() +{ + return new TDirListBox( streamableInit ); +} +#endif // NO_STREAM + + diff --git a/tvision/classes/tdisplay.cc b/tvision/classes/tdisplay.cc new file mode 100644 index 0000000..0bef192 --- /dev/null +++ b/tvision/classes/tdisplay.cc @@ -0,0 +1,493 @@ +/**[txh]******************************************************************** + + Copyright 2001-2002 by Salvador E. Tropea + This file is covered by the GPL license. + + Module: Display + Include: TDisplay + Comments: + This is the base class for low level screen output. + Most members are pointers to functions defined by each platform dependent +driver. Default members are provided. + This is a complete new file created from concepts that José Angel Sanchez +Caso provide me and coded from scratch. The names of some members are the +same used in original Turbo Vision for compatibility purposes. + +***************************************************************************/ + +//#define DEBUG_CURSOR +#define Uses_stdio +#define Uses_stdlib +#define Uses_TScreen +#define Uses_TVCodePage +#include + +// Remove me please! +int TDisplay::dual_display=0; + +void (*TDisplay::clearScreen)(uchar, uchar)=TDisplay::defaultClearScreen; +ushort (*TDisplay::getRows)() =TDisplay::defaultGetRows; +ushort (*TDisplay::getCols)() =TDisplay::defaultGetCols; +void (*TDisplay::setCrtMode)(ushort mode) =TDisplay::defaultSetCrtMode; +ushort (*TDisplay::getCrtMode)() =TDisplay::defaultGetCrtMode; +void (*TDisplay::getCursorPos)(unsigned &x, unsigned &y) + =TDisplay::defaultGetCursorShape; +void (*TDisplay::setCursorPos)(unsigned x, unsigned y) + =TDisplay::defaultSetCursorShape; +void (*TDisplay::setCursorShape)(unsigned start, unsigned end) + =TDisplay::defaultSetCursorShape; +void (*TDisplay::getCursorShape)(unsigned &start, unsigned &end) + =TDisplay::defaultGetCursorShape; +void (*TDisplay::setCrtModeExt)(char *mode)=TDisplay::defaultSetCrtModeExt; +int (*TDisplay::checkForWindowSize)(void) =TDisplay::defaultCheckForWindowSize; +const char *(*TDisplay::getWindowTitle)(void) =TDisplay::defaultGetWindowTitle; +int (*TDisplay::setWindowTitle)(const char *name) + =TDisplay::defaultSetWindowTitle; +int (*TDisplay::getBlinkState)() =TDisplay::defaultGetBlinkState; +void (*TDisplay::getDisPaletteColors)(int from, int number, TScreenColor *colors) + =TDisplay::defaultGetDisPaletteColors; +int (*TDisplay::setDisPaletteColors)(int from, int number, TScreenColor *colors) + =TDisplay::defaultSetDisPaletteColors; +int (*TDisplay::setCrtModeRes_p)(unsigned w, unsigned h, int fW, int fH) + =TDisplay::defaultSetCrtModeRes; +Boolean (*TDisplay::showBusyState)(Boolean state) + =TDisplay::defaultShowBusyState; +void (*TDisplay::beep)() =TDisplay::defaultBeep; +int TDisplay::argc =0; +char **TDisplay::argv =NULL; +char **TDisplay::environment =NULL; +TScreenColor TDisplay::OriginalPalette[16]; +TScreenColor TDisplay::ActualPalette[16]; +char TDisplay::paletteModified =0; +char TDisplay::avoidMoire =0; +uint32 TDisplay::opts1 =0; +TVCodePage *TDisplay::codePage =NULL; +Boolean TDisplay::busyState =False; +TVScreenDriverDetectCallBack TDisplay::dCB =NULL; +TScreenResolution TDisplay::dosModesRes[TDisplayDOSModesNum]= +{ + { 80,25 }, + { 80,28 }, + { 80,30 }, + { 80,34 }, + { 80,35 }, + { 80,40 }, + { 80,43 }, + { 80,50 }, + { 80,60 }, + { 82,25 }, + { 90,30 }, + { 90,34 }, + { 94,30 }, + { 94,34 }, + { 132,25 }, + { 132,43 }, + { 132,50 }, + { 132,60 } +}; +TScreenResolution TDisplay::dosModesCell[TDisplayDOSModesNum]= +{ + { 9,16 }, + { 9,14 }, + { 9,16 }, + { 9,14 }, + { 9,10 }, + { 9,10 }, + { 9, 8 }, + { 9, 8 }, + { 9, 8 }, + { 8,16 }, + { 9,16 }, + { 9,14 }, + { 9,16 }, + { 9,14 }, + { 9,14 }, + { 9,11 }, + { 9,10 }, + { 9, 8 } +}; +int TDisplay::dosModes[TDisplayDOSModesNum]= +{ + smCO80x25, + smCO80x28, + smCO80x30, + smCO80x34, + smCO80x35, + smCO80x40, + smCO80x43, + smCO80x50, + smCO80x60, + smCO82x25, + smCO90x30, + smCO90x34, + smCO94x30, + smCO94x34, + smCO132x25, + smCO132x43, + smCO132x50, + smCO132x60 +}; + +/***************************************************************************** + + Default actions for TDisplay. + +*****************************************************************************/ + +/**[txh]******************************************************************** + Description: Number of columns of the physical screen. +***************************************************************************/ + +ushort TDisplay::defaultGetCols() +{ + return 80; +} + +/**[txh]******************************************************************** + Description: Number of rows of the physical screen. +***************************************************************************/ + +ushort TDisplay::defaultGetRows() +{ + return 25; +} + +/**[txh]******************************************************************** + Description: Erase the screen using this width and height. +***************************************************************************/ + +void TDisplay::defaultClearScreen( uchar, uchar ) +{ +} + +/**[txh]******************************************************************** + Description: Sets the cursor shape, values in percent. +***************************************************************************/ + +void TDisplay::defaultSetCursorShape(unsigned /*start*/, unsigned /*end*/) +{ +} + +/**[txh]******************************************************************** + Description: Gets the cursor shape, values in percent. +***************************************************************************/ + +void TDisplay::defaultGetCursorShape(unsigned &start, unsigned &end) +{ + start=end=0; +} + +/**[txh]******************************************************************** + Description: + Returns information about a legacy DOS mode. + Return: True if the mode is known. +***************************************************************************/ + +Boolean TDisplay::searchDOSModeInfo(ushort mode, unsigned &w, unsigned &h, + int &fW, int &fH) +{ + int i; + for (i=0; i>8); + #ifdef DEBUG_CURSOR + fprintf(stderr,"Seteando 0x%0X => %X %X\n",val,val & 0xFF,val>>8); + #endif +} + +ushort TDisplay::getCursorType() +{ + unsigned start,end; + getCursorShape(start,end); + #ifdef DEBUG_CURSOR + fprintf(stderr,"Obteniendo: start %X end %X => 0x%0X\n",start,end,(start | (end<<8))); + #endif + return (ushort)(start | (end<<8)); +} + +void TDisplay::setArgv(int aArgc, char **aArgv, char **aEnvir) +{ + argc=aArgc; + argv=aArgv; + environment=aEnvir; +} + +Boolean TDisplay::searchClosestRes(TScreenResolution *res, unsigned x, + unsigned y, unsigned cant, unsigned &pos) +{ + unsigned i, minDif, indexMin, dif; + int firstXMatch=-1; + // Look for an exact match of width + for (i=0; i + +/**[txh]******************************************************************** + + Description: + Copies count bytes from source to the data buffer starting at indent. The +function uses the provided attribute, but if the attribute is 0 the attribute +in the buffer is unmodified.@p + Added a check to avoid writings passing the end of the buffer.@p + +***************************************************************************/ + +void TDrawBuffer::moveBuf(unsigned indent, const void *source, + unsigned attr, unsigned count) + +{ + if (!count || (indent >= (unsigned)maxViewWidth)) return; + if (count+indent > (unsigned)maxViewWidth) + count = maxViewWidth - indent; + + ushort *dest = &data[indent]; + const uchar *s = (const uchar *)source; + + if (attr) + { + while (count-- && *s) + { + ((uchar *)dest)[0] = *s++; + ((uchar *)dest++)[1] = (uchar)attr; + } + } + else + { + while (count-- && *s) + { + *(uchar *)dest++ = *s++; + } + } +} + +/**[txh]******************************************************************** + + Description: + Fills count bytes in the buffer starting at the indent position. If the +attribute is 0 the original is left unchanged. If the character is 0 only +the attribute is used.@p + Added a check to avoid writings passing the end of the buffer.@p + +***************************************************************************/ + +void TDrawBuffer::moveChar(unsigned indent, char c, unsigned attr, + unsigned count ) +{ + if (!count || (indent >= (unsigned)maxViewWidth)) return; + if (count+indent > (unsigned)maxViewWidth) + count = maxViewWidth - indent; + + ushort *dest=&data[indent]; + + if (attr) + { + if (c) + { + while (count--) + { + ((uchar*)dest)[0] = c; + ((uchar*)dest++)[1] = attr; + } + } + else + { + dest=(ushort *)((uchar *)dest+1); + while (count--) + { + *(uchar *)dest++ = attr; + } + } + } + else + { + while (count--) + { + *(uchar *)dest++ = c; + } + } +} + +/**[txh]******************************************************************** + + Description: + That's the same as moveStr but the attrs parameter holds two attributes +the lower 8 bits are the normal value and the upper 8 bits define the +attribute to be used for text enclosed by ASCII 126. @x{::moveStr}.@p + The routine was modified to avoid writes passing the end of the buffer. +Additionally was re-writed in assembler (I guess the Borland's original code +was assembler, but I didn't take a look to it) because the check slow downs +the routine so I wanted to avoid a lose in performance. SET. + +***************************************************************************/ + +void TDrawBuffer::moveCStr( unsigned indent, const char *str, unsigned attrs ) +{ +#if !defined(TVCPU_x86) || !defined(TVComp_GCC) +//$todo: implement it in asm for Win32 + uchar bh = attrs >> 8, ah = attrs & 0xff; + uchar al; + ushort *dest = data+indent; + ushort *end = data+maxViewWidth; + while (*str && dest= maxViewWidth ? \n\ + cmpl %%esi,%%edi \n\ + jae 2f \n\ + \n\ + incl %%edx \n\ + // character == '~' ? \n\ + cmpb $126,%%al \n\ + jne 0f \n\ + // exchange the attributes \n\ + movb %%ah,%%al \n\ + movb %%bh,%%ah \n\ + movb %%al,%%bh \n\ + jmp 1f \n\ + .align 2,0x90 \n\ + \n\ +0: \n\ + movw %%ax,(%%edi) \n\ + addl $2,%%edi \n\ + \n\ +1: \n\ + movb (%%edx),%%al \n\ + cmpb $0,%%al \n\ + jne 3b \n\ +2: \n\ + popl %%ebx \n\ + " : : "D"(&data[indent]), "S"(&data[maxViewWidth]), "d"(str), "a"(attrs) + //: "%ebx" I save EBX because 2.7.x forgets it + ); +#endif +} + +/**[txh]******************************************************************** + + Description: + Writes a string in the buffer with the provided attribute. The routine +copies until the EOS is found or the buffer is filled.@p + Modified to avoid writes passing the end of the buffer. Optimized for +32 bits. Translated to asm just for fun, I think is a little bit faster. +SET. + +***************************************************************************/ + +void TDrawBuffer::moveStr( unsigned indent, const char *str, unsigned attr ) +{ +#if !defined(TVCPU_x86) || !defined(TVComp_GCC) +//$todo: implement it in asm + ushort *dest = data+indent; + ushort *end = data+maxViewWidth; + while (*str && dest + +inline int isWordChar( int ch ) +{ // SET: changed by the uchar version + return ucisalnum(ch) || ch == '_'; +} + +/* SET: I changed the symbols here by the new keyboard definitions to make + it uniform, I could use the original */ +const ushort firstKeys[] = +{ + 39, + kbCtA, cmWordLeft, + kbCtC, cmPageDown, + kbCtD, cmCharRight, + kbCtE, cmLineUp, + kbCtF, cmWordRight, + kbCtG, cmDelChar, + kbCtH, cmBackSpace, + kbCtK, 0xFF02, + kbCtL, cmSearchAgain, + kbCtM, cmNewLine, + kbCtO, cmIndentMode, + kbCtQ, 0xFF01, + kbCtR, cmPageUp, + kbCtS, cmCharLeft, + kbCtT, cmDelWord, + kbCtU, cmUndo, + kbCtV, cmInsMode, + kbCtX, cmLineDown, + kbCtY, cmDelLine, + // SET: The hack used by the class to search a command needs to have + // first the codes with modifiers (like Control+Left) and then the code + // without the modifiers (like Left). + kbCtLeft, cmWordLeft, + kbCtRight, cmWordRight, + kbCtPgUp, cmTextStart, + kbCtPgDn, cmTextEnd, + kbCtInsert, cmCopy, + kbCtDelete, cmClear, + kbShInsert, cmPaste, + kbShDelete, cmCut, + kbLeft, cmCharLeft, + kbRight, cmCharRight, + kbHome, cmLineStart, + kbEnd, cmLineEnd, + kbUp, cmLineUp, + kbDown, cmLineDown, + kbPgUp, cmPageUp, + kbPgDn, cmPageDown, + kbDelete, cmDelChar, + kbInsert, cmInsMode, + kbEnter, cmNewLine, + kbBackSpace, cmBackSpace +}; + +/* SET: Here Borland used a bad trick using the ASCII for the ASCII letters + with the new keyboard handling that isn't true. The ASCII reported is the + letter, but the keycode have an arbitrary symbol and it could change from + OS to OS. Currently is the same under DOS and Linux */ +const ushort quickKeys[] = +{ 8, + kbA, cmReplace, + kbC, cmTextEnd, + kbD, cmLineEnd, + kbF, cmFind, + kbH, cmDelStart, + kbR, cmTextStart, + kbS, cmLineStart, + kbY, cmDelEnd +}; + +const ushort blockKeys[] = +{ 5, + kbB, cmStartSelect, + kbC, cmPaste, + kbH, cmHideSelect, + kbK, cmCopy, + kbY, cmCut +}; + +const ushort *keyMap[] = { firstKeys, quickKeys, blockKeys }; + +ushort defEditorDialog( int, ... ); + +#define KeyMap ((const ushort*)(keyMap)) + +const ushort kbModMask=~kbKeyMask; + + +// SET: Quick hack by Robert, should be adapted as the other. The original was +// assembler, not much faster than it. +// I changed the silly assumptions about the keycodes by masks based on values +// defined in headers. +ushort scanKeyMap( const void *keyMap, int keyCode ) +{ + int i=0; + ushort bx,cx,dx,ax; + dx = keyCode; + cx = KeyMap[i++]; + do + { + bx = KeyMap[i++]; + ax = KeyMap[i++]; + if ((bx & kbKeyMask) == (dx & kbKeyMask)) + { + if (!(bx & kbModMask)) return ax; + // SET: Here I changed the methode. That's tricky so if you don't + // understand it don't worry. The idea is that: if I press Ctrl+Shift+ + // Left it should match with Control+Left and not Left. And if I press + // Shift+Left it must match with Left (because nothing is assigned to + // Shift+Left. + //if ((bx & kbModMask) == (dx & kbModMask)) return ax; + if ((bx & kbModMask) & (dx & kbModMask)) return ax; + } + cx--; + } while (cx != 0); + return 0; +} + +#define cpEditor "\x06\x07" + +TEditor::TEditor( const TRect& bounds, + TScrollBar *aHScrollBar, + TScrollBar *aVScrollBar, + TIndicator *aIndicator, + uint32 aBufSize ) : + TView( bounds ), + hScrollBar( aHScrollBar ), + vScrollBar( aVScrollBar ), + indicator( aIndicator ), + bufSize( aBufSize ), + canUndo( True ), + selecting( False ), + overwrite( False ), + autoIndent( False ) , + lockCount( 0 ), + keyState( 0 ) +{ + growMode = gfGrowHiX | gfGrowHiY; + options |= ofSelectable; + eventMask = evMouseDown | evKeyDown | evCommand | evBroadcast; + showCursor(); + initBuffer(); + if( buffer != 0 ) + isValid = True; + else + { + editorDialog( edOutOfMemory ); + bufSize = 0; + isValid = False; + } + setBufLen(0); +} + +TEditor::~TEditor() +{ +} + +void TEditor::shutDown() +{ + doneBuffer(); + TView::shutDown(); +} + +void TEditor::changeBounds( const TRect& bounds ) +{ + setBounds(bounds); + delta.x = max(0, min(delta.x, limit.x - size.x)); + delta.y = max(0, min(delta.y, limit.y - size.y)); + update(ufView); +} + +/* SET: Note that Robert added a tabSize member to the class */ +int TEditor::charPos( uint32 p, uint32 target ) +{ + int pos = 0; + while( p < target ) + { + if( bufChar(p) == '\x9' ) +#if 0 + pos |= 7; +#else + pos += tabSize - (pos % tabSize) -1; +#endif + pos++; + p++; + } + return pos; +} + +uint32 TEditor::charPtr( uint32 p, int target ) +{ + int pos = 0; + while( (pos < target) && (p < bufLen) && (bufChar(p) != '\x0D') && (bufChar(p) != '\x0A') ) + { + if( bufChar(p) == '\x09' ) +#if 0 + pos |= 7; +#else + pos += tabSize - (pos % tabSize) -1; +#endif + pos++; + p++; + } + if( pos > target ) + p--; + return p; +} + +Boolean TEditor::clipCopy() +{ + Boolean res = False; + if( (clipboard != 0) && (clipboard != this) ) + { + res = clipboard->insertFrom(this); + selecting = False; + update(ufUpdate); + } + return res; +} + +void TEditor::clipCut() +{ + if( clipCopy() == True ) + deleteSelect(); +} + +void TEditor::clipPaste() +{ + if( (clipboard != 0) && (clipboard != this) ) + insertFrom(clipboard); +} + + +void TEditor::convertEvent( TEvent& event ) +{ + if( event.what == evKeyDown ) + { + /* SET: Here we had another dirty code. The code assumed some special + values for (A) the modifiers and (B) the keycodes, that's really + bad coding style + if ( (shiftkeys() & 0x03) != 0 && + event.keyDown.charScan.scanCode >= 0x47 && + event.keyDown.charScan.scanCode <= 0x51 + ) + event.keyDown.charScan.charCode = 0;*/ + + // SET: More assumptions were here + ushort key = event.keyDown.keyCode; + if( keyState != 0 ) + { + if( key>=kbCtA && key<=kbCtZ ) + key+=kbA-kbCtA; + if( key>=kbShA && key<=kbShA ) + key+=kbA-kbShA; + } + key = scanKeyMap(keyMap[keyState], key); + keyState = 0; + if( key != 0 ) + { + if( (key & 0xFF00) == 0xFF00 ) + { + keyState = (key & 0xFF); + clearEvent(event); + } + else + { + event.what = evCommand; + event.message.command = key; + } + } + } +} + +Boolean TEditor::cursorVisible() +{ + return Boolean((curPos.y >= delta.y) && (curPos.y < delta.y + size.y)); +} + +void TEditor::deleteRange( uint32 startPtr, + uint32 endPtr, + Boolean delSelect + ) +{ + if( hasSelection() == True && delSelect == True ) + deleteSelect(); + else + { + setSelect(curPtr, endPtr, True); + deleteSelect(); + setSelect(startPtr, curPtr, False); + deleteSelect(); + } +} + +void TEditor::deleteSelect() +{ + insertText( 0, 0, False ); +} + +void TEditor::doneBuffer() +{ + delete buffer; +} + +void TEditor::doSearchReplace() +{ + int i; + do { + i = cmCancel; + if( search(findStr, editorFlags) == False ) + { + if( (editorFlags & (efReplaceAll | efDoReplace)) != + (efReplaceAll | efDoReplace) ) + editorDialog( edSearchFailed ); + } + else + if( (editorFlags & efDoReplace) != 0 ) + { + i = cmYes; + if( (editorFlags & efPromptOnReplace) != 0 ) + { + TPoint c = makeGlobal( cursor ); + i = editorDialog( edReplacePrompt, &c ); + } + if( i == cmYes ) + { + lock(); + insertText( replaceStr, strlen(replaceStr), False); + trackCursor(False); + unlock(); + } + } + } while( i != cmCancel && (editorFlags & efReplaceAll) != 0 ); +} + +void TEditor::doUpdate() +{ + if( updateFlags != 0 ) + { + setCursor(curPos.x - delta.x, curPos.y - delta.y); + if( (updateFlags & ufView) != 0 ) + drawView(); + else + if( (updateFlags & ufLine) != 0 ) + drawLines( curPos.y-delta.y, 1, lineStart(curPtr) ); + if( hScrollBar != 0 ) + hScrollBar->setParams(delta.x, 0, limit.x - size.x, size.x / 2, 1); + if( vScrollBar != 0 ) + vScrollBar->setParams(delta.y, 0, limit.y - size.y, size.y - 1, 1); + if( indicator != 0 ) + indicator->setValue(curPos, modified); + if( (state & sfActive) != 0 ) + updateCommands(); + updateFlags = 0; + } +} + +void TEditor::draw() +{ + if( drawLine != delta.y ) + { + drawPtr = lineMove( drawPtr, delta.y - drawLine ); + drawLine = delta.y; + } + drawLines( 0, size.y, drawPtr ); +} + +void TEditor::drawLines( int y, int count, uint32 linePtr ) +{ + ushort color = getColor(0x0201); + while( count-- > 0 ) + { + ushort b[maxLineLength]; + formatLine( b, linePtr, delta.x+size.x, color ); + writeBuf(0, y, size.x, 1, &b[delta.x]); + linePtr = nextLine(linePtr); + y++; + } +} + +void TEditor::find() +{ + TFindDialogRec findRec( findStr, editorFlags ); + if( editorDialog( edFind, &findRec ) != cmCancel ) + { + strcpy( findStr, findRec.find ); + editorFlags = findRec.options & ~efDoReplace; + doSearchReplace(); + } +} + +uint32 TEditor::getMousePtr( TPoint m ) +{ + TPoint mouse = makeLocal( m ); + mouse.x = max(0, min(mouse.x, size.x - 1)); + mouse.y = max(0, min(mouse.y, size.y - 1)); + return charPtr(lineMove(drawPtr, mouse.y + delta.y - drawLine), + mouse.x + delta.x); +} + +TPalette& TEditor::getPalette() const +{ + static TPalette palette( cpEditor, sizeof( cpEditor )-1 ); + return palette; +} + + +void TEditor::checkScrollBar( const TEvent& event, + TScrollBar *p, + int& d + ) +{ + if( (event.message.infoPtr == p) && (p->value != d) ) + { + d = p->value; + update( ufView ); + } +} + +void TEditor::handleEvent( TEvent& event ) +{ + TView::handleEvent( event ); + //if (macros) macros->handleEvent(event,this); + convertEvent( event ); + Boolean centerCursor = Boolean(!cursorVisible()); + uchar selectMode = 0; + // SET: This way of getting the shift state is deprecated in our port, by + // now works. + if( selecting == True || (TGKey::getShiftState() & (kbRightShiftDown|kbLeftShiftDown)) != 0 ) + selectMode = smExtend; + + switch( event.what ) + { + + case evMouseDown: + if( event.mouse.doubleClick == True ) + selectMode |= smDouble; + + do { + lock(); + if( event.what == evMouseAuto ) + { + TPoint mouse = makeLocal( event.mouse.where ); + TPoint d = delta; + if( mouse.x < 0 ) + d.x--; + if( mouse.x >= size.x ) + d.x++; + if( mouse.y < 0 ) + d.y--; + if( mouse.y >= size.y ) + d.y++; + scrollTo(d.x, d.y); + } + setCurPtr(getMousePtr(event.mouse.where), selectMode); + selectMode |= smExtend; + unlock(); + } while( mouseEvent(event, evMouseMove + evMouseAuto) ); + break; + + case evKeyDown: + if( event.keyDown.charScan.charCode == 9 || + ( event.keyDown.charScan.charCode >= 32 && event.keyDown.charScan.charCode < 255 ) ) + { + lock(); + if( overwrite == True && hasSelection() == False ) + if( curPtr != lineEnd(curPtr) ) + selEnd = nextChar(curPtr); + insertText( &event.keyDown.charScan.charCode, 1, False); + trackCursor(centerCursor); + unlock(); + } + else + return; + break; + + case evCommand: + switch( event.message.command ) + { + case cmInsertText: + insertText(event.message.infoPtr,strlen((char *)event.message.infoPtr),False); + break; + case cmFind: + find(); + break; + case cmReplace: + replace(); + break; + case cmSearchAgain: + doSearchReplace(); + break; + default: + lock(); + switch( event.message.command ) + { + case cmCut: + clipCut(); + break; + case cmCopy: + clipCopy(); + break; + case cmPaste: + clipPaste(); + break; + case cmUndo: + undo(); + break; + case cmClear: + deleteSelect(); + break; + case cmCharLeft: + setCurPtr(prevChar(curPtr), selectMode); + break; + case cmCharRight: + setCurPtr(nextChar(curPtr), selectMode); + break; + case cmWordLeft: + setCurPtr(prevWord(curPtr), selectMode); + break; + case cmWordRight: + setCurPtr(nextWord(curPtr), selectMode); + break; + case cmLineStart: + setCurPtr(lineStart(curPtr), selectMode); + break; + case cmLineEnd: + setCurPtr(lineEnd(curPtr), selectMode); + break; + case cmLineUp: + setCurPtr(lineMove(curPtr, -1), selectMode); + break; + case cmLineDown: + setCurPtr(lineMove(curPtr, 1), selectMode); + break; + case cmPageUp: + setCurPtr(lineMove(curPtr, -(size.y-1)), selectMode); + break; + case cmPageDown: + setCurPtr(lineMove(curPtr, size.y-1), selectMode); + break; + case cmTextStart: + setCurPtr(0, selectMode); + break; + case cmTextEnd: + setCurPtr(bufLen, selectMode); + break; + case cmNewLine: + newLine(); + break; + case cmBackSpace: + deleteRange(prevChar(curPtr), curPtr, True); + break; + case cmDelChar: + deleteRange(curPtr, nextChar(curPtr), True); + break; + case cmDelWord: + deleteRange(curPtr, nextWord(curPtr), False); + break; + case cmDelStart: + deleteRange(lineStart(curPtr), curPtr, False); + break; + case cmDelEnd: + deleteRange(curPtr, lineEnd(curPtr), False); + break; + case cmDelLine: + deleteRange(lineStart(curPtr), nextLine(curPtr), False); + break; + case cmInsMode: + toggleInsMode(); + break; + case cmStartSelect: + startSelect(); + break; + case cmHideSelect: + hideSelect(); + break; + case cmIndentMode: + autoIndent = Boolean(!autoIndent); + break; + default: + unlock(); + return; + } + trackCursor(centerCursor); + unlock(); + break; + } + + case evBroadcast: + switch( event.message.command ) + { + case cmScrollBarChanged: + checkScrollBar( event, hScrollBar, delta.x ); + checkScrollBar( event, vScrollBar, delta.y ); + break; + default: + return; + } + } + clearEvent(event); +} + + +// TEDITOR2.CC + +// inline int isWordChar( int ch ) +// { +// return isalnum(ch) || ch == '_'; +// } + +int countLines( void *buf, uint32 count ) +{ + int ret=0,i=0; + while (count--) if (((const char *)(buf))[i++] == 0x0a) ret++; + return ret; +} + +#define Block ((const char *)(block)) + +uint32 scan( const void *block, uint32 size, const char *str ) +{ + if (!size) return (UINT_MAX); + uint32 ret=0; + while (size--) + { + if (Block[ret] == str[0]) + { + uint32 i=0; + do + { + i++; + if (!str[i]) return (ret); + if (size insCount ) + delLen = selLen - insCount; + } + + uint32 newSize = uint32(bufLen + delCount - selLen + delLen) + length; + + if( newSize > bufLen + delCount ) + if( setBufSize((uint32)(newSize)) == False ) + { + editorDialog( edOutOfMemory ); + return False; + } + + uint32 selLines = countLines( &buffer[bufPtr(selStart)], selLen ); + if( curPtr == selEnd ) + { + if( allowUndo == True ) + { + if( delLen > 0 ) + memmove( + &buffer[curPtr + gapLen - delCount - delLen], + &buffer[selStart], + delLen + ); + insCount -= selLen - delLen; + } + curPtr = selStart; + curPos.y -= selLines; + } + if( delta.y > curPos.y ) + { + delta.y -= selLines; + if( delta.y < curPos.y ) + delta.y = curPos.y; + } + + if( length > 0 ) + memmove( + &buffer[curPtr], + &p[offset], + length + ); + + uint32 lines = countLines( &buffer[curPtr], length ); + curPtr += length; + curPos.y += lines; + drawLine = curPos.y; + drawPtr = lineStart(curPtr); + curPos.x = charPos(drawPtr, curPtr); + if( selectText == False ) + selStart = curPtr; + selEnd = curPtr; + bufLen += length - selLen; + gapLen -= length - selLen; + if( allowUndo == True ) + { + delCount += delLen; + insCount += length; + } + limit.y += lines - selLines; + delta.y = max(0, min(delta.y, limit.y - size.y)); + if( isClipboard() == False ) + modified = True; + setBufSize(bufLen + delCount); + if( selLines == 0 && lines == 0 ) + update(ufLine); + else + update(ufView); + return True; +} + +Boolean TEditor::insertFrom( TEditor *editor ) +{ + return insertBuffer( editor->buffer, + editor->bufPtr(editor->selStart), + editor->selEnd - editor->selStart, + canUndo, + isClipboard() + ); +} + +Boolean TEditor::insertText( const void *text, uint32 length, Boolean selectText ) +{ + return insertBuffer( (char *)text, 0, length, canUndo, selectText); +} + +Boolean TEditor::isClipboard() +{ + return Boolean(clipboard == this); +} + +uint32 TEditor::lineMove( uint32 p, int count ) +{ + uint32 i = p; + p = lineStart(p); + int pos = charPos(p, i); + while( count != 0 ) + { + i = p; + if( count < 0 ) + { + p = prevLine(p); + count++; + } + else + { + p = nextLine(p); + count--; + } + } + if( p != i ) + p = charPtr(p, pos); + return p; +} + +void TEditor::lock() +{ + lockCount++; +} + +void TEditor::newLine() +{ + uint32 p = lineStart(curPtr); + uint32 i = p; + while( i < curPtr && + ( (buffer[i] == ' ') || (buffer[i] == '\x9')) + ) + i++; + insertText(CLY_crlf,CLY_LenEOL,False); + if( autoIndent == True ) + insertText( &buffer[p], i - p, False); +} + +uint32 TEditor::nextLine( uint32 p ) +{ + return nextChar(lineEnd(p)); +} + +uint32 TEditor::nextWord( uint32 p ) +{ + if (isWordChar(bufChar(p))) + while (p < bufLen && isWordChar(bufChar(p))) + p = nextChar(p); + else if (p < bufLen) + p = nextChar(p); + while (p < bufLen && !isWordChar(bufChar(p))) + p = nextChar(p); + return p; +} + +uint32 TEditor::prevLine( uint32 p ) +{ + return lineStart(prevChar(p)); +} + +uint32 TEditor::prevWord( uint32 p ) +{ + while( p > 0 && isWordChar(bufChar(prevChar(p))) == 0 ) + p = prevChar(p); + while( p > 0 && isWordChar(bufChar(prevChar(p))) != 0 ) + p = prevChar(p); + return p; +} + +void TEditor::replace() +{ + TReplaceDialogRec replaceRec( findStr, replaceStr, editorFlags ); + if( editorDialog( edReplace, &replaceRec ) != cmCancel ) + { + strcpy( findStr, replaceRec.find ); + strcpy( replaceStr, replaceRec.replace ); + editorFlags = replaceRec.options | efDoReplace; + doSearchReplace(); + } + +} + +void TEditor::scrollTo( int x, int y ) +{ + x = max(0, min(x, limit.x - size.x)); + y = max(0, min(y, limit.y - size.y)); + if( x != delta.x || y != delta.y ) + { + delta.x = x; + delta.y = y; + update(ufView); + } +} + +Boolean TEditor::search( const char *findStr, ushort opts ) +{ + uint32 pos = curPtr; + uint32 i; + do { + if( (opts & efCaseSensitive) != 0 ) + i = scan( &buffer[bufPtr(pos)], bufLen - pos, findStr); + else + i = iScan( &buffer[bufPtr(pos)], bufLen - pos, findStr); + + if( i != sfSearchFailed ) + { + i += pos; + if( (opts & efWholeWordsOnly) == 0 || + !( + ( i != 0 && isWordChar(bufChar(i - 1)) != 0 ) || + ( i + strlen(findStr) != bufLen && + isWordChar(bufChar(i + strlen(findStr))) + ) + )) + { + lock(); + setSelect(i, i + strlen(findStr), False); + trackCursor(Boolean(!cursorVisible())); + unlock(); + return True; + } + else + pos = i + 1; + } + } while( i != sfSearchFailed ); + return False; +} + +void TEditor::setBufLen( uint32 length ) +{ + bufLen = length; + gapLen = bufSize - length; + selStart = 0; + selEnd = 0; + curPtr = 0; + delta.x = 0; + delta.y = 0; + curPos = delta; + limit.x = maxLineLength; + limit.y = countLines( &buffer[gapLen], bufLen ) + 1; + drawLine = 0; + drawPtr = 0; + delCount = 0; + insCount = 0; + modified = False; + update(ufView); +} + +Boolean TEditor::setBufSize( uint32 newSize ) +{ + return Boolean(newSize <= bufSize); +} + +void TEditor::setCmdState( ushort command, Boolean enable ) +{ + TCommandSet s; + s += command; + if( enable == True && (state & sfActive) != 0 ) + enableCommands(s); + else + disableCommands(s); +} + +void TEditor::setCurPtr( uint32 p, uchar selectMode ) +{ + uint32 anchor; + if( (selectMode & smExtend) == 0 ) + anchor = p; + else if( curPtr == selStart ) + anchor = selEnd; + else + anchor = selStart; + + if( p < anchor ) + { + if( (selectMode & smDouble) != 0 ) + { + p = prevLine(nextLine(p)); + anchor = nextLine(prevLine(anchor)); + } + setSelect(p, anchor, True); + } + else + { + if( (selectMode & smDouble) != 0 ) + { + p = nextLine(p); + anchor = prevLine(nextLine(anchor)); + } + setSelect(anchor, p, False); + } +} + +void TEditor::setSelect( uint32 newStart, uint32 newEnd, Boolean curStart ) +{ + uint32 p; + if( curStart != 0 ) + p = newStart; + else + p = newEnd; + + uchar flags = ufUpdate; + + if( newStart != selStart || newEnd != selEnd ) + if( newStart != newEnd || selStart != selEnd ) + flags = ufView; + + if( p != curPtr ) + { + if( p > curPtr ) + { + uint32 l = p - curPtr; + memmove( &buffer[curPtr], &buffer[curPtr + gapLen], l); + curPos.y += countLines(&buffer[curPtr], l); + curPtr = p; + } + else + { + uint32 l = curPtr - p; + curPtr = p; + curPos.y -= countLines(&buffer[curPtr], l); + memmove( &buffer[curPtr + gapLen], &buffer[curPtr], l); + } + drawLine = curPos.y; + drawPtr = lineStart(p); + curPos.x = charPos(drawPtr, p); + delCount = 0; + insCount = 0; + setBufSize(bufLen); + } + selStart = newStart; + selEnd = newEnd; + update(flags); +} + +void TEditor::setState( ushort aState, Boolean enable ) +{ + TView::setState(aState, enable); + switch( aState ) + { + case sfActive: + if( hScrollBar != 0 ) + hScrollBar->setState(sfVisible, enable); + if( vScrollBar != 0 ) + vScrollBar->setState(sfVisible, enable); + if( indicator != 0 ) + indicator->setState(sfVisible, enable); + updateCommands(); + break; + + case sfExposed: + if( enable == True ) + unlock(); + } +} + +void TEditor::startSelect() +{ + hideSelect(); + selecting = True; +} + +void TEditor::toggleInsMode() +{ + overwrite = Boolean(!overwrite); + setState(sfCursorIns, Boolean(!getState(sfCursorIns))); +} + +void TEditor::trackCursor( Boolean center ) +{ + if( center == True ) + scrollTo( curPos.x - size.x + 1, curPos.y - size.y / 2); + else + scrollTo( max(curPos.x - size.x + 1, min(delta.x, curPos.x)), + max(curPos.y - size.y + 1, min(delta.y, curPos.y))); +} + +void TEditor::undo() +{ + if( delCount != 0 || insCount != 0 ) + { + selStart = curPtr - insCount; + selEnd = curPtr; + uint32 length = delCount; + delCount = 0; + insCount = 0; + insertBuffer(buffer, curPtr + gapLen - length, length, False, True); + } +} + +void TEditor::unlock() +{ + if( lockCount > 0 ) + { + lockCount--; + if( lockCount == 0 ) + doUpdate(); + } +} + +void TEditor::update( uchar aFlags ) +{ + updateFlags |= aFlags; + if( lockCount == 0 ) + doUpdate(); +} + +void TEditor::updateCommands() +{ + setCmdState( cmUndo, Boolean( delCount != 0 || insCount != 0 ) ); + if( isClipboard() == False ) + { + setCmdState(cmCut, hasSelection()); + setCmdState(cmCopy, hasSelection()); + setCmdState(cmPaste, + Boolean(clipboard != 0 && (clipboard->hasSelection())) ); + } + setCmdState(cmClear, hasSelection()); + setCmdState(cmFind, True); + setCmdState(cmReplace, True); + setCmdState(cmSearchAgain, True); +} + +Boolean TEditor::valid( ushort ) +{ + return isValid; +} + +#ifndef NO_STREAM + +void TEditor::write( opstream& os ) +{ + TView::write( os ); + os << hScrollBar << vScrollBar << indicator + << bufSize << (short)canUndo; +} + +void *TEditor::read( ipstream& is ) +{ + TView::read( is ); + short temp; + is >> hScrollBar >> vScrollBar >> indicator + >> bufSize >> temp; + canUndo = Boolean(temp); + selecting = False; + overwrite = False; + autoIndent = False; + lockCount = 0; + keyState = 0; + initBuffer(); + if( buffer != 0 ) + isValid = True; + else + { + TEditor::editorDialog( edOutOfMemory, 0 ); + bufSize = 0; + } + lockCount = 0; + lock(); + setBufLen( 0 ); + return this; +} + +TStreamable *TEditor::build() +{ + return new TEditor( streamableInit ); +} + +TEditor::TEditor( StreamableInit ) : TView( streamableInit ) +{ +} + +#endif + +// SET: The following routines were assembler in the original TVision, Robert +// did just a quick hack. +// Notes: changed 0xd by '\r' and 0xa by '\n'. Seems to work with EOL=\n +// with only one patch. +// EDITS.CC + +char TEditor::bufChar( uint32 p ) +{ + if (p>=curPtr) p+=gapLen; + return buffer[p]; +} + +uint32 TEditor::bufPtr(uint32 p) +{ + if (p= curPtr) gl = gapLen; + #ifdef CLY_UseCrLf + if (buffer[gl+p] == '\n' && buffer[gl+p-1] == '\r') return (p+1); + #endif + return p; +} + +uint32 TEditor::prevChar(uint32 p) +{ + uint32 gl=0; + if (!p) return p; + p--; + if (!p) return p; + if (p >= curPtr) gl = gapLen; + #ifdef CLY_UseCrLf + if (buffer[gl+p] == '\n' && buffer[gl+p-1] == '\r') return (p-1); + #endif + return p; +} + +// SET: Static members. +// EDITSTAT.CC + +ushort defEditorDialog( int, ... ) +{ + return cmCancel; +} + +TEditorDialog TEditor::editorDialog = defEditorDialog; +ushort TEditor::editorFlags = efBackupFiles | efPromptOnReplace; +char TEditor::findStr[maxFindStrLen] = ""; +char TEditor::replaceStr[maxReplaceStrLen] = ""; +TEditor *TEditor::clipboard = 0; +uint32 TEditor::tabSize = 8; diff --git a/tvision/classes/teditorf.cc b/tvision/classes/teditorf.cc new file mode 100644 index 0000000..e4db81e --- /dev/null +++ b/tvision/classes/teditorf.cc @@ -0,0 +1,106 @@ +/* Modified by Robert Hoehne and Salvador Eduardo Tropea for the gcc port */ +/*----------------------------------------------------------*/ +/* */ +/* Turbo Vision 1.0 */ +/* Copyright (c) 1991 by Borland International */ +/* */ +/*----------------------------------------------------------*/ +/***************************************************************************** + + These are the routines that formats the lines before writing to the buffer. +They are a hack, the original TV had it made in assembler (edits.asm) and +Robert did a quick hack. We still using some of this code so isn't too bad +;-) + + JASC -> Jul 2000, endian stuff + +*****************************************************************************/ + +#define Uses_TEditor +#include + +#if defined(TV_BIG_ENDIAN) + #define endianCol( letra, color ) ((((unsigned)letra)<<8) | ((unsigned)color)) +#else + #define endianCol( letra, color ) ((((unsigned)color)<<8) | ((unsigned)letra)) +#endif + +#define CALL if (call10(this,(ushort *)DrawBuf,color,count,offset,LinePtr,bufptr,Width) == False) return + +Boolean call10(const TEditor *edit, ushort *drawBuf, ushort color, int cx, + int &offset, unsigned &lineptr, int &bufptr, int Width) +{ + uchar c; + int count = cx - lineptr; + if (count<=0) return True; + do { + c = edit->buffer[lineptr++]; + if (c == 0x0a || c == 0x0d || c == 0x09) + { + if (c == 0x09) + { + do + { + drawBuf[bufptr++] = endianCol(' ', color); + offset++; +#if 1 + } while (offset & 7); +#else + } while ((offset % TEditor::tabSize) != 0); +#endif + } + else + { + count = Width-offset; + if (count<=0) + return True; + while (count--) + drawBuf[bufptr++] = endianCol(' ', color); + return False; + } + } + else + { + drawBuf[bufptr++] = endianCol(c, color); + offset++; + } + if (offset >= Width) + { + return False; + } + count--; + } while (count); + return True; +} + +#define normalColor (Colors & 0xff) +#define selectColor (Colors >> 8) + +void TEditor::formatLine( void *DrawBuf, uint32 LinePtr, int Width, + ushort Colors ) +{ + int count,offset,bufptr; + ushort color; + bufptr = 0; + offset = 0; + if (selStart > LinePtr) + { + color = normalColor; + count = selStart; + CALL; + } + color = selectColor; + count = curPtr; + CALL; + LinePtr += gapLen; + count = selEnd+gapLen; + CALL; + color = normalColor; + count = bufSize; + CALL; + count = Width-offset; + //if (count<=offset) return; + if (count<1) return; + while (count--) ((ushort *)(DrawBuf))[bufptr++] = endianCol(' ', color); +} + diff --git a/tvision/classes/teditwin.cc b/tvision/classes/teditwin.cc new file mode 100644 index 0000000..9b32d8c --- /dev/null +++ b/tvision/classes/teditwin.cc @@ -0,0 +1,126 @@ +/* Modified by Robert Hoehne and Salvador Eduardo Tropea for the gcc port */ +/*----------------------------------------------------------*/ +/* */ +/* Turbo Vision 1.0 */ +/* Copyright (c) 1991 by Borland International */ +/* */ +/*----------------------------------------------------------*/ +/***************************************************************************** + + That's a window containing an editor. + +*****************************************************************************/ + +#define Uses_TFrame +#define Uses_TWindow +#define Uses_TRect +#define Uses_TIndicator +#define Uses_TEditor +#define Uses_TMemo +#define Uses_TFileEditor +#define Uses_TEditWindow +#define Uses_TEvent +#define Uses_TScrollBar +#define Uses_opstream +#define Uses_ipstream +#include + +const TPoint minEditWinSize = {24, 6}; + +TEditWindow::TEditWindow( const TRect& bounds, + const char *fileName, + int aNumber + ) : + TWindowInit( &TEditWindow::initFrame ) + , TWindow( bounds, 0, aNumber ) +{ + options |= ofTileable; + + TScrollBar *hScrollBar = + new TScrollBar( TRect( 18, size.y - 1, size.x - 2, size.y ) ); + hScrollBar->hide(); + insert(hScrollBar); + + TScrollBar *vScrollBar = + new TScrollBar( TRect( size.x - 1, 1, size.x, size.y - 1 ) ); + vScrollBar->hide(); + insert(vScrollBar); + + TIndicator *indicator = + new TIndicator( TRect( 2, size.y - 1, 16, size.y ) ); + indicator->hide(); + insert(indicator); + + + TRect r( getExtent() ); + r.grow(-1, -1); + editor = new TFileEditor( r, hScrollBar, vScrollBar, indicator, fileName ); + insert(editor); +} + +void TEditWindow::close() +{ + if( editor->isClipboard() == True ) + hide(); + else + TWindow::close(); +} + +const char *TEditWindow::getTitle( short ) +{ + if( editor->isClipboard() == True ) + return _(clipboardTitle); + else if( *(editor->fileName) == EOS ) + return _(untitled); + else + return editor->fileName; +} + +void TEditWindow::handleEvent( TEvent& event ) +{ + TWindow::handleEvent(event); + if( event.what == evBroadcast && event.message.command == cmUpdateTitle ) + { + if( frame != 0 ) + frame->drawView(); + clearEvent(event); + } +} + +void TEditWindow::sizeLimits( TPoint& min, TPoint& max ) +{ + TWindow::sizeLimits(min, max); + min = minEditWinSize; +} + +#ifndef NO_STREAM + +void TEditWindow::write( opstream& os ) +{ + TWindow::write( os ); + os << editor; +} + +void *TEditWindow::read( ipstream& is ) +{ + TWindow::read( is ); + is >> editor; + return this; +} + +TStreamable *TEditWindow::build() +{ + return new TEditWindow( streamableInit ); +} + +TEditWindow::TEditWindow( StreamableInit ) : + TWindowInit( NULL ) + , TWindow( streamableInit ) +{ +} + +#endif + +const char *TEditWindow::clipboardTitle = __("Clipboard"); +const char *TEditWindow::untitled = __("Untitled"); + diff --git a/tvision/classes/tevent.cc b/tvision/classes/tevent.cc new file mode 100644 index 0000000..f270517 --- /dev/null +++ b/tvision/classes/tevent.cc @@ -0,0 +1,223 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +//#define Uses_stdio +#define Uses_string +#define Uses_TEventQueue +#define Uses_TEvent +#define Uses_TScreen +#define Uses_TVCodePage +#include +#include + +TMouse *TEventQueue::mouse = NULL; +// SET: egcs gets upset if we partially initialize structures and egcs +// 2.91.66 even crash under Linux (not in DOS, but prints "(null)"). +TEvent TEventQueue::eventQueue[eventQSize]; +TEvent *TEventQueue::eventQHead = TEventQueue::eventQueue; +TEvent *TEventQueue::eventQTail = TEventQueue::eventQueue; +Boolean TEventQueue::mouseIntFlag = False; + +ushort TEventQueue::eventCount = 0; + +Boolean TEventQueue::mouseEvents = False; +Boolean TEventQueue::mouseReverse = False; +ushort TEventQueue::doubleDelay = 8; +ushort TEventQueue::repeatDelay = 8; +ushort TEventQueue::autoTicks = 0; +ushort TEventQueue::autoDelay = 0; + +MouseEventType TEventQueue::lastMouse; +MouseEventType TEventQueue::curMouse; +MouseEventType TEventQueue::downMouse; +ushort TEventQueue::downTicks = 0; + +TEventQueue::TEventQueue() +{ + // SET: Just in case. Note: I can't debug it! + memset((void *)&eventQueue[0],0,sizeof(TEvent)*eventQSize); + resume(); +} + +static int TEventQueue_suspended = 1; + +void TEventQueue::resume() +{ + if (!TEventQueue_suspended) return; + // SET: We resumed, no matters if mouse fails or not + TEventQueue_suspended = 0; + TGKey::resume(); + mouseEvents = False; + if( !mouse ) + mouse = new TMouse(); + if( mouse->present() == False ) + mouse->resume(); + if( mouse->present() == False ) + return; + mouse->getEvent( curMouse ); + lastMouse = curMouse; + + mouseEvents = True; + mouse->setRange( TScreen::getCols()-1, TScreen::getRows()-1 ); +} + +void TEventQueue::suspend() +{ + if (TEventQueue_suspended) + return; + if (mouse->present()) + mouse->suspend(); + /* RH: I think here is the right place for clearing the + buffer */ + TGKey::clear(); + TGKey::suspend(); + TEventQueue_suspended = 1; +} + +TEventQueue::~TEventQueue() +{ + suspend(); + // SET: Destroy the mouse object + if (mouse) + delete mouse; +} + +#ifdef TVComp_BCPP +// it works better (faster) +#define AUTO_DELAY_VAL 0 +#else +#define AUTO_DELAY_VAL 1 +#endif + +void TEventQueue::getMouseEvent( TEvent& ev ) +{ + if( mouseEvents == True ) + { + + getMouseState( ev ); + + if( ev.mouse.buttons == 0 && lastMouse.buttons != 0 ) + { + ev.what = evMouseUp; +// int buttons = lastMouse.buttons; + lastMouse = ev.mouse; +// ev.mouse.buttons = buttons; + return; + } + + if( ev.mouse.buttons != 0 && lastMouse.buttons == 0 ) + { + if( ev.mouse.buttons == downMouse.buttons && + ev.mouse.where == downMouse.where && + ev.what - downTicks <= doubleDelay ) + ev.mouse.doubleClick = True; + + downMouse = ev.mouse; + autoTicks = downTicks = ev.what; + autoDelay = repeatDelay; + ev.what = evMouseDown; + lastMouse = ev.mouse; + return; + } + + ev.mouse.buttons = lastMouse.buttons; + + if( ev.mouse.where != lastMouse.where ) + { + ev.what = evMouseMove; + lastMouse = ev.mouse; + return; + } + + if( ev.mouse.buttons != 0 && ev.what - autoTicks > autoDelay ) + { + autoTicks = ev.what; + autoDelay = AUTO_DELAY_VAL; + ev.what = evMouseAuto; + lastMouse = ev.mouse; + return; + } + } + + ev.what = evNothing; +} + +void TEventQueue::getMouseState( TEvent & ev ) +{ + if( eventCount == 0 ) + { + TMouse::getEvent(ev.mouse); + ev.what = CLY_Ticks(); + } + else + { + ev = *eventQHead; + if( ++eventQHead >= eventQueue + eventQSize ) + eventQHead = eventQueue; + eventCount--; + } + if( mouseReverse != False && ev.mouse.buttons != 0 && ev.mouse.buttons != 3 ) + ev.mouse.buttons ^= 3; +} + +#ifdef TVCompf_djgpp +#include + +void TEventQueue::mouseInt() +{ + int buttonPress; + + if (THWMouseDOS::getRMCB_InfoDraw(buttonPress)) + mouseIntFlag=True; + if (buttonPress && eventCountwhat =CLY_Ticks(); + eventQTail->mouse=curMouse; + if (++eventQTail>=eventQueue+eventQSize) + eventQTail=eventQueue; + eventCount++; + } + + curMouse=THWMouseDOS::intEvent; +} + +#else + +void TEventQueue::mouseInt() +{ +} + +#endif + + +void TEvent::getKeyEvent() +{ + if (TGKey::kbhit()) + { + TGKey::fillTEvent(*this); + // SET: That's a special case, when the keyboard indicates the event + // is mouse up it means the keyboard forced an event in the mouse module. + if (what==evMouseUp) + getMouseEvent(); + else + { + if (TVCodePage::OnTheFlyRemapInpNeeded() && keyDown.charScan.charCode>32) + keyDown.charScan.charCode=TVCodePage::OnTheFlyInpRemap(keyDown.charScan.charCode); + TGKey::AltInternat2ASCII(*this); + } + } + else + what=evNothing; +} + + diff --git a/tvision/classes/tfilecol.cc b/tvision/classes/tfilecol.cc new file mode 100644 index 0000000..0aed0a5 --- /dev/null +++ b/tvision/classes/tfilecol.cc @@ -0,0 +1,120 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Added options to customize the file sorting by Salvador E. Tropea. + + * + * + */ +#include + +#if defined(TVCompf_djgpp) || defined(TVComp_BCPP) + #include +#endif +#define Uses_string +#define Uses_stdio +#define Uses_dir +#define Uses_TFileCollection +#define Uses_TSearchRec +#include + +// SET: Added to customize the sorting. These values are the values that make +// the class behave like the Turbo Vision help describes. Note that selecting +// fcolCaseSensitive and not using fcolAlphabetical breaks the incremental +// search trick that looks for Shift to look-up directories. +unsigned TFileCollection::sortOptions=fcolParentLast | fcolDirsLast | + fcolCaseInsensitive; + +inline const char *getName( void *k ) +{ + return ((TSearchRec *)k)->name; +} + +inline int attr( void *k ) +{ + return ((TSearchRec *)k)->attr; +} + +// SET: I remade it with 6 possible combinations +int TFileCollection::compare(void *key1, void *key2) +{ + unsigned sort=sortOptions & fcolTypeMask; + unsigned caseInSens=sortOptions & fcolCaseInsensitive; + const char *nKey1=getName(key1),*nKey2=getName(key2); + + // .* files are also special + if ((sortOptions & fcolDotsLast) && nKey1[0]!=nKey2[0]) + { + if (nKey1[0]=='.' && strcmp(nKey1,"..")!=0) return 1; + if (nKey2[0]=='.' && strcmp(nKey2,"..")!=0) return -1; + } + + if (sort==fcolAlphabetical) + { + if (caseInSens) + return strcasecmp(nKey1,nKey2); + else + return strcmp(nKey1,nKey2); + } + + // If the names are equal don't swap + if (caseInSens) + { + if (strcasecmp(nKey1,nKey2)==0) + return 0; + } + else + { + if (strcmp(nKey1,nKey2)==0) + return 0; + } + + // .. is special + if (strcmp(nKey1,"..")==0) + return sortOptions & fcolParentLast ? 1 : -1; + if (strcmp(nKey2,"..")==0) + return sortOptions & fcolParentLast ? -1 : 1; + + // One is a directory, but not the other + if ((attr(key1) & FA_DIREC) && (attr(key2) & FA_DIREC)==0) + return sort==fcolDirsFirst ? -1 : 1; + if ((attr(key2) & FA_DIREC) && (attr(key1) & FA_DIREC)==0) + return sort==fcolDirsLast ? -1 : 1; + + // Both of the same type + if (caseInSens) + return strcasecmp(nKey1,nKey2); + return strcmp(nKey1,nKey2); +} + + +#if !defined( NO_STREAM ) +TStreamable *TFileCollection::build() +{ + return new TFileCollection( streamableInit ); +} + +void TFileCollection::writeItem( void *obj, opstream& os ) +{ + TSearchRec *item = (TSearchRec *)obj; + os << item->attr << (unsigned long)item->time << (unsigned long)item->size; + os.writeString( item->name ); +} + +void *TFileCollection::readItem( ipstream& is ) +{ + TSearchRec *item = new TSearchRec; + unsigned long aux1, aux2; + is >> item->attr >> aux1 >> aux2; + is.readString( item->name, sizeof(item->name) ); + item->time = (time_t)aux1; + item->size = (size_t)aux2; + return item; +} +#endif // NO_STREAM + diff --git a/tvision/classes/tfiledia.cc b/tvision/classes/tfiledia.cc new file mode 100644 index 0000000..5fb82e5 --- /dev/null +++ b/tvision/classes/tfiledia.cc @@ -0,0 +1,326 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Salvador Eduardo Tropea to add more functionality. +Modified by Vadim Beloborodov to be used on WIN32 console + * + * + */ +#define Uses_string +#define Uses_ctype +#include +#define Uses_HaveLFNs +#define Uses_TFileDialog +#define Uses_MsgBox +#define Uses_TRect +#define Uses_TFileInputLine +#define Uses_TButton +#define Uses_T1Label +#define Uses_TFileList +#define Uses_THistory +#define Uses_TScrollBar +#define Uses_TEvent +#define Uses_TFileInfoPane +#define Uses_opstream +#define Uses_ipstream +#define Uses_TStreamableClass +#include + +#include + +// File dialog flags +const int + ffOpen = 0x0001, + ffSaveAs = 0x0002; + +const ushort + cmOpenDialogOpen = 100, + cmOpenDialogReplace = 101; + +TFileDialog::TFileDialog( const char *aWildCard, + const char *aTitle, + const char *inputName, + ushort aOptions, + uchar histId + ) : + TWindowInit( &TFileDialog::initFrame ), + TDialog( TRect( 15, 1, 64, 21 ), aTitle ), + directory( 0 ) +{ // SET: Enlarged the window 1 line and added 1 line to the list moving + // labels 1 line up + options |= ofCentered; + // SET: Allow it to grow + growMode = gfGrowAll; + flags |= wfGrow | wfZoom; + strcpy( wildCard, aWildCard ); + + fileName = new TFileInputLine( TRect( 3, 2, 31, 3 ), PATH_MAX ); + strcpy( fileName->data, wildCard ); + fileName->growMode=gfGrowHiX; + insert( fileName ); + + insert( new T1Label( 2, 1, inputName, fileName ) ); + THistory *his=new THistory(TRect(31,2,34,3),fileName,histId); + // SET: This and more settings to make it grow nicely + his->growMode=gfGrowLoX | gfGrowHiX; + insert(his); + + int longNames=CLY_HaveLFNs(); // SET + TScrollBar *sb = longNames ? + new TScrollBar( TRect( 34, 5, 35, 16 ) ) : + new TScrollBar( TRect( 3, 15, 34, 16 ) ); + insert( sb ); + insert(fileList=new TFileList(TRect(3,5,34,longNames ? 16 : 15),sb)); + fileList->growMode=gfGrowHiX | gfGrowHiY; + + insert( new T1Label( 2, 4, __("~F~iles"), fileList ) ); + + ushort opt = bfDefault; + TRect r( 35, 2, 46, 4 ); + + TButton *bt; + #define AddButton(flag,name,command)\ + if (aOptions & flag) {\ + bt=new TButton(r,name,command,opt); \ + bt->growMode=gfGrowLoX | gfGrowHiX; \ + insert(bt); opt=bfNormal; r.a.y+=2; r.b.y+=2; } + + AddButton(fdOpenButton,__("~O~pen"),cmFileOpen) + AddButton(fdOKButton,__("~O~K"),cmFileOpen) + AddButton(fdAddButton,__("~A~dd"),cmFileOpen) + AddButton(fdSelectButton,__("~S~elect"),cmFileSelect) + AddButton(fdReplaceButton,__("~R~eplace"),cmFileReplace) + AddButton(fdClearButton,__("~C~lear"),cmFileClear) + + bt=new TButton(r,aOptions & fdDoneButton ? __("Done") : __("Cancel"), + cmCancel,bfNormal); + bt->growMode=gfGrowLoX | gfGrowHiX; + insert(bt); + r.a.y += 2; + r.b.y += 2; + + if( (aOptions & fdHelpButton) != 0 ) + { + bt=new TButton(r,__("~H~elp"),cmHelp,bfNormal); + bt->growMode=gfGrowLoX | gfGrowHiX; + insert(bt); + r.a.y += 2; + r.b.y += 2; + } + + TFileInfoPane *fip=new TFileInfoPane(TRect(1,16,48,19)); + //fip->growMode=gfGrowHiX | gfGrowHiY; + fip->growMode=gfGrowHiX | gfGrowHiY | gfGrowLoY; + insert(fip); + + selectNext( False ); + if( (aOptions & fdNoLoadDir) == 0 ) + readDirectory(); + else + setUpCurDir(); // SET: We must setup the current directory anyways +} + +// SET: Avoid a size smaller than the starting one +void TFileDialog::sizeLimits(TPoint& min, TPoint& max) +{ + TDialog::sizeLimits(min,max); + min.x=64-15; + min.y=21-1; +} + +TFileDialog::~TFileDialog() +{ + DeleteArray((char *)directory); +} + +void TFileDialog::shutDown() +{ + fileName = 0; + fileList = 0; + TDialog::shutDown(); +} + +static void trim( char *dest, const char *src ) +{ + const char *end = NULL; + while( *src != EOS && ucisspace( *src ) ) + src++; + { +/* when a filename contains spaces (not tested) */ + end = src + strlen(src) - 1; + if (end < src) end = src; + else + { + while (end > src && ucisspace(*end)) end--; + } + } + while( *src != EOS && src <= end ) + *dest++ = *src++; + *dest = EOS; +} + +void TFileDialog::getFileName( char *s ) +{ + char buf[PATH_MAX]; + + trim( buf, fileName->data ); + if ( CLY_IsRelativePath( buf ) ) + { + strcpy( buf, directory ); + trim( buf + strlen(buf), fileName->data ); + } + CLY_fexpand( buf ); + strcpy( s, buf ); +} + +void TFileDialog::handleEvent(TEvent& event) +{ + TDialog::handleEvent(event); + if( event.what == evCommand ) + switch( event.message.command ) + { + case cmFileOpen: + case cmFileReplace: + case cmFileClear: + case cmFileSelect: + { + endModal(event.message.command); + clearEvent(event); + } + break; + default: + break; + } + // SET: From TV 2.0 + else if( event.what == evBroadcast && event.message.command == cmFileDoubleClicked ) + { + event.what = evCommand; + event.message.command = cmOK; + putEvent( event ); + clearEvent( event ); + } + +} + +void TFileDialog::readDirectory() +{ + fileList->readDirectory( wildCard ); + setUpCurDir(); +} + +void TFileDialog::setUpCurDir() +{ + DeleteArray((char *)directory); + char curDir[PATH_MAX]; + CLY_GetCurDirSlash(curDir); + directory = newStr( curDir ); +} + +void TFileDialog::setData( void *rec ) +{ + TDialog::setData( rec ); + if( *(char *)rec != EOS && CLY_IsWild( (char *)rec ) ) + { + valid( cmFileInit ); + fileName->select(); + } +} + +void TFileDialog::getData( void *rec ) +{ + getFileName( (char *)rec ); +} + +Boolean TFileDialog::checkDirectory( const char *str ) +{ + if( CLY_PathValid( str ) ) + return True; + else + { + messageBox( __("Invalid drive or directory"), mfError | mfOKButton ); + fileName->select(); + return False; + } +} + +Boolean TFileDialog::valid(ushort command) +{ + char fName[PATH_MAX]; + char name[PATH_MAX]; + char dir[PATH_MAX]; + + if (!TDialog::valid(command)) + return False; + + if ((command == cmValid) || (command == cmCancel)) + return True; + + getFileName( fName ); + if (command != cmFileClear) + { + if(CLY_IsWild(fName)) + { + CLY_ExpandPath(fName, dir, name); + if (checkDirectory(dir)) + { + DeleteArray((char *)directory); + directory = newStr(dir); + strcpy(wildCard, name); + if (command != cmFileInit) + fileList->select(); + fileList->readDirectory(directory, wildCard); + } + } + else if (CLY_IsDir(fName)) + { + if (checkDirectory(fName)) + { + delete (char *)directory; + strcat(fName, DIRSEPARATOR_); + directory = newStr(fName); + if (command != cmFileInit) + fileList->select(); + fileList->readDirectory(directory, wildCard); + } + } + else if (CLY_ValidFileName(fName)) + return True; + else + { + messageBox( __("Invalid file name."), mfError | mfOKButton ); + return False; + } + } + else + return True; + return False; // To shut up GCC's warning +} + +#if !defined( NO_STREAM ) +void TFileDialog::write( opstream& os ) +{ + TDialog::write( os ); + os.writeString( wildCard ); + os << fileName << fileList; +} + +void *TFileDialog::read( ipstream& is ) +{ + TDialog::read( is ); + is.readString( wildCard, sizeof(wildCard) ); + is >> fileName >> fileList; + readDirectory(); + return this; +} + +TStreamable *TFileDialog::build() +{ + return new TFileDialog( streamableInit ); +} +#endif // NO_STREAM + diff --git a/tvision/classes/tfileedi.cc b/tvision/classes/tfileedi.cc new file mode 100644 index 0000000..6f57f88 --- /dev/null +++ b/tvision/classes/tfileedi.cc @@ -0,0 +1,370 @@ +/* Modified by Robert Hoehne and Salvador Eduardo Tropea for the gcc port */ +/* Modified by Vadim Beloborodov to be used on WIN32 console */ +/* Modified to compile with gcc v3.x by Salvador E. Tropea, with the help of + Andris Pavenis. */ +/* Modified by Salvador E. Tropea to avoid using C++ streams (just C code) */ +/*----------------------------------------------------------*/ +/* */ +/* Turbo Vision 1.0 */ +/* Copyright (c) 1991 by Borland International */ +/* */ +/*----------------------------------------------------------*/ +#include + +#define Uses_filelength +#define Uses_limits +#define Uses_string +#define Uses_fcntl +#ifdef TVComp_MSC + #include +#else + #define Uses_unistd +#endif +#define Uses_stdio +#define Uses_sys_stat + +#define Uses_TGroup +#define Uses_TEditor +#define Uses_TFileEditor +#define Uses_TEvent +#define Uses_opstream +#define Uses_ipstream +#define Uses_TStreamableClass +#define Uses_IOS_BIN +#include + +UsingNamespaceStd + +inline uint32 min( uint32 u1, uint32 u2 ) +{ + return u1 < u2 ? u1 : u2; +} + +TFileEditor::TFileEditor( const TRect& bounds, + TScrollBar *aHScrollBar, + TScrollBar *aVScrollBar, + TIndicator *aIndicator, + const char *aFileName + ) : + TEditor( bounds, aHScrollBar, aVScrollBar, aIndicator, 4096 ) +{ + if( aFileName == 0 ) + fileName[0] = EOS; + else + { + strcpy( fileName, aFileName ); + if( isValid ) + isValid = loadFile(); + } +} + +void TFileEditor::doneBuffer() +{ + DeleteArray(buffer); +} + +void TFileEditor::handleEvent( TEvent& event ) +{ + TEditor::handleEvent(event); + switch( event.what ) + { + case evCommand: + switch( event.message.command ) + { + case cmSave: + save(); + break; + case cmSaveAs: + saveAs(); + break; + default: + return; + } + break; + default: + return; + } + clearEvent(event); +} + +void TFileEditor::initBuffer() +{ + buffer = new char[bufSize]; +} + +Boolean TFileEditor::loadFile() +{ + int crfound = 0; + char tmp[PATH_MAX]; + FILE *f=fopen(fileName,"rb"); + if( !f ) + { + setBufLen( 0 ); + return True; + } + else + { + #ifdef TVOS_DOS + int i; +/* check for a unix text file (is a heuristic, because only 1024 chars checked */ + { + char tmpbuf[1024]; + long fsize=filelength(fileno(f)); + if (fsize > 1024) fsize = 1024; + fread(tmpbuf,fsize,1,f); + for (i=0;i<1024;i++) + { + if (tmpbuf[i] == '\r') crfound = 1; + else if (tmpbuf[i] == '\n') break; + } + if (crfound) + { + fseek(f,0,SEEK_SET); + } + else + { + int readhandle,writehandle; + fclose(f); + readhandle = open(fileName,O_RDONLY|O_BINARY); + tmpnam(tmp); + writehandle = open(tmp,O_WRONLY|O_CREAT|O_TRUNC|O_TEXT,0600); + while ((fsize = ::read(readhandle,tmpbuf,1024)) > 0) + ::write(writehandle,tmpbuf,fsize); + close(readhandle); + close(writehandle); + f=fopen(tmp,"rb"); + } + } + #endif + long fSize=filelength(fileno(f));; + if( setBufSize((uint32)(fSize)) == False ) + { + editorDialog( edOutOfMemory ); + if (!crfound) remove(tmp); + return False; + } + else + { + if ( fSize > INT_MAX ) + { + fread( &buffer[bufSize - (uint32)(fSize)], INT_MAX, 1, f ); + fread( &buffer[bufSize - (uint32)(fSize) + INT_MAX], + (uint32)(fSize - INT_MAX), 1, f ); + + } + else + fread( &buffer[bufSize - (uint32)(fSize)], (uint32)(fSize), 1, f ); + int error=ferror(f); + if( fclose(f) || error ) + { + editorDialog( edReadError, fileName ); + if (!crfound) remove(tmp); + return False; + } + else + { + setBufLen((uint32)(fSize)); + if (!crfound) remove(tmp); + return True; + } + } + } +} + +Boolean TFileEditor::save() +{ + if( *fileName == EOS ) + return saveAs(); + else + return saveFile(); +} + +Boolean TFileEditor::saveAs() +{ + Boolean res = False; + if( editorDialog( edSaveAs, fileName ) != cmCancel ) + { + CLY_fexpand( fileName ); + message( owner, evBroadcast, cmUpdateTitle, 0 ); + res = saveFile(); + if( isClipboard() == True ) + *fileName = EOS; + } + return res; +} + +static void writeBlock( FILE *f, char *buf, unsigned len ) +{ + while( len > 0 ) + { + int l = len < INT_MAX ? len : INT_MAX; + fwrite( buf, l, 1, f ); + buf += l; + len -= l; + } +} + +// SET: from my editor: +static +int edTestForFile(const char *name) +{ + struct stat st; + + if (stat(name,&st)==0) + return S_ISREG(st.st_mode); + return 0; +} + +Boolean TFileEditor::saveFile() +{ + // SET: That's similar to what I use in TCEdit and is partially a hack + // to avoid fnsplit & fnmerge in Linux (originally from Robert). + if ((editorFlags & efBackupFiles) && + edTestForFile(fileName)) // Forget about it if that's a new file + { + char *dot,*slash; + int flen = strlen(fileName); + char backupName[PATH_MAX]; + strcpy(backupName,fileName); + dot = strrchr(backupName,'.'); + slash = strrchr(backupName,DIRSEPARATOR); + if (dot < slash) // directory has a dot but not the filename + dot = NULL; + if (!dot) + dot = backupName + flen; + strcpy(dot,backupExt); + unlink( backupName ); + rename( fileName, backupName ); + } + + FILE *f=fopen(fileName,"wb"); + + if( !f ) + { + editorDialog( edCreateError, fileName ); + return False; + } + else + { + writeBlock( f, buffer, curPtr ); + writeBlock( f, buffer+curPtr+gapLen, bufLen-curPtr ); + + int error=ferror(f); // SET: Is that needed? Or fclose will inform the error? + if( fclose(f) || error ) + { + editorDialog( edWriteError, fileName ); + return False; + } + else + { + modified = False; + update(ufUpdate); + } + } + return True; +} + +Boolean TFileEditor::setBufSize( uint32 newSize ) +{ + newSize = (newSize + 0x0FFF) & 0xFFFFF000L; + if( newSize != bufSize ) + { + char *temp = buffer; + if( (buffer = new char[newSize]) == 0 ) + { + delete temp; + return False; + } + uint32 n = bufLen - curPtr + delCount; + memcpy( buffer, temp, min( newSize, bufSize ) ); + memmove( &buffer[newSize - n], &temp[bufSize - n], n ); + delete temp; + bufSize = newSize; + gapLen = bufSize - bufLen; + } + return True; +} + +void TFileEditor::shutDown() +{ + setCmdState(cmSave, False); + setCmdState(cmSaveAs, False); + TEditor::shutDown(); +} + +void TFileEditor::updateCommands() +{ + TEditor::updateCommands(); + setCmdState(cmSave, True); + setCmdState(cmSaveAs, True); +} + +Boolean TFileEditor::valid( ushort command ) +{ + if( command == cmValid ) + return isValid; + else + { + if( modified == True ) + { + int d; + if( *fileName == EOS ) + d = edSaveUntitled; + else + d = edSaveModify; + + switch( editorDialog( d, fileName ) ) + { + case cmYes: + return save(); + case cmNo: + modified = False; + return True; + case cmCancel: + return False; + } + } + } + return True; +} + +#ifndef NO_STREAM + +void TFileEditor::write( opstream& os ) +{ + TEditor::write( os ); + os.writeString( fileName ); + os << selStart << selEnd << curPtr; +} + +void *TFileEditor::read( ipstream& is ) +{ + TEditor::read( is ); + is.readString( fileName, sizeof( fileName ) ); + if( isValid ) + { + isValid = loadFile(); + uint32 sStart, sEnd, curs; + is >> sStart >> sEnd >> curs; + if( isValid && sEnd <= bufLen ) + { + setSelect( sStart, sEnd, Boolean(curs == sStart) ); + trackCursor( True ); + } + } + return this; +} + +TStreamable *TFileEditor::build() +{ + return new TFileEditor( streamableInit ); +} + +TFileEditor::TFileEditor( StreamableInit ) : TEditor( streamableInit ) +{ +} + +#endif + +// SET: Changed to lower case because it looks much better when using LFNs +const char *TFileEditor::backupExt = ".bak"; diff --git a/tvision/classes/tfileinf.cc b/tvision/classes/tfileinf.cc new file mode 100644 index 0000000..ef3dd4b --- /dev/null +++ b/tvision/classes/tfileinf.cc @@ -0,0 +1,133 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ +#define Uses_time +#define Uses_stdio +#define Uses_stdlib +#define Uses_string +#define Uses_snprintf + +#define Uses_TFileInputLine +#define Uses_TEvent +#define Uses_TSearchRec +#define Uses_TFileInfoPane +#define Uses_TDrawBuffer +#define Uses_TFileDialog +#define Uses_TPalette +#include + +#define cpInfoPane "\x1E" + +TFileInfoPane::TFileInfoPane( const TRect& bounds ) : + TView(bounds) +{ + eventMask |= evBroadcast; + *(file_block.name) = EOS; // SET: We must have something in case there are no matches +} + +const char * const TFileInfoPane::months[] = + { + "",__("Jan"),__("Feb"),__("Mar"),__("Apr"),__("May"),__("Jun"), + __("Jul"),__("Aug"),__("Sep"),__("Oct"),__("Nov"),__("Dec") + }; + +void TFileInfoPane::draw() +{ + Boolean PM; + TDrawBuffer b; + ushort color; +#if 1 + struct tm *time; +#else + ftime *time; +#endif + char path[PATH_MAX]; + + strcpy( path, ((TFileDialog *)owner)->directory ); + strcat( path, ((TFileDialog *)owner)->wildCard ); + CLY_fexpand( path ); + + color = getColor(0x01); + b.moveChar( 0, ' ', color, size.x ); + b.moveStr( 1, path, color ); + writeLine( 0, 0, size.x, 1, b ); + + b.moveChar( 0, ' ', color, size.x ); + b.moveStr( 1, file_block.name, color ); + + writeLine( 0, 1, size.x, 1, b); + b.moveChar( 0, ' ', color, size.x ); + + if ( *(file_block.name) != EOS ) + { + const int blen=10; + char buf[blen]; + CLY_snprintf(buf,blen,"%ld",(long)file_block.size); + b.moveStr( 14, buf, color ); + + time = localtime(&file_block.time); + if (time) + {// SET: I don't know how many libc in the world behaves in this + // stupid way, but Mingw32 980701-4 does it for some crazy dates. + b.moveStr( 25, _(months[time->tm_mon+1]), color ); + CLY_snprintf(buf,blen,"%02d",time->tm_mday); + b.moveStr( 29, buf, color ); + + b.putChar( 31, ',' ); + CLY_snprintf(buf,blen,"%d",time->tm_year+1900); + b.moveStr( 32, buf, color ); + + PM = Boolean(time->tm_hour >= 12 ); + time->tm_hour %= 12; + + if ( time->tm_hour == 0 ) + time->tm_hour = 12; + CLY_snprintf(buf,blen,"%02d",time->tm_hour); + b.moveStr( 38, buf, color ); + b.putChar( 40, ':' ); + CLY_snprintf(buf,blen,"%02d",time->tm_min); + b.moveStr( 41, buf, color ); + + if ( PM ) + b.moveStr( 43, pmText, color ); + else + b.moveStr( 43, amText, color ); + } + } + writeLine(0, 2, size.x, 1, b ); + b.moveChar( 0, ' ', color, size. x); + writeLine( 0, 3, size.x, size.y-3, b); +} + +TPalette& TFileInfoPane::getPalette() const +{ + static TPalette palette( cpInfoPane, sizeof( cpInfoPane )-1 ); + return palette; +} + +void TFileInfoPane::handleEvent( TEvent& event ) +{ + TView::handleEvent(event); + if( event.what == evBroadcast && event.message.command == cmFileFocused ) + { + file_block = *((TSearchRec *)(event.message.infoPtr)); + drawView(); + } +} + +#if !defined( NO_STREAM ) +TStreamable *TFileInfoPane::build() +{ + return new TFileInfoPane( streamableInit ); +} +#endif // NO_STREAM + diff --git a/tvision/classes/tfileinp.cc b/tvision/classes/tfileinp.cc new file mode 100644 index 0000000..14f5420 --- /dev/null +++ b/tvision/classes/tfileinp.cc @@ -0,0 +1,83 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ +#define Uses_string +#define Uses_dir +#define Uses_TFileInputLine +#define Uses_TEvent +#define Uses_TSearchRec +#define Uses_TFileDialog +#include + +#if defined(TVComp_BCPP) + #include +#endif + +TFileInputLine::TFileInputLine( const TRect& bounds, short aMaxLen ) : + TInputLine( bounds, aMaxLen ) +{ + eventMask = eventMask | evBroadcast; +} + +/**[txh]******************************************************************** + + Description: + Simple routine to join three strings without coping more than max+1 bytes. +The data buffer must support max+1 bytes. The s2 and s3 parameters can be +NULL.@p + It could be implemented with var_args, any interest? + +***************************************************************************/ + +static +void strCat(char *dest, const char *s1, const char *s2, const char *s3, int max) +{ + char *end=dest+max; + + for (;*s1 && destattr & FA_DIREC) != 0 ) + strCat(data,((TSearchRec *)event.message.infoPtr)->name, + DIRSEPARATOR_,((TFileDialog *)owner)->wildCard, + maxLen); + else + strCat(data,((TSearchRec *)event.message.infoPtr)->name,0,0,maxLen); + drawView(); + } +} + +#if !defined( NO_STREAM ) +TFileInputLine::TFileInputLine( StreamableInit ) : + TInputLine( streamableInit) +{ +} + +TStreamable *TFileInputLine::build() +{ + return new TFileInputLine( streamableInit ); +} +#endif // NO_STREAM + diff --git a/tvision/classes/tfilelis.cc b/tvision/classes/tfilelis.cc new file mode 100644 index 0000000..56a06e4 --- /dev/null +++ b/tvision/classes/tfilelis.cc @@ -0,0 +1,623 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Vadim Beloborodov to be used on WIN32 console +Modified by Salvador E. Tropea to exclude .. in parent dir and +exlude some particular files by configuration. + + * + * + */ +#include + +#define Uses_string +#define Uses_stdio +#ifdef TVComp_MSC + #include + #define Uses_glob +#else + #define Uses_unistd +#endif +#define Uses_stdlib +#define Uses_ctype +#define Uses_HaveLFNs +#define Uses_dirent +#define Uses_getcwd +#define Uses_AllocLocal + +#define Uses_TGKey +#define Uses_MsgBox +#define Uses_TFileList +#define Uses_TRect +#define Uses_TSearchRec +#define Uses_TEvent +#define Uses_TGroup +#define Uses_TStreamableClass +#define Uses_TKeys +#define Uses_TKeys_Extended +#define Uses_sys_stat + +#if defined(TVCompf_djgpp) + // DJGPP + #define Uses_fnmatch + #include +#elif defined(TVComp_BCPP) || defined(TVCompf_Cygwin) || defined(TVOS_UNIX) && !defined(TVOSf_QNX4) + // UNIX, Win32/BC++, Win32/Cygwin + #define Uses_glob +#endif + +#include + +#include +#if defined(TVComp_BCPP) +#include +#endif + +TFileList::TFileList( const TRect& bounds, + TScrollBar *aScrollBar) : + TSortedListBox( bounds, 2, aScrollBar ) +{ + if (CLY_HaveLFNs()) + setNumCols(1); +} + +TFileList::~TFileList() +{ + if ( list() ) + CLY_destroy ( list() ); +} + +void TFileList::focusItem( ccIndex item ) +{ + TSortedListBox::focusItem( item ); + message( owner, evBroadcast, cmFileFocused, list()->at(item) ); +} + +// SET: From TV 2.0 +void TFileList::selectItem( ccIndex item ) +{ + message( owner, evBroadcast, cmFileDoubleClicked, list()->at(item) ); +} + +void TFileList::getData( void * ) +{ +} + +void TFileList::setData( void * ) +{ +} + +uint32 TFileList::dataSize() +{ + return 0; +} + +void* TFileList::getKey( const char *s ) +{ + static TSearchRec sR; + + if ((TGKey::getShiftState() & (kbLeftShiftDown | kbRightShiftDown)) || + *s=='.') + sR.attr=FA_DIREC; + else + sR.attr=0; + strcpy( sR.name, s ); + return &sR; +} + +void TFileList::getText( char *dest, ccIndex item, short maxChars ) +{ + TSearchRec *f = (TSearchRec *)(list()->at(item)); + + strncpy( dest, f->name, maxChars ); + dest[maxChars] = '\0'; + if( f->attr & FA_DIREC ) + strcat( dest, DIRSEPARATOR_ ); +} + +void TFileList::handleEvent( TEvent & event ) +{ + TSearchRec trec, *tp; + + TSortedListBox::handleEvent( event ); + if( event.what == evKeyDown ) + { + if( event.keyDown.keyCode == kbLeft ) + { + clearEvent( event ); + /* Move to .. */ + trec.attr = FA_DIREC; + strcpy( trec.name, ".." ); + message( owner, evBroadcast, cmFileFocused, &trec ); + message( owner, evBroadcast, cmFileDoubleClicked, &trec ); + } + else if( event.keyDown.keyCode == kbRight ) + { + clearEvent( event ); + /* Enter dir */ + tp = list()->at(focused); + if( tp->attr & FA_DIREC ) + message( owner, evBroadcast, cmFileDoubleClicked, tp ); + } + } +} + +void TFileList::readDirectory( const char *dir, const char *wildCard ) +{ + char path[PATH_MAX]; + strcpy( path, dir ); + strcat( path, wildCard ); + readDirectory( path ); +} + +void TFileList::setState( ushort aState, Boolean enable ) +{ + TSortedListBox::setState( aState, enable ); + if ( aState == sfFocused && enable ) + { + message( owner, evBroadcast, cmFileFocused, list()->at(focused) ); + } +} + +/******** struct DirSearchRec ********/ +#ifdef TVCompf_djgpp +// DJGPP +typedef struct TSearchRec DirSearchRec; + +struct __dj_DIR { + int num_read; + char *name; + int flags; + struct ffblk ff; + struct dirent de; +}; + +extern "C" size_t _file_time_stamp(unsigned); + +#else +#if defined(TVOS_Win32) && !defined(TVComp_BCPP) && !defined(TVCompf_Cygwin) +// MingW +struct DirSearchRec : public TSearchRec +{ + void readFf_blk(_finddata_t &s) + { + attr = 0; + if (s.attrib & _A_ARCH) + attr = FA_ARCH; + if (s.attrib & _A_SUBDIR) + attr |= FA_DIREC; + strcpy(name, s.name); + size = s.size; + time = s.time_write; + } +}; + +#else +// Linux, BC++/Win32 and CygWin +struct DirSearchRec : public TSearchRec +{ + /* SS: changed */ + void readFf_blk(const char *filename, struct stat &s) + { + attr = FA_ARCH; + if (S_ISDIR(s.st_mode)) attr |= FA_DIREC; + strcpy(name, filename); + size = s.st_size; + time = s.st_mtime; + } +}; +#endif +#endif +/******** end of struct DirSearchRec ********/ + + +// SET: Helper routine to exclude some special files +static +int ExcludeSpecialName(const char *name) +{ + int len=strlen(name); + if ((TFileCollection::sortOptions & fcolHideEndTilde) && name[len-1]=='~') + return 1; + if ((TFileCollection::sortOptions & fcolHideEndBkp) && len>4 && + strcasecmp(name+len-4,".bkp")==0) + return 1; + if ((TFileCollection::sortOptions & fcolHideStartDot) && name[0]=='.') + return 1; + return 0; +} + +/******** void readDirectory( const char *aWildCard ) ********/ +#ifdef TVCompf_djgpp +// DOS+DJGPP target +// this is really faster than the glob methode +void TFileList::readDirectory( const char *aWildCard ) +{ + DIR *dir; + struct dirent *de; + DirSearchRec *p; + TFileCollection *fileList = new TFileCollection( 10, 10 ); + AllocLocalStr(wildcard,strlen(aWildCard)+1); + strcpy(wildcard,aWildCard); + char *slash = strrchr(wildcard,DIRSEPARATOR); + char *path, pathAux[4]; + // SET: Added code to remove .. in the root directory + int removeParent=0; + + if (slash) + { + *slash = 0; + path = wildcard; + if (strlen(path) == 2 && path[1] == ':') + { + path = pathAux; + strcpy(path,wildcard); + strcat(path,"/"); + } + slash++; + if (strlen(path) == 3 && path[1] == ':') + removeParent=1; + } + else + { + slash = wildcard; + path = "."; + char *cwd=getcwd(0,PATH_MAX); + if (cwd) + { + if (strlen(cwd)==3 && cwd[1] == ':') + removeParent=1; + free(cwd); + } + } + dir = opendir(path); + if (dir) + { + while ((de = readdir(dir))) + { + struct ffblk &ff = dir->ff; + char *name=de->d_name; + if (!(ff.ff_attrib & FA_DIREC) && fnmatch(slash,name,0)) continue; + if (strcmp(name,".")==0) continue; + if (removeParent && strcmp(name,"..")==0) continue; + // SET: Special exclusions: + if (ExcludeSpecialName(name)) continue; + p = new DirSearchRec; + strcpy(p->name,name); + p->attr = ff.ff_attrib; + p->size = ff.ff_fsize; + p->time = ((unsigned long)(ff.ff_fdate)) << 16 | (unsigned short)ff.ff_ftime; + p->time = _file_time_stamp(p->time); + fileList->insert(p); + } + closedir(dir); + } + newList(fileList); + if (list()->getCount() > 0) + message( owner, evBroadcast, cmFileFocused, list()->at(0) ); + else + { + static DirSearchRec noFile; + message( owner, evBroadcast, cmFileFocused, &noFile ); + } +} + +#else +#if defined(TVOS_Win32) && !defined(TVComp_BCPP) && !defined(TVCompf_Cygwin) +// Win32+MingW +void TFileList::readDirectory( const char *aWildCard ) +{ + long dir; + _finddata_t de; + DirSearchRec *p; + TFileCollection *fileList = new TFileCollection( 10, 10 ); + AllocLocalStr(wildcard,strlen(aWildCard)+1); + strcpy(wildcard,aWildCard); + char *slash = strrchr(wildcard,DIRSEPARATOR); + char *path, pathAux[4]; + // SET: Added code to remove .. in the root directory + int removeParent=0; + char dirpath[PATH_MAX]; + + if (slash) + { + *slash = 0; + path = wildcard; + if (strlen(path) == 2 && path[1] == ':') + { + path = pathAux; + strcpy(path,wildcard); + strcat(path,DIRSEPARATOR_); + } + strcpy(dirpath,path); + strcat(dirpath,DIRSEPARATOR_"*"); + if (strlen(path) == 3 && path[1] == ':') + removeParent=1; + *slash = DIRSEPARATOR; + } + else + { + slash = wildcard; + path = "."; + char *cwd=getcwd(0,PATH_MAX); + if (cwd) + { + if (strlen(cwd)==3 && cwd[1] == ':') + removeParent=1; + free(cwd); + } + strcpy(dirpath,path); + strcat(dirpath,DIRSEPARATOR_"*"); + } + //find all directories + dir = _findfirst( dirpath, &de ) ; + if (dir!=-1) + { + do + { + if (!(de.attrib & _A_SUBDIR)) continue; + if (strcmp(de.name,".")==0) continue; + if (removeParent && strcmp(de.name,"..")==0) continue; + // SET: Special exclusions: + if (ExcludeSpecialName(de.name)) continue; + p = new DirSearchRec; + p->readFf_blk( de ); + fileList->insert(p); + } + while (_findnext(dir,&de)==0); + _findclose(dir); + } + + //find all files + dir = _findfirst( wildcard, &de ) ; + if (dir!=-1) + { + do + { + if (de.attrib & _A_SUBDIR) continue; + // SET: Special exclusions: + if (ExcludeSpecialName(de.name)) continue; + p = new DirSearchRec; + p->readFf_blk( de ); + fileList->insert(p); + } + while (_findnext(dir,&de)==0); + _findclose(dir); + } + + newList(fileList); + if (list()->getCount() > 0) + message( owner, evBroadcast, cmFileFocused, list()->at(0) ); + else + { + static DirSearchRec noFile; + message( owner, evBroadcast, cmFileFocused, &noFile ); + } +} +#else + +#if defined(TVOSf_QNX4) +void TFileList::readDirectory( const char *aWildCard ) +{ + DIR *dp; + DirSearchRec *p; + char dir[PATH_MAX]; + char file[PATH_MAX]; + char path[PATH_MAX]; + dirent *de; + struct stat s; + + strcpy( path, aWildCard ); + if (!CLY_IsWild(path)) + strcat(path, "*"); + CLY_fexpand( path ); + CLY_ExpandPath(path, dir, file); + TFileCollection *fileList = new TFileCollection( 5, 5 ); + + /* read regular archive files */ + + sprintf(path, "%s.", dir); + if ((dp = opendir(path)) != NULL) + { + while ((de = readdir(dp)) != NULL) + { + /* is it a regular file (not a directory) ? */ + sprintf(path, "%s%s", dir, de->d_name); + if (stat(path, &s) == 0 && S_ISREG(s.st_mode)) + { + if (ExcludeSpecialName(de->d_name)) + continue; + if (fnmatch(file, de->d_name, 0)==0) + { + if ((p = new DirSearchRec) == NULL) + break; + p->readFf_blk(de->d_name, s); + fileList->insert( p ); + } + } + } + closedir(dp); + } + + /* read directories */ + + sprintf(path, "%s.", dir); + if ((dp = opendir(path)) != NULL) + { + while ((de = readdir(dp)) != NULL) + { + /* we don't want these directories */ + + if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) + continue; + + /* is it a directory ? */ + sprintf(path, "%s%s", dir, de->d_name); + if (stat(path, &s) == 0 && S_ISDIR(s.st_mode)) + { + if ((p = new DirSearchRec) == NULL) + break; + p->readFf_blk(de->d_name, s); + fileList->insert( p ); + } + } + closedir(dp); + } + + if( strlen( dir ) > 1 ) + { + p = new DirSearchRec; + if( p != 0 ) + { + sprintf(path, "%s..", dir); + if (stat(path, &s) == 0) + p->readFf_blk("..", s); + else + { + strcpy( p->name, ".." ); + p->size = 0; + p->time = 0x210000uL; + p->attr = FA_DIREC; + } + fileList->insert( p ); + } + } + + newList(fileList); + + if( list()->getCount() > 0 ) + message( owner, evBroadcast, cmFileFocused, list()->at(0) ); + else + { + static DirSearchRec noFile; + message( owner, evBroadcast, cmFileFocused, &noFile ); + } +} + +#else + +// Linux, BC++/Win32 and CygWin +void TFileList::readDirectory( const char *aWildCard ) +{ + /* SS: changed */ + + DIR *dp; + DirSearchRec *p; + char dir[PATH_MAX]; + char file[PATH_MAX]; + char path[PATH_MAX]; + char *np; + dirent *de; + glob_t gl; + struct stat s; + + strcpy( path, aWildCard ); + if (!CLY_IsWild(path)) strcat(path, "*"); + CLY_fexpand( path ); + CLY_ExpandPath(path, dir, file); + TFileCollection *fileList = new TFileCollection( 10, 10 ); + + /* find all filenames that match our wildcards */ + + /* + * The use of 'glob' function was proposed by: + * Rainer Keuchel + * Date: 18 Jan 1997 22:52:12 +0000 + */ + #ifdef TVOSf_Linux + # define __gl_options GLOB_PERIOD + #else + # define __gl_options 0 + #endif + if (glob(path, __gl_options, NULL, &gl) == 0) + { + for (int i = 0; i < (int)gl.gl_pathc; i++) + { + /* is this a regular file ? */ + if (stat(gl.gl_pathv[i], &s) == 0 && S_ISREG(s.st_mode)) + { + /* strip directory part */ + if ((np = strrchr(gl.gl_pathv[i], '/')) != NULL) + np++; + else + np = gl.gl_pathv[i]; + // SET: Special exclusions: + if (ExcludeSpecialName(np)) continue; + p = new DirSearchRec; + p->readFf_blk(np, s); + fileList->insert( p ); + } + } + globfree(&gl); + } + /* now read all directory names */ + + sprintf(path, "%s.", dir); + if ((dp = opendir(path)) != NULL) + { + while ((de = readdir(dp)) != NULL) + { + /* we don't want these directories */ + if (strcmp(de->d_name, ".") == 0 || + strcmp(de->d_name, "..") == 0) continue; + /* is it a directory ? */ + sprintf(path, "%s%s", dir, de->d_name); + if (stat(path, &s) == 0 && S_ISDIR(s.st_mode) && + // SET: Special exclusions: + !ExcludeSpecialName(de->d_name)) + { + p = new DirSearchRec; + p->readFf_blk(de->d_name, s); + fileList->insert( p ); + } + } + closedir(dp); + } + + if ( strlen( dir ) > 1 ) + { + p = new DirSearchRec; + if (p) + { + sprintf(path, "%s..", dir); + if (stat(path, &s)==0) + p->readFf_blk("..", s); + else + { + strcpy( p->name, ".." ); + p->size = 0; + p->time = 0x210000uL; + p->attr = FA_DIREC; + } + fileList->insert( p ); + } + } + #if 0 // I think this will never hapen (new doesn't return 0) + if ( p == 0 ) + messageBox( tooManyFiles, mfOKButton | mfWarning ); + #endif + newList(fileList); + if ( list()->getCount() > 0 ) + message( owner, evBroadcast, cmFileFocused, list()->at(0) ); + else + { + static DirSearchRec noFile; + message( owner, evBroadcast, cmFileFocused, &noFile ); + } +} +#endif // TVOSf_QNX4 +#endif // Linux, BC++/Win32 and CygWin +#endif // !DOS+DJGPP +/******** end of void readDirectory ********/ + +#if !defined( NO_STREAM ) +TStreamable *TFileList::build() +{ + return new TFileList( streamableInit ); +} +#endif // NO_STREAM + diff --git a/tvision/classes/tfilterv.cc b/tvision/classes/tfilterv.cc new file mode 100644 index 0000000..68b746a --- /dev/null +++ b/tvision/classes/tfilterv.cc @@ -0,0 +1,85 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Salvador E. Tropea (to be compatible with TV 2.0) + + * + * + */ +#define Uses_string +#define Uses_limits +#define Uses_stdio +#define Uses_ipstream +#define Uses_opstream +#define Uses_TFilterValidator +#define Uses_MsgBox +#include + +TFilterValidator::TFilterValidator() : + TValidator(), + validChars(NULL) +{ +} + +TFilterValidator::TFilterValidator(const char * chars) : + TValidator() +{ + validChars = newStr(chars); +} + +TFilterValidator::~TFilterValidator() +{ + delete[] validChars; +} + +Boolean TFilterValidator::isValid(const char *S) +{ + int i=0; + while (S[i]) + { + if (!strchr(validChars,S[i])) return False; + i++; + } + return True; +} + +Boolean TFilterValidator::isValidInput(char *S,Boolean) +{ + return TFilterValidator::isValid(S); +} + +void TFilterValidator::error() +{ + messageBox(__("Invalid character in input"),mfError | mfOKButton); +} + +#if !defined( NO_STREAM ) +TFilterValidator::TFilterValidator(StreamableInit) : + TValidator(streamableInit) +{ +} + +TStreamable * TFilterValidator::build() +{ + return (TStreamable *) new TFilterValidator(streamableInit); +} + +void TFilterValidator::write(opstream & os) +{ + TValidator::write(os); + os.writeString(validChars); +} + +void * TFilterValidator::read(ipstream & is) +{ + TValidator::read(is); + validChars = is.readString(); + return this; +} +#endif // NO_STREAM + diff --git a/tvision/classes/tframe.cc b/tvision/classes/tframe.cc new file mode 100644 index 0000000..a141088 --- /dev/null +++ b/tvision/classes/tframe.cc @@ -0,0 +1,386 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Salvador E. Tropea + + * + * + */ +#define Uses_string +#define Uses_stdlib +#define Uses_stdio + +#define Uses_TFrame +#define Uses_TDrawBuffer +#define Uses_TWindow +#define Uses_TRect +#define Uses_TPoint +#define Uses_TEvent +#define Uses_TStreamableClass +#define Uses_TPalette +#include + +#define cpFrame "\x01\x01\x02\x02\x03" + +// SET: Used to disable icon animation +Boolean TFrame::doAnimation = True; + +TFrame::TFrame( const TRect& bounds ) : TView( bounds ) +{ + growMode = gfGrowHiX + gfGrowHiY; + eventMask |= evBroadcast | evMouseUp; +} + +void TFrame::draw() +{ + ushort cFrame, cTitle; + short f, i, l, width; + TDrawBuffer b; + + if( (state & sfActive) == 0 ) + { + cFrame = 0x0101; + cTitle = 0x0002; + f = 0; + } + else + if( (state & sfDragging) != 0 ) + { + cFrame = 0x0505; + cTitle = 0x0005; + f = 0; + } + else + { + cFrame = 0x0503; + cTitle = 0x0004; + f = 9; + } + + cFrame = getColor(cFrame); + cTitle = getColor(cTitle); + + width = size.x; + l = width - 10; + + if( ( ((TWindow *)owner)->flags & (wfClose | wfZoom) ) != 0 ) + l -= 6; + frameLine( b, 0, f, uchar(cFrame) ); + if( ((TWindow *)owner)->number != wnNoNumber ) + { + l -= 4; + if( ( ((TWindow *)owner)->flags & wfZoom ) != 0 ) + i = 7; + else + i = 3; + int number = ((TWindow *)owner)->number; + if (number > 10) i++; + if (number > 100) i++; + if (number > 1000) i++; + char Number[10]; + sprintf(Number,"%d",number); + int j=0; + while (Number[j]) + { + b.putChar( width-i+j, Number[j]); + j++; + } + } + + if( owner != 0 ) + { + const char *title = ((TWindow *)owner)->getTitle(l); + if( title != 0 ) + { + int ls; + l = max(width-10,0); + ls = strlen(title); + if (ls>l) + { + i = (width - l) >> 1; + b.moveBuf( i-1, " ..", cTitle, 3 ); + b.moveBuf( i+2, &title[ls-l+2], cTitle, l ); + b.putChar( i+l, ' ' ); + b.putChar( i+l+1, ' ' ); + } + else + { + l=ls; + i = (width - l) >> 1; + b.putChar( i-1, ' ' ); + b.moveBuf( i, title, cTitle, l ); + b.putChar( i+l, ' ' ); + } + } + } + + if( (state & sfActive) != 0 ) + { + if( ( ((TWindow *)owner)->flags & wfClose ) != 0 ) + b.moveCStr( 2, closeIcon, cFrame ); + if( ( ((TWindow *)owner)->flags & wfZoom ) != 0 ) + { + TPoint minSize, maxSize; + owner->sizeLimits( minSize, maxSize ); + if( owner->size == maxSize ) + b.moveCStr( width-5, unZoomIcon, cFrame ); + else + b.moveCStr( width-5, zoomIcon, cFrame ); + } + } + + writeLine( 0, 0, size.x, 1, b ); + for( i = 1; i <= size.y - 2; i++ ) + { + frameLine( b, i, f + 3, cFrame ); + writeLine( 0, i, size.x, 1, b ); + } + frameLine( b, size.y - 1, f + 6, cFrame ); + if( (state & sfActive) != 0 ) + if( ( ((TWindow *)owner)->flags & wfGrow ) != 0 ) + b.moveCStr( width-2, dragIcon, cFrame ); + writeLine( 0, size.y - 1, size.x, 1, b ); +} + +TPalette& TFrame::getPalette() const +{ + static TPalette palette( cpFrame, sizeof( cpFrame )-1 ); + return palette; +} + +void TFrame::dragWindow( TEvent& event, uchar mode ) +{ + TRect limits; + TPoint min, max; + + limits = owner->owner->getExtent(); + owner->sizeLimits( min, max ); + owner->dragView( event, owner->dragMode | mode, limits, min, max ); + clearEvent( event ); +} + +const int ciClose=0, ciZoom=1; + +void TFrame::drawIcon( int bNormal, const int ciType ) +{ + ushort cFrame; + + if( (state & sfActive) == 0 ) + cFrame = 0x0101; + else + if( (state & sfDragging) != 0 ) + cFrame = 0x0505; + else + cFrame = 0x0503; + + cFrame = getColor(cFrame); + + switch( ciType ) + { + // Close icon + case ciClose: + { + TDrawBuffer drawBuf; + drawBuf.moveCStr( 0, bNormal ? closeIcon : animIcon, cFrame ); + writeLine( 2, 0, 3, 1, drawBuf ); + } + break; + // Zoom icon + //case ciZoom: + default: + { + TPoint minSize, maxSize; + owner->sizeLimits( minSize, maxSize ); + + TDrawBuffer drawBuf; + drawBuf.moveCStr( 0, bNormal ? ( (owner->size == maxSize) ? unZoomIcon : zoomIcon ) : animIcon, cFrame ); + writeLine( size.x - 5, 0, 3, 1, drawBuf ); + } + break; + } +} + +// SET: Some helpers to make the code easier to understand +#define mouseOverClose() ( mouse.y == 0 && mouse.x >= 2 && mouse.x <= 4 ) +#define mouseOverZoom() ( mouse.y == 0 && ( mouse.x >= size.x - 5 ) && \ + ( mouse.x <= size.x - 3 ) ) +#define mouseOverGrow() ( ( mouse.x >= size.x - 2 ) && ( mouse.y >= size.y - 1 ) ) +#define ownerFlags() ( ((TWindow *)owner)->flags ) + + +void TFrame::handleEvent( TEvent& event ) +{ + TView::handleEvent(event); + // This version incorporates Eddie changes to "animate" the close and zoom icons. + if( (event.what & (evMouseDown | evMouseUp)) && (state & sfActive) ) + { + TPoint mouse = makeLocal( event.mouse.where ); + if( mouse.y == 0 ) + { // Close icon + if( ( ownerFlags() & wfClose ) && mouseOverClose() ) + { + if( doAnimation ) + { // Animated version, capture the focus until the button is released + do + { + mouse = makeLocal( event.mouse.where ); + drawIcon( !mouseOverClose(), ciClose ); + } while( mouseEvent( event, evMouseMove ) ); + + if( event.what == evMouseUp && mouseOverClose() ) + { + putEvent( evCommand, cmClose, owner ); + clearEvent( event ); + drawIcon( 1, ciClose ); + } + } + else + { // Not animated + if( event.what == evMouseUp ) + putEvent( evCommand, cmClose, owner ); + clearEvent( event ); + } + } + else + { // Double click on the upper line or zoom icon + if ( event.mouse.doubleClick || + ( ( ownerFlags() & wfZoom ) && mouseOverZoom() ) ) + { + if ( event.mouse.doubleClick ) + { + putEvent( evCommand, cmZoom, owner ); + clearEvent( event ); + } + else + { + if( doAnimation ) + { // Animated version, capture the focus until the button is released + do + { + mouse = makeLocal( event.mouse.where ); + drawIcon( !mouseOverZoom(), ciZoom ); + + } while( mouseEvent( event, evMouseMove ) ); + + if( ( event.what == evMouseUp ) && mouseOverZoom() ) + { + putEvent( evCommand, cmZoom, owner ); + clearEvent( event ); + drawIcon( 1, ciZoom ); + } + } + else + { // Not animated + if( event.what == evMouseUp ) + putEvent( evCommand, cmZoom, owner ); + clearEvent( event ); + } + } + } + else + // Click on the upper line (move) + if( (ownerFlags() & wfMove) && (event.what & evMouseDown) ) + dragWindow( event, dmDragMove ); + } + } + else + if( (event.what & evMouseDown) && mouseOverGrow() ) + { // Click on the grow corner + if( ownerFlags() & wfGrow ) + dragWindow( event, dmDragGrow ); + } + } +} + +void TFrame::setState( ushort aState, Boolean enable ) +{ + TView::setState( aState, enable ); + if( (aState & (sfActive | sfDragging)) != 0 ) + drawView(); +} + +#if !defined( NO_STREAM ) +TStreamable *TFrame::build() +{ + return new TFrame( streamableInit ); +} + +TFrame::TFrame( StreamableInit ) : TView( streamableInit ) +{ +} +#endif // NO_STREAM + +unsigned char FrameMask[maxViewWidth]; + +void TFrame::frameLine( TDrawBuffer& frameBuf, short y, short n, uchar color ) +{ + ushort si,ax,cx,dx,di; + int i=1; + TView *view; + cx = dx = size.x; + cx -= 2; + FrameMask[0] = initFrame[n]; + while (cx--) FrameMask[i++] = initFrame[n+1]; + FrameMask[i] = initFrame[n+2]; + view = owner->last; + dx--; +lab1: + view = view->next; + if (view == this) goto lab10; + if (!(view->options & ofFramed)) goto lab1; + if (!(view->state & sfVisible)) goto lab1; + ax = y - view->origin.y; + if ((short)(ax)<0) goto lab3; + if (ax>view->size.y) goto lab1; + if (axsize.y) ax = 5; + else ax = 0x0a03; + goto lab4; +lab3: + ax++; + if (ax) goto lab1; + ax = 0x0a06; +lab4: + si = view->origin.x; + di = si + view->size.x; + if (si>1) goto lab5; + si = 1; +lab5: + if (di=di) goto lab1; + FrameMask[si-1] |= (ax & 0x00ff); + ax ^= (((ax & 0xff00) >> 8) & 0x00ff); + FrameMask[di] |= (ax & 0x00ff); + if (!(ax & 0xff00)) goto lab1; + cx = di-si; + while (cx--) FrameMask[si++] |= (((ax & 0xff00) >> 8) & 0x00ff); + goto lab1; +lab10: + dx++; + { + uchar * framechars = (uchar *)malloc(dx); + for (i=0;i + +/***************************************************************************** + Data members initialization +*****************************************************************************/ + +char TGKey::suspended=1; +ushort TGKey::AltSet=0; // Default: Left and right key are different ones +int TGKey::Mode=0; +const char *TGKey::KeyNames[]= +{ +"Unknown", +"A","B","C","D","E","F","G","H","I","J","K", +"L","M","N","O","P","Q","R","S","T","U","V", +"W","X","Y","Z", +"OpenBrace","BackSlash","CloseBrace","Pause","Esc", +"0","1","2","3","4","5","6","7","8","9", +"BackSpace","Tab","Enter","Colon","Quote","Grave", +"Comma","Stop","Slash","Asterisk","Space","Minus", +"Plus","PrnScr","Equal","F1","F2","F3","F4","F5", +"F6","F7","F8","F9","F10","F11","F12","Home", +"Up","PgUp","Left","Right","End","Down","PgDn", +"Insert","Delete","Caret","Admid","DobleQuote", +"Numeral","Dolar","Percent","Amper","OpenPar", +"ClosePar","DoubleDot","LessThan","GreaterThan", +"Question","A_Roba","Or","UnderLine","OpenCurly", +"CloseCurly","Tilde","Macro","WinLeft","WinRight","WinSel", +"Mouse" +}; + +#define NumKeyNames (sizeof(TGKey::KeyNames)/sizeof(char *)) + +/***************************************************************************** + Function pointer members initialization +*****************************************************************************/ + +int (*TGKey::kbhit)(void) =defaultKbhit; +void (*TGKey::clear)(void) =defaultClear; +ushort (*TGKey::gkey)() =defaultGkey; +unsigned (*TGKey::getShiftState)() =defaultGetShiftState; +void (*TGKey::fillTEvent)(TEvent &e) =defaultFillTEvent; +uchar (*TGKey::NonASCII2ASCII)(uchar val) =defaultNonASCII2ASCII; +int (*TGKey::CompareASCII)(uchar val, uchar code)=defaultCompareASCII; +void (*TGKey::SetKbdMapping)(int version) =defaultSetKbdMapping; +int (*TGKey::GetKbdMapping)(int version) =defaultGetKbdMapping; +void (*TGKey::Suspend)() =defaultSuspend; +void (*TGKey::Resume)() =defaultResume; +int (*TGKey::SetCodePage)(int id) =defaultSetCodePage; +int (*TGKey::AltInternat2ASCII)(TEvent &event) =defaultAltInternat2ASCII; + + +/***************************************************************************** + Default behaviors for the members +*****************************************************************************/ + +int TGKey::defaultKbhit() { return 0; } +unsigned TGKey::defaultGetShiftState() { return 0; } +ushort TGKey::defaultGkey() { return 0; } +void TGKey::defaultClear() {} +void TGKey::defaultSuspend() {} +void TGKey::defaultResume() {} +uchar TGKey::defaultNonASCII2ASCII(uchar val) { return val; } +int TGKey::defaultCompareASCII(uchar val, uchar code) { return val==code; } +void TGKey::defaultSetKbdMapping(int version) { Mode=version; } +int TGKey::defaultGetKbdMapping(int /*version*/) { return Mode; } +void TGKey::defaultFillTEvent(TEvent &/*e*/) {}; + +/***************************************************************************** + Real members +*****************************************************************************/ + +void TGKey::suspend() +{ + if (suspended) return; + suspended=1; + Suspend(); +} + +void TGKey::resume() +{ + if (!suspended) return; + suspended=0; + Resume(); +} + +const char *TGKey::NumberToKeyName(unsigned val) +{ + if (valCantDef-1) + return 0; + return altCodes[keyCode]; +} + +ushort TGKey::GetAltCode(uchar c) +{ + int i; + c=NonASCII2ASCII(c); + c=uctoupper(c); + + for (i=0; i' },{ 0x042f,'Z' },{ 0x0430,'f' },{ 0x0431,',' },{ 0x0432,'d' }, +{ 0x0433,'u' },{ 0x0434,'L' },{ 0x0435,'t' },{ 0x0436,';' },{ 0x0437,'p' }, +{ 0x0438,'b' },{ 0x0439,'q' },{ 0x043a,'r' },{ 0x043b,'K' },{ 0x043c,'v' }, +{ 0x043d,'y' },{ 0x043e,'j' },{ 0x043f,'g' },{ 0x0440,'h' },{ 0x0441,'c' }, +{ 0x0442,'n' },{ 0x0443,'e' },{ 0x0444,'a' },{ 0x0445,'[' },{ 0x0446,'w' }, +{ 0x0447,'x' },{ 0x0448,'i' },{ 0x0449,'o' },{ 0x044a,'}' },{ 0x044b,'s' }, +{ 0x044c,'m' },{ 0x044d,'\'' },{ 0x044e,'.' },{ 0x044f,'z' } +}; + + +int TGKey::defaultSetCodePage(int id) +{ + switch (id) + { + case TVCodePage::PC855: + case TVCodePage::PC866: + case TVCodePage::ISORussian: + case TVCodePage::KOI8r: + case TVCodePage::KOI8_CRL_NMSU: + case TVCodePage::CP1251: + case TVCodePage::MacCyr: + case TVCodePage::MacOSUkrainian: + // Not sure about the rest of russian code pages. + FillKeyMapForCP(id,RussianKeyboard,sizeof(RussianKeyboard)/sizeof(stIntCodePairs)); + NonASCII2ASCII=Generic_NonASCII2ASCII; + CompareASCII=Generic_CompareASCII; + AltInternat2ASCII=Generic_AltInternat2ASCII; + break; + case TVCodePage::PC737: + case TVCodePage::PC869: + case TVCodePage::CP1253: + case TVCodePage::ISOGreek: + FillKeyMapForCP(id,GreekKeyboard,sizeof(GreekKeyboard)/sizeof(stIntCodePairs)); + NonASCII2ASCII=Generic_NonASCII2ASCII; + CompareASCII=Generic_CompareASCII; + AltInternat2ASCII=Generic_AltInternat2ASCII; + break; + default: + NonASCII2ASCII=defaultNonASCII2ASCII; + CompareASCII=defaultCompareASCII; + AltInternat2ASCII=defaultAltInternat2ASCII; + return 0; + } + return 1; +} + +uchar TGKey::KeyMap[128]; + +static +int compare(const void *v1, const void *v2) +{ + stIntCodePairs *p1=(stIntCodePairs *)v1; + stIntCodePairs *p2=(stIntCodePairs *)v2; + return (p1->unicode>p2->unicode)-(p1->unicodeunicode); +} + +/**[txh]******************************************************************** + + Description: + Fills the KeyMap table using the provided keyboard layout. + +***************************************************************************/ + +void TGKey::FillKeyMapForCP(int id, stIntCodePairs *keyboard, size_t szKb) +{ + stIntCodePairs cp[256]; + TVCodePage::GetUnicodesForCP(id,cp); + ushort *tr=TVCodePage::GetTranslate(id); + int i; + stIntCodePairs s; + for (i=128; i<256; i++) + { + s.unicode=TVCodePage::UnicodeForInternalCode(tr[i]); + void *res=bsearch(&s,keyboard,szKb,sizeof(stIntCodePairs),compare); + KeyMap[i-128]=res ? ((stIntCodePairs *)res)->code : i; + } +} + +uchar TGKey::Generic_NonASCII2ASCII(uchar ascii) +{ + return ascii>=0x80 ? KeyMap[ascii-0x80] : ascii; +} + +int TGKey::Generic_CompareASCII(uchar val, uchar code) +{ + if (val >=0x80) val =KeyMap[val- 0x80]; + if (code>=0x80) code=KeyMap[code-0x80]; + return val==code; +} + +int TGKey::defaultAltInternat2ASCII(TEvent &) +{ + return 0; +} + +#if 0 +#define SP1 kbBackSpace +#define SP2 kbTab +#define SP3 kbEnter +#define SP4 kbEnter +#define SP5 kbEsc +#else +#define SP1 0x80 | kbH +#define SP2 0x80 | kbI +#define SP3 0x80 | kbJ +#define SP4 0x80 | kbM +#define SP5 0x80 | kbOpenBrace +#endif + +const uchar TGKey::kbByASCII[128]= +{ + 0,kbA,kbB,kbC,kbD,kbE,kbF,kbG, + SP1,SP2,SP3,kbK,kbL,SP4,kbN,kbO, + kbP,kbQ,kbR,kbS,kbT,kbU,kbV,kbW, + kbX,kbY,kbZ,SP5,kbBackSlash,kbCloseBrace,kb6,kbMinus, + kbSpace,kbAdmid,kbDobleQuote,kbNumeral,kbDolar,kbPercent,kbAmper,kbQuote, + kbOpenPar,kbClosePar,kbAsterisk,kbPlus,kbComma,kbMinus,kbStop,kbSlash, + kb0,kb1,kb2,kb3,kb4,kb5,kb6,kb7, + kb8,kb9,kbDoubleDot,kbColon,kbLessThan,kbEqual,kbGreaterThan,kbQuestion, + kbA_Roba,kbA,kbB,kbC,kbD,kbE,kbF,kbG, + kbH,kbI,kbJ,kbK,kbL,kbM,kbN,kbO, + kbP,kbQ,kbR,kbS,kbT,kbU,kbV,kbW, + kbX,kbY,kbZ,kbOpenBrace,kbBackSlash,kbCloseBrace,kbCaret,kbUnderLine, + kbGrave,kbA,kbB,kbC,kbD,kbE,kbF,kbG, + kbH,kbI,kbJ,kbK,kbL,kbM,kbN,kbO, + kbP,kbQ,kbR,kbS,kbT,kbU,kbV,kbW, + kbX,kbY,kbZ,kbOpenCurly,kbOr,kbCloseCurly,kbTilde,kbBackSpace +}; + +/**[txh]******************************************************************** + + Description: + When using a "non-ASCII" keyboard the application gets Alt+Non-ASCII. This +routine tries to figure out which key was used and changes the event to +be Alt+ASCII. Example: A greek keyboard can generate Alt+Alfa, in this case +the routine will convert it into Alt+A (because Alfa is in the key that A +is located). + + Return: !=0 if the event was altered. + +***************************************************************************/ + +int TGKey::Generic_AltInternat2ASCII(TEvent &e) +{ + if (e.what==evKeyDown && + e.keyDown.charScan.charCode>=0x80 && + (e.keyDown.keyCode & (kbAltRCode | kbAltLCode)) && + (e.keyDown.keyCode & kbKeyMask)==kbUnkNown) + { + uchar key=KeyMap[e.keyDown.charScan.charCode-0x80]; + if (key<0x80) + { + e.keyDown.keyCode|=kbByASCII[key]; + return 1; + } + } + return 0; +} diff --git a/tvision/classes/tgroup.cc b/tvision/classes/tgroup.cc new file mode 100644 index 0000000..fc5b1d1 --- /dev/null +++ b/tvision/classes/tgroup.cc @@ -0,0 +1,743 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + * + * Modified by Robert H”hne to be used for RHIDE. + +Modified cursor behavior while desktop locked by Salvador E. Tropea (SET) + + * + * + * + */ + +#define Uses_TGroup +#define Uses_TView +#define Uses_TRect +#define Uses_TEvent +#define Uses_opstream +#define Uses_ipstream +#define Uses_TCommandSet +#define Uses_TStreamableClass +#include + +TView *TheTopView = 0; + +TGroup::TGroup( const TRect& bounds ) : + TView(bounds), current( 0 ), last( 0 ), phase( phFocused ), buffer( 0 ), + lockFlag( 0 ), endState( 0 ) +{ + options |= ofSelectable | ofBuffered; + clip = getExtent(); + eventMask = 0xFFFF; +} + +TGroup::~TGroup() +{ +} + +void TGroup::shutDown() +{ + // Avoid problems if a hidden or unselectable TView was forced to be + // selected. Marek Bojarski + resetCurrent(); + TView* p = last; + if( p != 0 ) + do { + TView* T = p->prev(); + CLY_destroy( p ); + p = T; + } while( last != 0 ); + freeBuffer(); + current = 0; + TView::shutDown(); +} + +void doCalcChange( TView *p, void *d ) +{ + TRect r; + ((TGroup *)p)->calcBounds(r, *(TPoint*)d); + ((TGroup *)p)->changeBounds(r); +} + +void TGroup::changeBounds( const TRect& bounds ) +{ + TPoint d; + + d.x = (bounds.b.x - bounds.a.x) - size.x; + d.y = (bounds.b.y - bounds.a.y) - size.y; + if( d.x == 0 && d.y == 0 ) + { + setBounds(bounds); + drawView(); + } + else + { + freeBuffer(); + setBounds( bounds ); + clip = getExtent(); + getBuffer(); + lock(); + forEach( doCalcChange, &d ); + unlock(); + } +} + +void addSubviewDataSize( TView *p, void *T ) +{ + *((uint32 *)T) += ((TGroup *)p)->dataSize(); +} + +uint32 TGroup::dataSize() +{ + unsigned T = 0; + forEach( addSubviewDataSize, &T ); + return T; +} + +void TGroup::remove(TView* p) +{ + ushort saveState; + saveState = p->state; + p->hide(); + removeView(p); + p->owner = 0; + p->next= 0; + if( (saveState & sfVisible) != 0 ) + p->show(); +} + +static int force_redraw = 0; + +void TGroup::CLY_Redraw() +{ + force_redraw++; + redraw(); + force_redraw--; +} + +void TGroup::draw() +{ +/* I have changed it now to force a redraw of all subviews + instead of redrawing from the buffer, when the flag + 'force_redraw' is set. This flag is set by the new member + function 'Redraw' which should be called, when the app wants + a forced redraw of all subviews. +*/ + if (buffer != 0) + { + if (force_redraw) + { + lockFlag++; + redraw(); + lockFlag--; + } + writeBuf( 0, 0, size.x, size.y, buffer ); + } + else + { + getBuffer(); + if (buffer != 0) + { + lockFlag++; + redraw(); + lockFlag--; + writeBuf( 0, 0, size.x, size.y, buffer ); + } + else + { + clip = getClipRect(); + redraw(); + clip = getExtent(); + } + } +} + +void TGroup::drawSubViews( TView* p, TView* bottom ) +{ + while( p != bottom ) + { + p->drawView(); + p = p->nextView(); + } +} + +void TGroup::endModal( ushort command ) +{ + if( (state & sfModal) != 0 ) + endState = command; + else + TView::endModal( command ); +} + +void TGroup::eventError( TEvent& event ) +{ + if (owner != 0 ) + owner->eventError( event ); +} + +ushort TGroup::execute() +{ + do { + endState = 0; + do { + TEvent e; + getEvent( e ); + handleEvent( e ); + if( e.what != evNothing ) + eventError( e ); + } while( endState == 0 ); + } while( !valid(endState) ); + return endState; +} + +ushort TGroup::execView( TView* p ) +{ + if( p == 0 ) + return cmCancel; + + ushort saveOptions = p->options; + TGroup *saveOwner = p->owner; + TView *saveTopView = TheTopView; + TView *saveCurrent= current; + TCommandSet saveCommands; + getCommands( saveCommands ); + TheTopView = p; + p->options = p->options & ~ofSelectable; + p->setState(sfModal, True); + setCurrent(p, enterSelect); + if( saveOwner == 0 ) + insert(p); + + // Just be foolproof + int oldLock=lockFlag; + if (lockFlag) + { + lockFlag=1; unlock(); + } + + ushort retval = p->execute(); + p->setState(sfActive, False); + + // Re-lock if needed + lockFlag=oldLock; + + if( saveOwner == 0 ) + remove(p); + setCurrent(saveCurrent, leaveSelect); + p->setState(sfModal, False); + p->options = saveOptions; + TheTopView = saveTopView; + setCommands(saveCommands); + return retval; +} + +TView *TGroup::first() +{ + if( last == 0 ) + return 0; + else + return last->next; +} + +TView *TGroup::firstMatch( ushort aState, ushort aOptions ) +{ + if( last == 0 ) + return 0; + + TView* temp = last; + while(1) + { + if( ((temp->state & aState) == aState) && + ((temp->options & aOptions) == aOptions)) + return temp; + + temp = temp->next; + if( temp == last ) + return 0; + } +} + +void TGroup::freeBuffer() +{ + if( (options & ofBuffered) != 0 && buffer != 0 ) + { +#if 0 + TVMemMgr::freeDiscardable( buffer ); +#else + DeleteArray(buffer); +#endif + buffer = 0; + } +} + +void TGroup::getBuffer() +{ + if( (state & sfExposed) != 0 ) + if( (options & ofBuffered) != 0 && (buffer == 0 )) +#if 0 + TVMemMgr::allocateDiscardable( (void *&)buffer, size.x * size.y * sizeof(ushort) ); +#else + buffer = new ushort[size.x * size.y]; +#endif +} + +void TGroup::getData(void *rec) +{ + unsigned i = 0; + if (last != 0 ) + { + TView* v = last; + do { + v->getData( ((char *)rec) + i ); + i += v->dataSize(); + v = v->prev(); + } while( v != last ); + } +} + +struct handleStruct +{ + handleStruct( TEvent& e, TGroup& g ) : event( e ), grp( g ) {} + TEvent& event; + TGroup& grp; +}; + +static void doHandleEvent( TView *p, void *s ) +{ + handleStruct *ptr = (handleStruct *)s; + + if( p == 0 || + ( (p->state & sfDisabled) != 0 && + (ptr->event.what & (positionalEvents | focusedEvents)) != 0 + ) + ) + return; + + switch( ptr->grp.phase ) + { + case TView::phPreProcess: + if( (p->options & ofPreProcess) == 0 ) + return; + break; + case TView::phPostProcess: + if( (p->options & ofPostProcess) == 0 ) + return; + break; + default: + break; + } + if( (ptr->event.what & p->eventMask) != 0 ) + p->handleEvent( ptr->event ); +} + +static Boolean hasMouse( TView *p, void *s ) +{ + return p->containsMouse( *(TEvent *)s ); +} + +void TGroup::handleEvent( TEvent& event ) +{ + TView::handleEvent( event ); + + handleStruct hs( event, *this ); + + if( (event.what & focusedEvents) != 0 ) + { + phase = phPreProcess; + forEach( doHandleEvent, &hs ); + + phase = phFocused; + doHandleEvent( current, &hs ); + + phase = phPostProcess; + forEach( doHandleEvent, &hs ); + } + else + { + phase = phFocused; + if( (event.what & positionalEvents) != 0 ) + { + doHandleEvent( firstThat( hasMouse, &event ), &hs ); + } + else + forEach( doHandleEvent, &hs ); + } +} + +void TGroup::insert( TView* p ) +{ + insertBefore( p, first() ); +} + +void TGroup::insertBefore( TView *p, TView *Target ) +{ + if( p != 0 && p->owner == 0 && (Target == 0 || Target->owner == this) ) + { + if( (p->options & ofCenterX) != 0 ) + p->origin.x = (size.x - p->size.x)/2; + if( (p->options & ofCenterY) != 0 ) + p->origin.y = (size.y - p->size.y)/2; + ushort saveState = p->state; + p->hide(); + insertView( p, Target ); + if( (saveState & sfVisible) != 0 ) + p->show(); + } +} + +void TGroup::insertView( TView* p, TView* Target ) +{ + p->owner = this; + if( Target != 0 ) + { + Target = Target->prev(); + p->next = Target->next; + Target->next= p; + } + else + { + if( last== 0 ) + p->next = p; + else + { + p->next = last->next; + last->next = p; + } + last = p; + } +} + +void TGroup::lock() +{ + if( buffer != 0 || lockFlag != 0 ) + lockFlag++; +} + +void TGroup::redraw() +{ + drawSubViews( first(), 0 ); +} + +void TGroup::resetCurrent() +{ + setCurrent( firstMatch( sfVisible, ofSelectable ), normalSelect ); +} + +void TGroup::resetCursor() +{ + if( current != 0 ) + current->resetCursor(); +} + +void TGroup::selectNext( Boolean forwards ) +{ + if( current != 0 ) + { + TView* p = current; + do { + if (forwards) + p = p->next; + else + p = p->prev(); + } while ( !( + (((p->state & (sfVisible + sfDisabled)) == sfVisible) && + (p->options & ofSelectable)) || (p == current) + ) ); + p->select(); + } +} + +void TGroup::selectView( TView* p, Boolean enable ) +{ + if( p != 0 ) + p->setState( sfSelected, enable ); +} + +void TGroup::focusView( TView* p, Boolean enable ) +{ + if( (state & sfFocused) != 0 && p != 0 ) + p->setState( sfFocused, enable ); +} + + + +void TGroup::setCurrent( TView* p, selectMode mode ) +{ + if (current!= p) + { + lock(); + focusView( current, False ); + // Test if focus lost was allowed and focus has really been loose + if ( (mode == normalSelect) && + current && + (current->state & sfFocused) + ) + { + unlock(); + return; + } + if( mode != enterSelect ) + if( current != 0 ) + current->setState( sfSelected, False ); + if( mode != leaveSelect ) + if( p != 0 ) + p->setState( sfSelected, True ); + focusView( p, True ); + current = p; + unlock(); + } +} + +void TGroup::setData(void *rec) +{ + unsigned i = 0; + if( last!= 0 ) + { + TView* v = last; + do { + v->setData( (char *)rec + i ); + i += v->dataSize(); + v = v->prev(); + } while (v != last); + } +} + +static void doExpose( TView *p, void *enable ) +{ + if( (p->state & sfVisible) != 0 ) + p->setState( sfExposed, *(Boolean *)enable ); +} + +struct setBlock +{ + ushort st; + Boolean en; +}; + +static void doSetState( TView *p, void *b ) +{ + p->setState( ((setBlock *)b)->st, ((setBlock *)b)->en ); +} + +void TGroup::setState( ushort aState, Boolean enable ) +{ + setBlock sb; + sb.st = aState; + sb.en = enable; + + TView::setState( aState, enable ); + + if( (aState & (sfActive | sfDragging)) != 0 ) + { + lock(); + forEach( doSetState, &sb ); + unlock(); + } + + if( (aState & sfFocused) != 0 ) + { + if( current != 0 ) + current->setState( sfFocused, enable ); + } + + if( (aState & sfExposed) != 0 ) + { + forEach( doExpose, &enable ); + if( enable == False ) + freeBuffer(); + } +} + +void TGroup::unlock() +{ + if( lockFlag != 0 && --lockFlag == 0 ) + { + drawView(); + // SET: Now is time to hide/show mouse according to + // changes while we were locked. + resetCursor(); + } +} + +Boolean isInvalid( TView *p, void * commandP) +{ + return Boolean( !p->valid( *(ushort *)commandP ) ); +} + +Boolean TGroup::valid( ushort command ) +{ + return Boolean( firstThat( isInvalid, &command ) == 0 ); +} + +ushort TGroup::getHelpCtx() +{ + ushort h = hcNoContext; + if( current!= 0 ) + h = current->getHelpCtx(); + if (h == hcNoContext) + h = TView::getHelpCtx(); + return h; +} + +#if !defined( NO_STREAM ) +static void doPut( TView *p, void *osp ) +{ + *(opstream *)osp << p; +} + +void TGroup::write( opstream& os ) +{ + ushort index; + + TView::write( os ); + TGroup *ownerSave = owner; + owner = this; + int count = indexOf( last ); + os << count; + forEach( doPut, &os ); + if (current == 0) + index = 0; + else + index = indexOf(current); + os << index; + owner = ownerSave; +} + +void *TGroup::read( ipstream& is ) +{ + ushort index; + + TView::read( is ); + clip = getExtent(); + TGroup *ownerSave = owner; + owner = this; + last = 0; + phase = TView::phFocused; + current = 0; + buffer = 0; + lockFlag = 0; + endState = 0; + int count; + is >> count; + TView *tv; + for( int i = 0; i < count; i++ ) + { + is >> tv; + if( tv != 0 ) + insertView( tv, 0 ); + } + owner = ownerSave; + TView *current; + is >> index; + current = at(index); + setCurrent( current, TView::normalSelect ); + return this; +} + +TStreamable *TGroup::build() +{ + return new TGroup( streamableInit ); +} + +TGroup::TGroup( StreamableInit ) : TView( streamableInit ) +{ +} +#endif // NO_STREAM + +// GRP.CC + +TView *TGroup::at( short index ) +{ + TView *temp = last; + while( index-- > 0 ) + temp = temp->next; + return temp; +} + +TView *TGroup::firstThat( Boolean (*func)(TView *, void *), void *args ) +{ + TView *temp = last; + if( temp == 0 ) + return 0; + + do { + temp = temp->next; + if( func( temp, args ) == True ) + return temp; + } while( temp != last ); + return 0; +} + +void TGroup::forEach( void (*func)(TView*, void *), void *args ) +{ + TView *term = last; + TView *temp = last; + if( temp == 0 ) + return; + + TView *next = temp->next; + do { + temp = next; + next = temp->next; + func( temp, args ); + } while( temp != term ); + +} + +short TGroup::indexOf( TView *p ) +{ + if( last == 0 ) + return 0; + + short index = 0; + TView *temp = last; + do { + index++; + temp = temp->next; + } while( temp != p && temp != last ); + if( temp != p ) + return 0; + else + return index; +} + +// TGRMV.CC + +void TGroup::removeView(TView *p) +{ + TView *akt,*view; + if (!last) return; + view = last; + akt = view->next; + while ((akt != p) && (akt != last)) + { + view = akt; + akt = view->next; + } + if (akt == p) + { + akt = p->next; + view->next = akt; + if (last != p) return; + if (akt == p) view = NULL; + last = view; + return; + } + if (akt == last) return; +} + +// SET: TViews will ask us if that's good time to draw cursor changes +Boolean TGroup::canShowCursor() +{ + if (buffer) + { + if (owner) + return owner->canShowCursor(); + return False; + } + return lockFlag ? False : True; +} diff --git a/tvision/classes/thistory.cc b/tvision/classes/thistory.cc new file mode 100644 index 0000000..71fa07f --- /dev/null +++ b/tvision/classes/thistory.cc @@ -0,0 +1,143 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#include +#define Uses_string + +#define Uses_THistory +#define Uses_TKeys +#define Uses_TRect +#define Uses_TEvent +#define Uses_TInputLine +#define Uses_THistoryWindow +#define Uses_opstream +#define Uses_ipstream +#define Uses_TPalette +#include + +#define cpHistory "\x16\x17" + +THistory::THistory( const TRect& bounds, + TInputLine *aLink, + ushort aHistoryId) : + TView(bounds), + link( aLink ), + historyId( aHistoryId ) +{ + options |= ofPostProcess; + eventMask |= evBroadcast; +} + +void THistory::shutDown() +{ + link = 0; + TView::shutDown(); +} + +void THistory::draw() +{ + TDrawBuffer b; + + b.moveCStr( 0, icon, getColor(0x0102) ); + writeLine( 0, 0, size.x, size.y, b ); +} + +TPalette& THistory::getPalette() const +{ + static TPalette palette( cpHistory, sizeof( cpHistory )-1 ); + return palette; +} + +void THistory::handleEvent( TEvent& event ) +{ + THistoryWindow *historyWindow; + TRect r, p; + ushort c; + + TView::handleEvent( event ); + if( event.what == evMouseDown || + ( event.what == evKeyDown && + ctrlToArrow( event.keyDown.keyCode ) == kbDown && + (link->state & sfFocused) != 0 + ) + ) + { + link->select(); + historyAdd( historyId, link->data ); + r = link->getBounds(); + r.a.x--; + r.b.x++; + r.b.y += 7; + r.a.y--; + p = owner->getExtent(); + r.intersect( p ); + r.b.y--; + historyWindow = initHistoryWindow( r ); + if( historyWindow != 0 ) + { + c = owner->execView( historyWindow ); + if( c == cmOK ) + { + char rslt[256]; + historyWindow->getSelection( rslt ); + strncpy( link->data, rslt, link->maxLen ); + link->data[link->maxLen] = EOS; + link->selectAll( True ); + link->drawView(); + } + CLY_destroy( historyWindow ); + } + clearEvent( event ); + } + else + if( event.what == evBroadcast ) + if( (event.message.command == cmReleasedFocus && + event.message.infoPtr == link) || + event.message.command == cmRecordHistory + ) + historyAdd( historyId, link->data ); +} + +THistoryWindow *THistory::initHistoryWindow( const TRect& bounds ) +{ + THistoryWindow *p = new THistoryWindow( bounds, historyId ); + p->helpCtx = link->helpCtx; + return p; +} + +#if !defined( NO_STREAM ) +void THistory::write( opstream& os ) +{ + TView::write( os ); + os << link << historyId; +} + +void *THistory::read( ipstream& is ) +{ + TView::read( is ); + is >> link >> historyId; + return this; +} + +TStreamable *THistory::build() +{ + return new THistory( streamableInit ); +} + +THistory::THistory( StreamableInit ) : TView( streamableInit ) +{ +} +#endif // NO_STREAM + + diff --git a/tvision/classes/thistvie.cc b/tvision/classes/thistvie.cc new file mode 100644 index 0000000..8504892 --- /dev/null +++ b/tvision/classes/thistvie.cc @@ -0,0 +1,89 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#include +#define Uses_string + +#define Uses_TKeys +#define Uses_THistoryViewer +#define Uses_TScrollBar +#define Uses_TEvent +#define Uses_TPalette +#include + +#define cpHistoryViewer "\x06\x06\x07\x06\x06" + +THistoryViewer::THistoryViewer( const TRect& bounds, + TScrollBar *aHScrollBar, + TScrollBar *aVScrollBar, + ushort aHistoryId) : + TListViewer(bounds, 1, aHScrollBar, aVScrollBar), + historyId( aHistoryId ) +{ + setRange( historyCount( aHistoryId ) ); + if( range > 1 ) + focusItem( 1 ); + hScrollBar->setRange( 0, historyWidth() - size.x + 3 ); +} + +TPalette& THistoryViewer::getPalette() const +{ + static TPalette palette( cpHistoryViewer, sizeof( cpHistoryViewer )-1 ); + return palette; +} + +void THistoryViewer::getText( char *dest, ccIndex item, short maxChars ) +{ + const char *str = historyStr( historyId, item ); + if( str != 0 ) + { + strncpy( dest, str, maxChars ); + dest[maxChars] = '\0'; + } + else + *dest = EOS; +} + +void THistoryViewer::handleEvent( TEvent& event ) +{ + if( (event.what == evMouseDown && event.mouse.doubleClick) || + (event.what == evKeyDown && event.keyDown.keyCode == kbEnter) + ) + { + endModal( cmOK ); + clearEvent( event ); + } + else + if( (event.what == evKeyDown && event.keyDown.keyCode == kbEsc) || + (event.what == evCommand && event.message.command == cmCancel) + ) + { + endModal( cmCancel ); + clearEvent( event ); + } + else + TListViewer::handleEvent( event ); +} + +int THistoryViewer::historyWidth() +{ + int width = 0; + int count = historyCount( historyId ); + for( int i = 0; i < count; i++ ) + { + int T = strlen( historyStr( historyId, i ) ); + width = max( width, T ); + } + return width; +} diff --git a/tvision/classes/thistwin.cc b/tvision/classes/thistwin.cc new file mode 100644 index 0000000..7329726 --- /dev/null +++ b/tvision/classes/thistwin.cc @@ -0,0 +1,56 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#define Uses_THistoryWindow +#define Uses_THistoryViewer +#define Uses_TPalette +#include + +THistInit::THistInit( TListViewer *(*cListViewer)( TRect, TWindow *, ushort ) ) : + createListViewer( cListViewer ) +{ +} + +#define cpHistoryWindow "\x13\x13\x15\x18\x17\x13\x14" + +THistoryWindow::THistoryWindow( const TRect& bounds, + ushort historyId ) : + TWindowInit( &THistoryWindow::initFrame ) + , THistInit( &THistoryWindow::initViewer ) + , TWindow( bounds, 0, wnNoNumber) +{ + flags = wfClose; + if( createListViewer != 0 && + (viewer = createListViewer( getExtent(), this, historyId )) != 0 ) + insert( viewer ); +} + +TPalette& THistoryWindow::getPalette() const +{ + static TPalette palette( cpHistoryWindow, sizeof( cpHistoryWindow )-1 ); + return palette; +} + +void THistoryWindow::getSelection( char *dest ) +{ + viewer->getText( dest, viewer->focused, 255 ); +} + +TListViewer *THistoryWindow::initViewer( TRect r, TWindow * win, ushort historyId ) +{ + r.grow( -1, -1 ); + return new THistoryViewer( r, + win->standardScrollBar( sbHorizontal | sbHandleKeyboard ), + win->standardScrollBar( sbVertical | sbHandleKeyboard ), + historyId); +} diff --git a/tvision/classes/thwmouse.cc b/tvision/classes/thwmouse.cc new file mode 100644 index 0000000..54bcd70 --- /dev/null +++ b/tvision/classes/thwmouse.cc @@ -0,0 +1,162 @@ +/**[txh]******************************************************************** + + Mouse module, Copyright 2001-2003 by Salvador E. Tropea + Description: + This is the base class for low level mouse input. + Most members are pointers to functions defined by each platform dependent +driver. Default members are provided. + This is a complete new file created from concepts that José Angel Sanchez +Caso provide me and coded from scratch. The names of some members are the +same used in original Turbo Vision for compatibility purposes. + +***************************************************************************/ +// Definitions are located at the event.h header + +#define Uses_TEvent +#define Uses_TEventQueue +#include + +/***************************************************************************** + Data members initialization +*****************************************************************************/ + +Boolean THWMouse::handlerInstalled=False; +Boolean THWMouse::noMouse =False; +uchar THWMouse::buttonCount =0; +uchar THWMouse::oldButtonCount =0; +uchar THWMouse::btBeforeForce =0; +char THWMouse::visible =0; +char THWMouse::forced =0; +volatile +unsigned THWMouse::drawCounter =0; +MouseEventType THWMouse::forcedME; + +/***************************************************************************** + Function pointer members initialization +*****************************************************************************/ + +void (*THWMouse::Show)() =defaultShow; +void (*THWMouse::Hide)() =defaultHide; +void (*THWMouse::setRange)(ushort, ushort) =defaultSetRange; +void (*THWMouse::GetEvent)(MouseEventType&) =defaultGetEvent; +void (*THWMouse::registerHandler)(unsigned, void (*)())=defaultRegisterHandler; +void (*THWMouse::Suspend)() =defaultSuspend; +void (*THWMouse::Resume)() =defaultResume; +int (*THWMouse::drawMouse)(int x, int y) =defaultDrawMouse; + +/***************************************************************************** + Default behaviors for the members +*****************************************************************************/ + +void THWMouse::defaultShow() +{ + visible=1; +} + +void THWMouse::defaultHide() +{ + visible=0; +} + +void THWMouse::defaultSuspend() {} +void THWMouse::defaultResume() { buttonCount=oldButtonCount; } +void THWMouse::defaultSetRange(ushort /*rx*/, ushort /*ry*/) {} +int THWMouse::defaultDrawMouse(int /*x*/, int /*y*/) { return 0; } + +void THWMouse::defaultRegisterHandler(unsigned, void (*)()) {} + +void THWMouse::defaultGetEvent(MouseEventType &me) +{ + me.where.x=TEventQueue::curMouse.where.x; + me.where.y=TEventQueue::curMouse.where.y; + me.buttons=TEventQueue::curMouse.buttons; + me.doubleClick=False; +} + +/***************************************************************************** + Real members +*****************************************************************************/ + +THWMouse::THWMouse() +{ + resume(); +} + +THWMouse::~THWMouse() +{ + suspend(); +} + +void THWMouse::show() +{ + if (!present() || visible) return; + Show(); +} + +void THWMouse::hide() +{ + if (!present() || !visible) return; + Hide(); +} + +void THWMouse::suspend() +{ + if (!present()) + return; + if (visible) + Hide(); + oldButtonCount=buttonCount; + buttonCount=0; + Suspend(); +} + +void THWMouse::resume() +{ + if (present()) + return; + Resume(); + if (!visible) + Show(); +} + +void THWMouse::forceEvent(int x, int y, int buttons) +{ + forced=0; + if (TEventQueue::curMouse.where.x!=x || TEventQueue::curMouse.where.y!=y) + forced++; + if (TEventQueue::curMouse.buttons!=buttons) + forced++; + forcedME.where.x=x; + forcedME.where.y=y; + forcedME.doubleClick=False; + btBeforeForce=forcedME.buttons; + forcedME.buttons=buttons; +} + +void THWMouse::getEvent(MouseEventType& me) +{ + if (!present()) + { + me=TEventQueue::curMouse; + return; + } + if (forced) + { + me=forcedME; + if (forced==2) + me.buttons=btBeforeForce; + TEventQueue::curMouse=me; + drawMouse(forcedME.where.x,forcedME.where.y); + forced--; + } + else if (handlerInstalled) + { + me=TEventQueue::curMouse; + } + else + { + GetEvent(me); + TEventQueue::curMouse=me; + } +} + diff --git a/tvision/classes/tindicat.cc b/tvision/classes/tindicat.cc new file mode 100644 index 0000000..ce23a29 --- /dev/null +++ b/tvision/classes/tindicat.cc @@ -0,0 +1,107 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#if 0 + #define Uses_strstream +#else + #define Uses_stdio +#endif +#define Uses_string + +#define Uses_TIndicator +#define Uses_TDrawBuffer +#define Uses_TEvent +#define Uses_TView +#define Uses_opstream +#define Uses_ipstream +#define Uses_TIndicator +#define Uses_TStreamableClass +#define Uses_TPalette +#include + +#define cpIndicator "\x02\x03" + +TIndicator::TIndicator( const TRect& bounds ) : + TView( bounds ) +{ + growMode = gfGrowLoY | gfGrowHiY; + location.x = location.y = 1; +} + +void TIndicator::draw() +{ + uchar color, frame; + TDrawBuffer b; + char s[15]; + + if( (state & sfDragging) == 0 ) + { + color = getColor(1); + frame = dragFrame; + } + else + { + color = getColor(2); + frame = normalFrame; + } + + b.moveChar( 0, frame, color, size.x ); + if( modified ) + b.putChar( 0, modifiedStar ); +#if 1 + sprintf(s," %d:%d ",location.y+1,location.x+1); +#else + ostrstream os( s, 15 ); + + os << ' ' << (location.y+1) + << ':' << (location.x+1) << ' ' << ends; +#endif + b.moveCStr( 8-int(strchr(s, ':')-s), s, color); + writeBuf(0, 0, size.x, 1, b); +} + +TPalette& TIndicator::getPalette() const +{ + static TPalette palette( cpIndicator, sizeof( cpIndicator )-1 ); + return palette; +} + +void TIndicator::setState( ushort aState, Boolean enable ) +{ + TView::setState(aState, enable); + if( aState == sfDragging ) + drawView(); +} + +void TIndicator::setValue( const TPoint& aLocation, Boolean aModified ) +{ + if( (location != aLocation) || (modified != aModified) ) + { + location = aLocation; + modified = aModified; + drawView(); + } +} + +#if !defined( NO_STREAM ) +TStreamable *TIndicator::build() +{ + return new TIndicator( streamableInit ); +} + +TIndicator::TIndicator( StreamableInit ) : TView( streamableInit ) +{ +} +#endif // NO_STREAM + diff --git a/tvision/classes/tinputli.cc b/tvision/classes/tinputli.cc new file mode 100644 index 0000000..cae0a08 --- /dev/null +++ b/tvision/classes/tinputli.cc @@ -0,0 +1,563 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Salvador E. Tropea (added insertChar, middle button paste and +other stuff). + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +// Added insertChar member. +#define Uses_ctype +#define Uses_string +#define Uses_stdlib +#define Uses_AllocLocal +#define Uses_TKeys +#define Uses_TKeys_Extended +#define Uses_TGKey +#define Uses_TInputLine +#define Uses_TDrawBuffer +#define Uses_TEvent +#define Uses_opstream +#define Uses_ipstream +#define Uses_TStreamableClass +#define Uses_TValidator +#define Uses_TPalette +#define Uses_TVOSClipboard +#define Uses_TGroup +#include + +unsigned TInputLine::defaultModeOptions=0; + +#define cpInputLine "\x13\x13\x14\x15" + +TInputLine::TInputLine( const TRect& bounds, int aMaxLen, TValidator *aValid ) : + TView(bounds), + data( new char[aMaxLen] ), + maxLen( aMaxLen-1 ), + curPos( 0 ), + firstPos( 0 ), + selStart( 0 ), + selEnd( 0 ), + validator( aValid ), + oldData( new char[aMaxLen] ) +{ + state |= sfCursorVis; + options |= ofSelectable | ofFirstClick; + *data = EOS; + modeOptions = defaultModeOptions; + hideContent = False; +} + +void TInputLine::setValidator(TValidator * aValidator) +{ + CLY_destroy(validator); + validator = aValidator; +} + +TInputLine::~TInputLine() +{ + delete[] data; + delete[] oldData; + CLY_destroy(validator); +} + +Boolean TInputLine::canScroll( int delta ) +{ + if( delta < 0 ) + return Boolean( firstPos > 0 ); + else + if( delta > 0 ) + return Boolean( (int)strlen(data) - firstPos + 2 > size.x ); + else + return False; +} + +unsigned TInputLine::dataSize() +{ + unsigned dSize = 0; + + if (validator) + dSize = validator->transfer(data, NULL, vtDataSize); + if (dSize == 0) + dSize = maxLen + 1; + return dSize; +} + +void TInputLine::draw() +{ + int l, r; + TDrawBuffer b; + + uchar color = (state & sfFocused) ? getColor( 2 ) : getColor( 1 ); + + b.moveChar( 0, ' ', color, size.x ); + AllocLocalStr( buf, size.x ); + if( hideContent ) + { + int rest = strlen( data ) - firstPos; + if( rest > 0 ) + b.moveChar( 1, '*', color, min( size.x - 2, rest) ); + } + else + { + strncpy( buf, data+firstPos, size.x - 2 ); + buf[size.x - 2 ] = EOS; + b.moveStr( 1, buf, color ); + } + + if( canScroll(1) ) + b.moveChar( size.x-1, rightArrow, getColor(4), 1 ); + if( canScroll(-1) ) + b.moveChar( 0, leftArrow, getColor(4), 1 ); + if( state & sfSelected ) + { + l = selStart - firstPos; + r = selEnd - firstPos; + l = max( 0, l ); + r = min( size.x - 2, r ); + if (l < r) + b.moveChar( l+1, 0, getColor(3), r - l ); + } + writeLine( 0, 0, size.x, size.y, b ); + setCursor( curPos-firstPos+1, 0); +} + +void TInputLine::getData( void *rec ) +{ + if (!validator || !validator->transfer(data, rec, vtGetData)) + memcpy( rec, data, dataSize() ); +} + +TPalette& TInputLine::getPalette() const +{ + static TPalette palette( cpInputLine, sizeof( cpInputLine )-1 ); + return palette; +} + +int TInputLine::mouseDelta( TEvent& event ) +{ + TPoint mouse = makeLocal( event.mouse.where ); + + if( mouse.x <= 0 ) + return -1; + else + if( mouse.x >= size.x - 1 ) + return 1; + else + return 0; +} + +int TInputLine::mousePos( TEvent& event ) +{ + TPoint mouse = makeLocal( event.mouse.where ); + mouse.x = max( mouse.x, 1 ); + int pos = mouse.x + firstPos - 1; + pos = max( pos, 0 ); + pos = min( (size_t)pos, strlen(data) ); + return pos; +} + +void TInputLine::deleteSelect() +{ + if( selStart < selEnd ) + { + strcpy( data+selStart, data+selEnd ); + curPos = selStart; + } +} + +/**[txh]******************************************************************** + + Description: + Inserts a character at the cursor position. If the text is currently +selected it's removed. If a validator is defined it's called. This basic +input line have a fixed size and will refuse to insert the character if +there is not enough space, but the virtual resizeData() is called giving +a chance to create variable size input lines.@* + I (SET) moved it to allow insertions from sources other than the keyboard +emulating it's behavior. + + Return: False if the validator canceled the character, otherwise True. + +***************************************************************************/ + +Boolean TInputLine::insertChar(char value) +{ + saveState(); + if( (state & sfCursorIns) == 0 ) + { + deleteSelect(); + } + int l = strlen(data); + if (((l == maxLen) && ((state & sfCursorIns) == 0)) || + ((state & sfCursorIns) && curPos == maxLen)) + resizeData(); + { + if( (state & sfCursorIns) == 0 ) + { + if (l < maxLen) + memmove( data + curPos + 1, data + curPos, + strlen(data+curPos)+1 ); + } + else if (l == curPos) + { + data[curPos+1] = 0; + } + if ((((state & sfCursorIns) == 0) && (l < maxLen)) || + ((state & sfCursorIns) && (curPos < maxLen))) + { + if( firstPos > curPos ) + firstPos = curPos; + data[curPos++] = value; + } + } + + return checkValid(False); +} + +/**[txh]******************************************************************** + + Description: + Used internally to ensure the cursor is at a visible position, unselect +the text and force a draw. + +***************************************************************************/ + +void TInputLine::makeVisible() +{ + if( firstPos > curPos ) + firstPos = curPos; + int i = curPos - size.x + 2; + if( firstPos < i ) + firstPos = i; + drawView(); +} + +void TInputLine::saveState() +{ + if (validator) + { + strcpy(oldData,data); + oldCurPos = curPos; + oldFirstPos = firstPos; + oldSelStart = selStart; + oldSelEnd = selEnd; + } +} + +void TInputLine::restoreState() +{ + if (validator) + { + strcpy(data, oldData); + curPos = oldCurPos; + firstPos = oldFirstPos; + selStart = oldSelStart; + selEnd = oldSelEnd; + } +} + +Boolean TInputLine::checkValid(Boolean noAutoFill) +{ + int oldLen; + char *newData; + + if (validator) + { + oldLen = (int)strlen(data); + // SET: I think TValidator should avoid to exceed maxLen. + newData = new char[maxLen+2]; + strcpy(newData, data); + if (!validator->isValidInput(newData, noAutoFill)) + { + restoreState(); + delete[] newData; + return False; + } + else + { + if ((int)strlen(newData) > maxLen) + // We don't support validators that write more data than the allowed. + abort(); + //newData[maxLen] = 0; + strcpy(data,newData); + // Handle the autofill feature + if ((curPos >= oldLen) && ((int)strlen(data) > oldLen)) + curPos = (int)strlen(data); + delete[] newData; + return True; + } + } + return True; +} + + + +#define adjustSelectBlock() \ + if( curPos < anchor ) \ + { \ + selStart = curPos; \ + selEnd = anchor; \ + } \ + else \ + { \ + selStart = anchor; \ + selEnd = curPos; \ + } + +void TInputLine::handleEvent( TEvent& event ) +{ + ushort key; + Boolean extendBlock; + TView::handleEvent(event); + + int delta, anchor=0; + if( (state & sfSelected) != 0 ) + switch( event.what ) + { + case evMouseDown: + if( event.mouse.buttons == mbMiddleButton && + TVOSClipboard::isAvailable() > 1 ) + { + unsigned size,i; + char *p=TVOSClipboard::paste(1,size); + if( p ) + { + for (i=0; i 1 ) + TVOSClipboard::copy(1,data+selStart,selEnd-selStart); + } + clearEvent(event); + break; + case evKeyDown: + key = ctrlToArrow(event.keyDown.keyCode); + extendBlock = False; + if( key & kbShiftCode ) + { + ushort keyS = key & (~kbShiftCode); + if( keyS == kbHome || keyS == kbLeft || keyS == kbRight || keyS == kbEnd ) + { + if (curPos == selEnd) + anchor = selStart; + else + anchor = selEnd; + key = keyS; + extendBlock = True; + } + } + + switch( key ) + { + case kbLeft: + if( curPos > 0 ) + curPos--; + break; + case kbRight: + if( curPos < (int)strlen(data) ) + curPos++; + break; + case kbHome: + curPos = 0; + break; + case kbEnd: + curPos = strlen(data); + break; + case kbBackSpace: + if( curPos > 0 ) + { + saveState(); + strcpy( data+curPos-1, data+curPos ); + curPos--; + if( firstPos > 0 ) + firstPos--; + checkValid(True); + } + break; + case kbDelete: + saveState(); + if( selStart == selEnd ) + if( curPos < (int)strlen(data) ) + { + selStart = curPos; + selEnd = curPos + 1; + } + deleteSelect(); + checkValid(True); + break; + case kbInsert: + setState(sfCursorIns, Boolean(!(state & sfCursorIns))); + break; + case kbCtY: + *data = EOS; + curPos = 0; + break; + // Let them pass even if these contains a strange ASCII (SET) + case kbEnter: + case kbTab: + return; + default: + if( event.keyDown.charScan.charCode >= ' ' ) + { + if( !insertChar( event.keyDown.charScan.charCode ) ) + { + clearEvent(event); + break; + } + } + else + { + return; + } + } + if (extendBlock) + { + adjustSelectBlock() + } + else + { + selStart = 0; + selEnd = 0; + } + makeVisible(); + clearEvent( event ); + break; + } +} + +void TInputLine::selectAll( Boolean enable ) +{ + selStart = 0; + if( enable ) + curPos = selEnd = strlen(data); + else + curPos = selEnd = 0; + firstPos = max( 0, curPos-size.x+2 ); + if( TVOSClipboard::isAvailable() > 1 ) + TVOSClipboard::copy(1,data+selStart,selEnd-selStart); + drawView(); +} + +void TInputLine::setData( void *rec ) +{ + if (!validator || !validator->transfer(data,rec,vtSetData)) + { + // The following is invalid is someboy calls setData("string") + // memcpy( data, rec, dataSize()-1 ); + strncpy( data, (const char*)rec, dataSize()-1 ); + data[dataSize()-1] = EOS; // strncpy doesn't make it if strlen(rec)>dataSize()-1 + } + selectAll( True ); +} + +void TInputLine::setState( ushort aState, Boolean enable ) +{ + if (validator && // We have a validator + (modeOptions & ilValidatorBlocks) && // We want to block if invalid + owner && (owner->state & sfActive) && // The owner is visible + aState==sfFocused && enable==False) // We are losing the focus + { + TValidator *v=validator; + validator=NULL; // Avoid nested tests + Boolean ret=v->validate(data); // Check if we have valid data + validator=v; + if (!ret) // If not refuse the focus change + return; + } + TView::setState( aState, enable ); + if( aState == sfSelected || + ( aState == sfActive && (state & sfSelected) != 0 ) + ) + selectAll( enable ); +} + +#if !defined( NO_STREAM ) +void TInputLine::write( opstream& os ) +{ + TView::write( os ); + os << maxLen << curPos << firstPos + << selStart << selEnd; + os.writeString( data); + os << validator; +} + +void *TInputLine::read( ipstream& is ) +{ + TView::read( is ); + is >> maxLen >> curPos >> firstPos + >> selStart >> selEnd; + data = new char[maxLen + 1]; + oldData = new char[maxLen + 1]; + is.readString(data, maxLen+1); + state |= sfCursorVis; + is >> validator; + // BC++ TV 2.0 options |= ofSelectable | ofFirstClick; + return this; +} + +TStreamable *TInputLine::build() +{ + return new TInputLine( streamableInit ); +} + +TInputLine::TInputLine( StreamableInit ) : TView( streamableInit ), + validator(NULL) +{ +} +#endif // NO_STREAM + +Boolean TInputLine::valid(ushort cmd) +{ + if (validator) + { + if (cmd == cmValid) + return Boolean(validator->status == vsOk); + else if (cmd != cmCancel) + if (!validator->validate(data)) + { + owner->current = 0; + select(); + return False; + } + } + return True; +} + + diff --git a/tvision/classes/tlabel.cc b/tvision/classes/tlabel.cc new file mode 100644 index 0000000..08350be --- /dev/null +++ b/tvision/classes/tlabel.cc @@ -0,0 +1,179 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Salvador E. Tropea: added i18n support. + + * + * + */ + +#define Uses_TLabel +#define Uses_TEvent +#define Uses_TDrawBuffer +#define Uses_TGroup +#define Uses_TView +#define Uses_opstream +#define Uses_ipstream +#define Uses_TStreamableClass +#define Uses_TPalette +#define Uses_TGKey +#define Uses_ctype +#define Uses_TScreen +#include + +#define cpLabel "\x07\x08\x09\x09\x0D\x0D" + +TLabel::TLabel( const TRect& bounds, const char *aText, TView* aLink) : + TStaticText( bounds, aText ) +{ + init( aLink ); +} + +TLabel::TLabel( const TRect& bounds, const char *aText, TView *aLink, + stTVIntl *aIntlText ) : + TStaticText( bounds, aText, aIntlText ) +{ + init( aLink ); +} + +void TLabel::init( TView *aLink ) +{ + link = aLink; + light = False; + options |= ofPreProcess | ofPostProcess; + eventMask |= evBroadcast; + // This class can be "Braille friendly" + if (TScreen::getShowCursorEver()) + state |= sfCursorVis; +} + +void TLabel::shutDown() +{ + link = 0; + TStaticText::shutDown(); +} + +// SET: Now labels propagate the disabled state. +void TLabel::setState( ushort aState, Boolean enable ) +{ + TView::setState( aState, enable ); + if( aState == sfDisabled ) + { + link->setState( aState, enable ); + drawView(); + } +} + +void TLabel::draw() +{ + ushort color; + TDrawBuffer b; + uchar scOff; + + if( state & sfDisabled ) + {// SET: Now disabled labels shows it + color = getColor(0x0605); + scOff = 4; + } + else + { + if( light ) + { + color = getColor(0x0402); + scOff = 0; + } + else + { + color = getColor(0x0301); + scOff = 4; + } + } + + b.moveChar( 0, ' ', color, size.x ); + if( text != 0 ) + { + b.moveCStr( 1, getText(), color ); + if( light ) + {// Usually this will do nothing because the focus is in the linked + // object + setCursor( 1 , 0 ); + resetCursor(); + } + } + if( showMarkers ) + b.putChar( 0, specialChars[scOff] ); + writeLine( 0, 0, size.x, 1, b ); +} + +TPalette& TLabel::getPalette() const +{ + static TPalette palette( cpLabel, sizeof( cpLabel )-1 ); + return palette; +} + +#define validLink() (link && (link->options & ofSelectable) && \ + !(link->state & sfDisabled)) + +void TLabel::handleEvent( TEvent& event ) +{ + TStaticText::handleEvent(event); + if( event.what == evMouseDown ) + { + if( validLink() ) + link->select(); + clearEvent( event ); + } + else if( event.what == evKeyDown ) + { + char c = hotKey( getText() ); + if( TGKey::GetAltCode(c) == event.keyDown.keyCode || + ( c != 0 && owner->phase == TGroup::phPostProcess && + TGKey::CompareASCII(uctoupper(event.keyDown.charScan.charCode),c) ) + ) + { + if( validLink() ) + link->select(); + clearEvent( event ); + } + } + else if( event.what == evBroadcast && + ( event.message.command == cmReceivedFocus || + event.message.command == cmReleasedFocus ) + ) + { + light = Boolean( (link->state & sfFocused) != 0 ); + drawView(); + } +} + +#if !defined( NO_STREAM ) +void TLabel::write( opstream& os ) +{ + TStaticText::write( os ); + os << link; +} + +void *TLabel::read( ipstream& is ) +{ + TStaticText::read( is ); + is >> link; + light = False; + return this; +} + +TStreamable *TLabel::build() +{ + return new TLabel( streamableInit ); +} + +TLabel::TLabel( StreamableInit ) : TStaticText( streamableInit ) +{ +} +#endif // NO_STREAM + + diff --git a/tvision/classes/tlistbox.cc b/tvision/classes/tlistbox.cc new file mode 100644 index 0000000..73c4770 --- /dev/null +++ b/tvision/classes/tlistbox.cc @@ -0,0 +1,139 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Salvador E. Tropea to add functionality. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_string + +#define Uses_TListBox +#define Uses_TEvent +#define Uses_TCollection +#define Uses_opstream +#define Uses_ipstream +#define Uses_TStreamableClass +#include + +TListBox::TListBox( const TRect& bounds, + ushort aNumCols, + TScrollBar *aScrollBar ) : + TListViewer(bounds, aNumCols, 0, aScrollBar), + items( 0 ) +{ + setRange(0); + center = False; +} + +// SET: +TListBox::TListBox( const TRect& bounds, + ushort aNumCols, + TScrollBar *aHScrollBar, + TScrollBar *aVScrollBar, + Boolean aCenterOps) : + TListViewer(bounds, aNumCols, aHScrollBar, aVScrollBar), + items( 0 ) +{ + setRange(0); + center = aCenterOps; +} + +TListBox::~TListBox() +{ +} + +uint32 TListBox::dataSize() +{ + return sizeof(TListBoxRec); +} + +void TListBox::getData( void * rec ) +{ + TListBoxRec *p = (TListBoxRec *)rec; + p->items = items; + p->selection = focused; +} + +void TListBox::getText( char *dest, ccIndex item, short maxChars ) +{ + if( items != 0 ) + { + strncpy( dest, (const char *)(items->at(item)), maxChars ); + dest[maxChars] = '\0'; + } + else + *dest = EOS; +} + +// SET: You not always want to destroy the items +void TListBox::newList( TCollection *aList, Boolean destroyItems ) +{ + if( destroyItems ) + CLY_destroy( items ); + items = aList; + if( aList != 0 ) + setRange( aList->getCount() ); + else + setRange(0); + if( range > 0 ) + focusItem(0); + drawView(); +} + +// SET: This is for compatibility +void TListBox::newList( TCollection *aList ) +{ + newList( aList, True ); +} + +// SET: You not always want to destroy the items +void TListBox::setData( void *rec, Boolean destroyItems ) +{ + TListBoxRec *p = (TListBoxRec *)rec; + newList( p->items, destroyItems ); + if( center ) + focusItemCentered( p->selection ); + else + focusItem( p->selection ); + drawView(); +} + +// SET: This is for compatibility +void TListBox::setData( void *rec ) +{ + setData( rec, True ); +} + +#if !defined( NO_STREAM ) +void TListBox::write( opstream& os ) +{ + TListViewer::write( os ); + os << items; +} + +void *TListBox::read( ipstream& is ) +{ + TListViewer::read( is ); + is >> items; + return this; +} + +TStreamable *TListBox::build() +{ + return new TListBox( streamableInit ); +} + +TListBox::TListBox( StreamableInit ) : TListViewer( streamableInit ) +{ +} +#endif // NO_STREAM + + diff --git a/tvision/classes/tlistvie.cc b/tvision/classes/tlistvie.cc new file mode 100644 index 0000000..172bf74 --- /dev/null +++ b/tvision/classes/tlistvie.cc @@ -0,0 +1,530 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Vadim Beloborodov to be used on WIN32 console +Modified by Salvador E. Tropea to add functionality. + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_string +#define Uses_AllocLocal +#define Uses_TKeys +#define Uses_TListViewer +#define Uses_TScrollBar +#define Uses_TDrawBuffer +#define Uses_TPoint +#define Uses_TEvent +#define Uses_TGroup +#define Uses_opstream +#define Uses_ipstream +#define Uses_TStreamableClass +#define Uses_TPalette +#include + +#define cpListViewer "\x1A\x1A\x1B\x1C\x1D" + +// SET: By default I make it report more messages than original TV. In this +// case the focusItem(ccIndex item) member generates a broadcast. +unsigned TListViewer::extraOptions=ofBeVerbose; + +TListViewer::TListViewer( const TRect& bounds, + ushort aNumCols, + TScrollBar *aHScrollBar, + TScrollBar *aVScrollBar) : + TView( bounds ), + topItem( 0 ), + focused( 0 ), + range( 0 ), + handleSpace(True) +{ + options |= ofFirstClick | ofSelectable | extraOptions; + eventMask |= evBroadcast; + + hScrollBar = aHScrollBar; + vScrollBar = aVScrollBar; + center = False; + setNumCols(aNumCols); +} + +// SET: Moved here to allow changes from sub-classes +void TListViewer::setNumCols(int aNumCols) +{ + int arStep,pgStep; + + numCols=aNumCols; + // Compute the scroll bar changes. + if (vScrollBar!=0) + { + if (numCols==1) + { + pgStep=size.y-1; + arStep=1; + } + else + { + pgStep=size.y*numCols; + arStep=size.y; + } + vScrollBar->setStep(pgStep,arStep); + } + if (hScrollBar) + hScrollBar->setStep(size.x/numCols,1); +} + +void TListViewer::changeBounds( const TRect& bounds ) +{ + TView::changeBounds( bounds ); + if( hScrollBar != 0 ) + hScrollBar->setStep( size.x / numCols, 1 ); +} + +void TListViewer::draw() +{ + short i, j; + ccIndex item; + ushort normalColor, selectedColor, focusedColor=0, color; + short colWidth, curCol, indent; + TDrawBuffer b; + uchar scOff; + + if( (state&(sfSelected | sfActive)) == (sfSelected | sfActive)) + { + normalColor = getColor(1); + focusedColor = getColor(3); + selectedColor = getColor(4); + } + else + { + normalColor = getColor(2); + selectedColor = getColor(4); + } + + if( hScrollBar != 0 ) + indent = hScrollBar->value; + else + indent = 0; + + colWidth = size.x / numCols + 1; + for( i = 0; i < size.y; i++ ) + { + for( j = 0; j < numCols; j++ ) + { + int width;; + item = j * size.y + i + topItem; + curCol = j * colWidth; + if (j == numCols-1) width = size.x - curCol + 1; + else width = colWidth; + if( (state & (sfSelected | sfActive)) == (sfSelected | sfActive) && + focused == item && + range > 0) + { + color = focusedColor; + setCursor( curCol + 1, i ); + scOff = 0; + } + else if( item < range && isSelected(item) ) + { + color = selectedColor; + scOff = 2; + } + else + { + color = normalColor; + scOff = 4; + } + + b.moveChar( curCol, ' ', color, width ); + if( item < range ) + { + // This was probably the + // reason for a bug, because + // getText assumes a buffer + // with a length of maxLen + 1 + AllocLocalStr(text,width+indent+1); + AllocLocalStr(buf,width+1); + getText( text, item, width + indent ); + int tl = strlen(text); + if (tl <= indent) + buf[0] = 0; + else + { + memcpy( buf, text+indent, width ); + buf[tl-indent] = EOS; + } + b.moveStr( curCol+1, buf, color ); + if( showMarkers ) + { + b.putChar( curCol, specialChars[scOff] ); + b.putChar( curCol+width-2, specialChars[scOff+1] ); + } + } + else if( i == 0 && j == 0 ) + b.moveStr( curCol+1, _(""), getColor(1) ); + + // It was a really nasty thing, this call used 179 instead of + // a configurable value like now. + b.moveChar( curCol+width-1, columnSeparator, getColor(5), 1 ); + } + writeLine( 0, i, size.x, 1, b ); + } +} + +void TListViewer::focusItem( ccIndex item ) +{ + focused = item; + + if( item < topItem ) + { + if( numCols == 1 ) + topItem = item; + else + topItem = item - item % size.y; + } + else + { + if( item >= topItem + size.y*numCols ) + { + if( numCols == 1 ) + topItem = item - size.y + 1; + else + topItem = item - item % size.y - (size.y * (numCols-1)); + } + } + if( vScrollBar != 0 ) + vScrollBar->setValue( item ); + else + drawView(); + if (owner && (options & ofBeVerbose)) + message(owner,evBroadcast,cmListItemFocused,this); +} + + +/**[txh]******************************************************************** + + Description: + That's a variant of focusItem that tries to center the focused item when +the list have only one column. + +***************************************************************************/ + +void TListViewer::focusItemCentered( ccIndex item ) +{ + if( numCols != 1 ) + { + focusItem( item ); + return; + } + center = True; + focused = item; + + if( item < topItem ) + { + topItem = item - size.y/2; + if( topItem < 0) + topItem = 0; + } + else + { + if( item >= topItem + size.y*numCols ) + { + topItem = item - size.y/2; + if( topItem + size.y >= range && range > size.y) + topItem = range - size.y; + } + } + if( vScrollBar != 0 ) + vScrollBar->setValue( item ); + else + drawView(); + if (owner && (options & ofBeVerbose)) + message(owner,evBroadcast,cmListItemFocused,this); + center = False; +} + +void TListViewer::focusItemNum( ccIndex item ) +{ + if( item < 0 ) + item = 0; + else + if( item >= range && range > 0 ) + item = range - 1; + + if( range != 0 ) + { + if( center ) + focusItemCentered( item ); + else + focusItem( item ); + } +} + +TPalette& TListViewer::getPalette() const +{ + static TPalette palette( cpListViewer, sizeof( cpListViewer )-1 ); + return palette; +} + +void TListViewer::getText( char *dest, ccIndex, short ) +{ + *dest = EOS; +} + +Boolean TListViewer::isSelected( ccIndex item ) +{ + return Boolean( item == focused ); +} + +void TListViewer::handleEvent( TEvent& event ) +{ + TPoint mouse; + ushort colWidth; + ccIndex oldItem, newItem; + ushort count; + int mouseAutosToSkip = 4; + + TView::handleEvent(event); + + if( event.what == evMouseDown ) + { + // They must be before doubleClick to avoid "b4 double click" + if( event.mouse.buttons == mbButton4 ) + { + focusItemNum(focused - size.y * numCols); + clearEvent( event ); + return; + } + if( event.mouse.buttons == mbButton5 ) + { + focusItemNum(focused + size.y * numCols); + clearEvent( event ); + return; + } + if( event.mouse.doubleClick && range > focused ) + { + selectItem( focused ); + clearEvent( event ); + return; + } + colWidth = size.x / numCols + 1; + oldItem = focused; + mouse = makeLocal( event.mouse.where ); + newItem = mouse.y + (size.y * (mouse.x / colWidth)) + topItem; + count = 0; + do { + if( newItem != oldItem ) + focusItemNum( newItem ); + oldItem = newItem; + mouse = makeLocal( event.mouse.where ); + if( mouseInView( event.mouse.where ) ) + newItem = mouse.y + (size.y * (mouse.x / colWidth)) + topItem; + else + { + if( numCols == 1 ) + { + if( event.what == evMouseAuto ) + count++; + if( count == mouseAutosToSkip ) + { + count = 0; + if( mouse.y < 0 ) + newItem = focused - 1; + else + if( mouse.y >= size.y ) + newItem = focused + 1; + } + } + else + { + if( event.what == evMouseAuto ) + count++; + if( count == mouseAutosToSkip ) + { + count = 0; + if( mouse.x < 0 ) + newItem = focused - size.y; + else if( mouse.x >= size.x ) + newItem = focused + size.y; + else if( mouse.y < 0 ) + newItem = focused - focused % size.y; + else if( mouse.y > size.y ) + newItem = focused - focused % size.y + size.y - 1; + } + } + } + } while( mouseEvent( event, evMouseMove | evMouseAuto ) ); + focusItemNum( newItem ); + if( event.mouse.doubleClick && range > focused ) + selectItem( focused ); + clearEvent( event ); + } + else if( event.what == evKeyDown ) + { + if ((handleSpace == True) && + (event.keyDown.charScan.charCode == ' ') && focused < range ) + { + selectItem( focused ); + newItem = focused; + } + else + { + switch (ctrlToArrow(event.keyDown.keyCode)) + { + case kbUp: + newItem = focused - 1; + break; + case kbDown: + newItem = focused + 1; + break; + case kbRight: + if( numCols > 1 ) + newItem = focused + size.y; + else + { // SET: if the user put a scroll bar with one column + // that's what he wants + if (hScrollBar) hScrollBar->handleEvent(event); + return; + } + break; + case kbLeft: + if( numCols > 1 ) + newItem = focused - size.y; + else + { // SET: see kbRight + if (hScrollBar) hScrollBar->handleEvent(event); + return; + } + break; + case kbPgDn: + newItem = focused + size.y * numCols; + break; + case kbPgUp: + newItem = focused - size.y * numCols; + break; + case kbHome: + newItem = topItem; + break; + case kbEnd: + newItem = topItem + (size.y * numCols) - 1; + break; + case kbCtrlPgDn: + newItem = range - 1; + break; + case kbCtrlPgUp: + newItem = 0; + break; + default: + return; + } + focusItemNum(newItem); + } + clearEvent(event); + } + else if( event.what == evBroadcast ) + { + if( (options & ofSelectable) != 0 ) + { + if( event.message.command == cmScrollBarClicked && + ( event.message.infoPtr == hScrollBar || + event.message.infoPtr == vScrollBar ) ) + select(); + else if( event.message.command == cmScrollBarChanged ) + { + if( vScrollBar == event.message.infoPtr ) + { + focusItemNum( vScrollBar->value ); + drawView(); + } + else if( hScrollBar == event.message.infoPtr ) + drawView(); + } + } + } +} + +void TListViewer::selectItem( ccIndex ) +{ + message( owner, evBroadcast, cmListItemSelected, this ); +} + +void TListViewer::setRange( ccIndex aRange ) +{ + range = aRange; + if (focused >= aRange) + focused = (aRange - 1 >= 0) ? aRange - 1 : 0; + if( vScrollBar != 0 ) + { + vScrollBar->setParams( focused, + 0, + aRange - 1, + vScrollBar->pgStep, + vScrollBar->arStep + ); + } + else + drawView(); +} + +void TListViewer::setState( ushort aState, Boolean enable) +{ + TView::setState( aState, enable ); + if( (aState & (sfSelected | sfActive)) != 0 ) + { + if( hScrollBar != 0 ) + { + if( getState(sfActive) ) + hScrollBar->show(); + else + hScrollBar->hide(); + } + if( vScrollBar != 0 ) + { + if( getState(sfActive) ) + vScrollBar->show(); + else + vScrollBar->hide(); + } + drawView(); + } +} + +void TListViewer::shutDown() +{ + hScrollBar = 0; + vScrollBar = 0; + TView::shutDown(); +} + +#if !defined( NO_STREAM ) +void TListViewer::write( opstream& os ) +{ + TView::write( os ); + os << hScrollBar << vScrollBar << numCols + << topItem << focused << range; +} + +void *TListViewer::read( ipstream& is ) +{ + TView::read( is ); + is >> hScrollBar >> vScrollBar >> numCols + >> topItem >> focused >> range; + return this; +} + +TStreamable *TListViewer::build() +{ + return new TListViewer( streamableInit ); +} + +TListViewer::TListViewer( StreamableInit ) : TView( streamableInit ) +{ +} +#endif // NO_STREAM + + diff --git a/tvision/classes/tlookupv.cc b/tvision/classes/tlookupv.cc new file mode 100644 index 0000000..96dc3e8 --- /dev/null +++ b/tvision/classes/tlookupv.cc @@ -0,0 +1,110 @@ +/*------------------------------------------------------------*/ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + * Modified by Salvador E. Tropea. Covered by the GPL license. + * * Change NO_STREAM usage. + * * Fixed missing explicit base class initialization. + * * Changed 0 to NULL. + * * Added headers request. + */ + +#define Uses_string +#define Uses_TStringLookupValidator +#define Uses_MsgBox +#include + +// TLookupValidator + +Boolean TLookupValidator::isValid(const char* s) +{ + return lookup(s); +} + +Boolean TLookupValidator::lookup(const char* s) +{ + return True; +} + +#if !defined(NO_STREAM) +TStreamable * TLookupValidator::build() +{ + return (TStreamable *) new TLookupValidator(streamableInit); +} + +TLookupValidator::TLookupValidator( StreamableInit s ) : TValidator(s) +{ +} +#endif // NO_STREAM + +// TStringLookupValidator + +TStringLookupValidator::TStringLookupValidator(TStringCollection* aStrings) : + TLookupValidator() +{ + strings = aStrings; +} + +TStringLookupValidator::~TStringLookupValidator() +{ + newStringList(NULL); +} + +const char * TStringLookupValidator::errorMsg = __("Input is not in list of valid strings"); + +void TStringLookupValidator::error() +{ + messageBox(mfError | mfOKButton, errorMsg); +} + +static Boolean stringMatch(void* a1, void* a2) +{ + return Boolean(strcmp((const char*)a1, (const char*)a2) == 0); +} + + +Boolean TStringLookupValidator::lookup(const char* s) +{ + return Boolean(strings->firstThat(stringMatch,(void*)s) != 0); +} + +// Attention!!! the collection is deleted, NOT destroyed. +void TStringLookupValidator::newStringList(TStringCollection* aStrings) +{ + if (strings) + delete strings; + + strings = aStrings; +} + +#if !defined(NO_STREAM) +void TStringLookupValidator::write( opstream& os ) +{ + TLookupValidator::write( os ); + os << strings; +} + +void* TStringLookupValidator::read( ipstream& is ) +{ + TLookupValidator::read(is); + is >> strings; + + return this; +} + +TStreamable * TStringLookupValidator::build() +{ + return (TStreamable *) new TStringLookupValidator(streamableInit); +} + +TStringLookupValidator::TStringLookupValidator( StreamableInit s ) : + TLookupValidator(s) +{ +} +#endif // NO_STREAM + + + diff --git a/tvision/classes/tmemo.cc b/tvision/classes/tmemo.cc new file mode 100644 index 0000000..00ede46 --- /dev/null +++ b/tvision/classes/tmemo.cc @@ -0,0 +1,105 @@ +/* Modified by Robert Hoehne and Salvador Eduardo Tropea for the gcc port */ +/*----------------------------------------------------------*/ +/* */ +/* Turbo Vision 1.0 */ +/* Copyright (c) 1991 by Borland International */ +/* */ +/*----------------------------------------------------------*/ +/***************************************************************************** + + Be careful, I think we never really tested this class. In fact I modified +the size of the memo structure because the old code uses 4Gb ;-) + +*****************************************************************************/ + +#define Uses_string + +#define Uses_TKeys +#define Uses_TEditor +#define Uses_TMemo +#define Uses_TEvent +#define Uses_opstream +#define Uses_ipstream +#include + +#define cpMemo "\x1A\x1B" + +TMemo::TMemo( const TRect& bounds, + TScrollBar *aHScrollBar, + TScrollBar *aVScrollBar, + TIndicator *aIndicator, + uint32 aBufSize ) : + TEditor( bounds, aHScrollBar, aVScrollBar, aIndicator, aBufSize ) +{ +} + +uint32 TMemo::dataSize() +{ + return bufSize + sizeof( ushort ); +} + +void TMemo::getData( void *rec ) +{ + TMemoData *data = (TMemoData *)rec; + + data->length = bufLen; + memcpy(data->buffer, buffer, curPtr); + memcpy(&data->buffer[curPtr], buffer+(curPtr + gapLen), bufLen - curPtr); + memset(&data->buffer[bufLen], 0, bufSize - bufLen); +} + +void TMemo::setData( void *rec ) +{ + TMemoData *data = (TMemoData *)rec; + + memcpy(&buffer[bufSize - data->length], data->buffer, data->length); + setBufLen(data->length); +} + +TPalette& TMemo::getPalette() const +{ + static TPalette palette( cpMemo, sizeof( cpMemo )-1 ); + return palette; +} + +void TMemo::handleEvent( TEvent& event ) +{ + if( event.what != evKeyDown || event.keyDown.keyCode != kbTab ) + TEditor::handleEvent(event); +} + +#ifndef NO_STREAM + +void TMemo::write( opstream& os ) +{ + TEditor::write( os ); + os << bufLen; + os.writeBytes( buffer, curPtr ); + os.writeBytes( buffer + gapLen, bufLen - curPtr ); +} + +void *TMemo::read( ipstream& is ) +{ + TEditor::read( is ); + uint32 length; + is >> length; + if( isValid ) + { + is.readBytes( buffer + bufSize - length, length ); + setBufLen( length ); + } + else + is.seekg( is.tellg() + CLY_StreamPosT(length) ); + return this; +} + +TStreamable *TMemo::build() +{ + return new TMemo( streamableInit ); +} + +TMemo::TMemo( StreamableInit ) : TEditor( streamableInit ) +{ +} + +#endif // #ifndef NO_STREAM diff --git a/tvision/classes/tmenubar.cc b/tvision/classes/tmenubar.cc new file mode 100644 index 0000000..5709a1e --- /dev/null +++ b/tvision/classes/tmenubar.cc @@ -0,0 +1,190 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Salvador E. Tropea. [Also added i18n support]. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_string + +#define Uses_TMenuBar +#define Uses_TDrawBuffer +#define Uses_TMenu +#define Uses_TMenuItem +#define Uses_TRect +#define Uses_TSubMenu +#define Uses_TScreen +#include + +TMenuBar::TMenuBar( const TRect& bounds, TMenu *aMenu ) : + TMenuView( bounds ) +{ + menu = aMenu; + growMode = gfGrowHiX; + options |= ofPreProcess; + computeLength(); + // This class can be "Braille friendly" + if (TScreen::getShowCursorEver()) + state |= sfCursorVis; +} + +TMenuBar::TMenuBar( const TRect& bounds, TSubMenu& aMenu ) : + TMenuView( bounds ) +{ + menu = new TMenu( aMenu ); + growMode = gfGrowHiX; + options |= ofPreProcess; + computeLength(); + // This class can be "Braille friendly" + if (TScreen::getShowCursorEver()) + state |= sfCursorVis; +} + + +TMenuBar::~TMenuBar() +{ + delete(menu); +} + + +/**[txh]******************************************************************** + + Description: + This routine computes the length of the menu bar, if that's greater than +the size.x the menu becomes compacted to allow more options.@* + Added by SET. + +***************************************************************************/ + +void TMenuBar::computeLength() +{ + int l = 0; + TMenuItem *p; + + if( menu != 0 ) + { + p = menu->items; + while( p != 0 ) + { + if( p->name != 0 ) + l += cstrlen(TVIntl::getText(p->name,p->intlName)) + 2; + p = p->next; + } + } + compactMenu = l > size.x; +} + +/**[txh]******************************************************************** + + Description: + Calls TMenuView::changeBounds, additionally re-computes the length of the +bar to select the no/compact mode.@* + Added by SET. + +***************************************************************************/ + +void TMenuBar::changeBounds(const TRect& bounds) +{ + TMenuView::changeBounds(bounds); + int oldCompact=compactMenu; + computeLength(); + if (compactMenu!=oldCompact) + draw(); +} + +void TMenuBar::draw() +{ + ushort color; + int x, l, inc, xSel=-1; + TMenuItem *p; + TDrawBuffer b; + + ushort cNormal = getColor(0x0301); + ushort cSelect = getColor(0x0604); + ushort cNormDisabled = getColor(0x0202); + ushort cSelDisabled = getColor(0x0505); + b.moveChar( 0, ' ', cNormal, size.x ); + inc = (compactMenu ? 1 : 2); // SET + if( menu != 0 ) + { + x = 0; + p = menu->items; + while( p != 0 ) + { + if( p->name != 0 ) + { + l = cstrlen(TVIntl::getText(p->name,p->intlName)); + if( x + l < size.x ) + { + if( p->disabled ) + if( p == current ) + { + xSel = x; + color = cSelDisabled; + } + else + color = cNormDisabled; + else + if( p == current ) + { + xSel = x; + color = cSelect; + } + else + color = cNormal; + + b.moveChar( x, ' ', color, 1 ); + b.moveCStr( x+1, TVIntl::getText(p->name,p->intlName), color ); + b.moveChar( x+l+1, ' ', color, 1 ); + } + x += l + inc; + } + p = p->next; + } + } + writeBuf( 0, 0, size.x, 1, b ); + if( xSel != -1 ) + { + setCursor( xSel , 0 ); + resetCursor(); + } +} + +TRect TMenuBar::getItemRect( TMenuItem *item ) +{ + int y = compactMenu ? 1 : 0; // SET + TRect r( y, 0, y, 1 ); + y = compactMenu ? 1 : 2; // SET + TMenuItem *p = menu->items; + while( p ) + { + r.a.x = r.b.x; + if( p->name != 0 ) + r.b.x += cstrlen(TVIntl::getText(p->name,p->intlName)) + y; + if( p == item ) + return r; + p = p->next; + } + return TRect(0, 0, 0, 0); // SAA: should not ever happen +} + +#if !defined( NO_STREAM ) +TStreamable *TMenuBar::build() +{ + return new TMenuBar( streamableInit ); +} + +TMenuBar::TMenuBar( StreamableInit ) : TMenuView( streamableInit ) +{ +} +#endif // NO_STREAM + + diff --git a/tvision/classes/tmenubox.cc b/tvision/classes/tmenubox.cc new file mode 100644 index 0000000..a5cb511 --- /dev/null +++ b/tvision/classes/tmenubox.cc @@ -0,0 +1,164 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Salvador E. Tropea. [also added i18n support] + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_string + +#define Uses_TRect +#define Uses_TMenu +#define Uses_TMenuItem +#define Uses_TMenuBox +#define Uses_TScreen // getShowCursorEver() +#include + +static TRect getRect( const TRect& bounds, TMenu *aMenu ) +{ + short w = 10; + short h = 2; + if( aMenu != 0 ) + { + for( TMenuItem *p = aMenu->items; p != 0; p = p->next ) + { + if( p->name != 0 ) + { + short l = cstrlen(TVIntl::getText(p->name,p->intlName)) + 6; + if( p->command == 0 ) + l += 3; + else + if( p->param != 0 ) + l += cstrlen(p->param) + 2; + w = max( l, w ); + } + h++; + } + } + + TRect r( bounds ); + + if( r.a.x + w < r.b.x ) + r.b.x = r.a.x + w; + else + r.a.x = r.b.x - w; + + if (r.a.y + h < r.b.y) + r.b.y = r.a.y + h; + else + r.a.y = r.b.y - h; + return r; +} + +TMenuBox::TMenuBox( const TRect& bounds, + TMenu *aMenu, + TMenuView *aParentMenu) : + TMenuView( getRect( bounds, aMenu ), aMenu, aParentMenu ) +{ + state |= sfShadow; + // This class can be "Braille friendly" + if (TScreen::getShowCursorEver()) + state |= sfCursorVis; + options |= ofPreProcess; +} + +static ushort cNormal, color; + +void TMenuBox::frameLine( TDrawBuffer& b, short n ) +{ + b.moveBuf( 0, &frameChars[n], cNormal, 2 ); + b.moveChar( 2, frameChars[n+2], color, size.x - 4 ); + b.moveBuf( size.x-2, &frameChars[n+3], cNormal, 2 ); +} + +void TMenuBox::draw() +{ + TDrawBuffer b; + + cNormal = getColor(0x0301); + ushort cSelect = getColor(0x0604); + ushort cNormDisabled = getColor(0x0202); + ushort cSelDisabled = getColor(0x0505); + int y=0, yCur=-1; + color = cNormal; + frameLine( b, 0 ); + writeBuf( 0, y++, size.x, 1, b ); + if( menu != 0 ) + { + for( TMenuItem *p = menu->items; p != 0; p = p->next ) + { + color = cNormal; + if( p->name == 0 ) + frameLine( b, 15 ); + else + { + if( p->disabled ) + if( p == current ) + { + color = cSelDisabled; + yCur = y; + } + else + color = cNormDisabled; + else if( p == current ) + { + color = cSelect; + yCur = y; + } + frameLine( b, 10 ); + b.moveCStr( 3, TVIntl::getText(p->name,p->intlName), color ); + if( p->command == 0 ) + b.putChar( size.x-4, rightArrow ); + else if( p->param != 0 ) + b.moveStr( size.x-3-strlen(p->param), + p->param, + color); + } + writeBuf( 0, y++, size.x, 1, b ); + } + } + color = cNormal; + frameLine( b, 5 ); + writeBuf( 0, y++, size.x, 1, b ); + // SET: Force a cursor movement to indicate which one is selected. + // This helps Braille Terminals, but the cursor must be visible! + if( yCur != -1 ) + { + setCursor( 2 , yCur ); + resetCursor(); + } +} + +TRect TMenuBox::getItemRect( TMenuItem *item ) +{ + short y = 1; + TMenuItem *p = menu->items; + + while( p != item ) + { + y++; + p = p->next; + } + return TRect( 2, y, size.x-2, y+1 ); +} + +#if !defined( NO_STREAM ) +TStreamable *TMenuBox::build() +{ + return new TMenuBox( streamableInit ); +} + +TMenuBox::TMenuBox( StreamableInit ) : TMenuView( streamableInit ) +{ +} +#endif // NO_STREAM + + diff --git a/tvision/classes/tmenuvie.cc b/tvision/classes/tmenuvie.cc new file mode 100644 index 0000000..20af538 --- /dev/null +++ b/tvision/classes/tmenuvie.cc @@ -0,0 +1,650 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Salvador E. Tropea to support i18n. +Added TMenuItem::append by Salvador E. Tropea. +Modified the behavior of short-cuts when Alt is not/pressed by SET. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#include +#define Uses_string + +#define Uses_stdio // just for debug + +#define Uses_TMenuItem +#define Uses_TMenu +#define Uses_TMenuView +#define Uses_TKeys +#define Uses_TRect +#define Uses_TEvent +#define Uses_TGroup +#define Uses_TMenuBox +#define Uses_opstream +#define Uses_ipstream +#define Uses_TPalette +#define Uses_TGKey +#define Uses_TVCodePage +#include + +#define cpMenuView "\x02\x03\x04\x05\x06\x07" + +TMenuItem::TMenuItem( const char *aName, + ushort aCommand, + ushort aKeyCode, + ushort aHelpCtx, + const char *p, + TMenuItem *aNext + ) +{ + name = newStr( aName ); + intlName = NULL; + command = aCommand; + disabled = Boolean(!TView::commandEnabled(command)); + keyCode = aKeyCode; + helpCtx = aHelpCtx; + if( p == NULL ) + param = NULL; + else + param = newStr( p ); + next = aNext; +} + +TMenuItem::TMenuItem( const char *aName, + ushort aKeyCode, + TMenu *aSubMenu, + ushort aHelpCtx, + TMenuItem *aNext + ) +{ + name = newStr( aName ); + intlName = NULL; + command = 0; + disabled = Boolean(!TView::commandEnabled(command)); + keyCode = aKeyCode; + helpCtx = aHelpCtx; + subMenu = aSubMenu; + next = aNext; +} + +TMenuItem::~TMenuItem() +{ + DeleteArray((char *)name); + TVIntl::freeSt( intlName ); + if( command == 0 ) + delete(subMenu); + else + DeleteArray((char *)param); +} + +/**[txh]******************************************************************** + + Description: + Appends the provided TMenuItem at the end of the chain.@* + Coded by SET. That's a mix between Dean Wakerley and TVTools ideas. + +***************************************************************************/ + +void TMenuItem::append( TMenuItem *aNext ) +{ + TMenuItem *item = this; + for ( ; item->next; item = item->next ); + item->next = aNext; +} + +TMenu::~TMenu() +{ + while( items != 0 ) + { + TMenuItem *temp = items; + items = items->next; + delete(temp); + } +} + +void TMenuView::trackMouse( TEvent& e ) +{ + TPoint mouse = makeLocal( e.mouse.where ); + for( current = menu->items; current != 0; current = current->next ) + { + TRect r = getItemRect( current ); + if( r.contains(mouse) ) + return; + } +} + +void TMenuView::nextItem() +{ + if( (current = current->next) == 0 ) + current = menu->items; +} + +void TMenuView::prevItem() +{ + TMenuItem *p; + + if( (p = current) == menu->items) + p = 0; + + do { + nextItem(); + } while( current->next != p ); +} + +void TMenuView::trackKey( Boolean findNext ) +{ + if( current == 0 ) + return; + + do { + if( findNext ) + nextItem(); + else + prevItem(); + } while( current->name == 0 ); +} + +Boolean TMenuView::mouseInOwner( TEvent& e ) +{ + if( parentMenu == 0 || parentMenu->size.y != 1 ) + return False; + else + { + TPoint mouse = parentMenu->makeLocal( e.mouse.where ); + TRect r = parentMenu->getItemRect( parentMenu->current ); + return r.contains( mouse ); + } +} + +Boolean TMenuView::mouseInMenus( TEvent& e ) +{ + TMenuView *p = parentMenu; + while( p != 0 && !p->mouseInView(e.mouse.where) ) + p = p->parentMenu; + + return Boolean( p != 0 ); +} + +TMenuView *TMenuView::topMenu() +{ + TMenuView *p = this; + while( p->parentMenu != 0 ) + p = p->parentMenu; + return p; +} + +enum menuAction { doNothing, doSelect, doReturn }; + +ushort TMenuView::execute() +{ + Boolean autoSelect = False; + menuAction action; + char ch; + int withAlt; + ushort result = 0; + TMenuItem *itemShown = 0; + TMenuItem *p; + TMenuView *target; + TRect r; + TEvent e; + + current = menu->deflt; + do { + action = doNothing; + getEvent(e); + switch (e.what) + { + case evMouseDown: + if( mouseInView(e.mouse.where) || mouseInOwner(e) ) + { + trackMouse(e); + if( size.y == 1 ) + autoSelect = True; + } + else + action = doReturn; + break; + case evMouseUp: + trackMouse(e); + if( mouseInOwner(e) ) + current = menu->deflt; + else if( current != 0 && current->name != 0 ) + action = doSelect; + else + action = doReturn; + break; + case evMouseMove: + if( e.mouse.buttons != 0 ) + { + trackMouse(e); + if( !(mouseInView(e.mouse.where) || mouseInOwner(e)) && + mouseInMenus(e) ) + action = doReturn; + } + break; + case evKeyDown: + switch( ctrlToArrow(e.keyDown.keyCode) ) + { + case kbUp: + case kbDown: + if( size.y != 1 ) + trackKey(Boolean(ctrlToArrow(e.keyDown.keyCode) == kbDown)); + else if( e.keyDown.keyCode == kbDown ) + autoSelect = True; + break; + case kbLeft: + case kbRight: + if( parentMenu == 0 ) + trackKey(Boolean(ctrlToArrow(e.keyDown.keyCode) == kbRight)); + else + action = doReturn; + break; + case kbHome: + case kbEnd: + if( size.y != 1 ) + { + current = menu->items; + if( e.keyDown.keyCode == kbEnd ) + trackKey(False); + } + break; + case kbEnter: + if( size.y == 1 ) + autoSelect = True; + action = doSelect; + break; + case kbEsc: + action = doReturn; + if( parentMenu == 0 || parentMenu->size.y != 1 ) + clearEvent(e); + break; + default: + target = this; + ch = TGKey::GetAltChar(e.keyDown.keyCode, + e.keyDown.charScan.charCode); + withAlt = e.keyDown.keyCode & (kbAltRCode | kbAltLCode); + if( ch == 0 ) + ch = e.keyDown.charScan.charCode; + if( withAlt ) + {// SET: Original behavior + if( ch ) + target = topMenu(); + p = target->findItem(ch); + } + else + {// SET: without alt pressed, look here. + // Robert did it unconditionaly, but using Alt state + // is better. + p = target->findItem(ch); + if( p == 0 ) + { + // and now in the main menu + target = topMenu(); + p = target->findItem(ch); + } + } + if( p == 0 ) + { + p = topMenu()->hotKey(e.keyDown.keyCode); + if( p != 0 && commandEnabled(p->command) ) + { + result = p->command; + action = doReturn; + } + } + else if( target == this ) + { + if( size.y == 1 ) + autoSelect = True; + action = doSelect; + current = p; + } + else if( parentMenu != target || + parentMenu->current != p ) + action = doReturn; + } + break; + case evCommand: + if( e.message.command == cmMenu ) + { + autoSelect = False; + if (parentMenu != 0 ) + action = doReturn; + } + else + action = doReturn; + break; + } + + if( itemShown != current ) + { + itemShown = current; + drawView(); + } + + if( (action == doSelect || (action == doNothing && autoSelect)) && + current != 0 && + current->name != 0 ) + { + if( current->command == 0 ) + { + if( (e.what & (evMouseDown | evMouseMove)) != 0 ) + putEvent(e); + r = getItemRect( current ); + r.a.x = r.a.x + origin.x; + r.a.y = r.b.y + origin.y; + r.b = owner->size; + if( compactMenu && size.y == 1 ) // SET + r.a.x--; + target = topMenu()->newSubView(r, current->subMenu,this); + result = owner->execView(target); + CLY_destroy( target ); + } + else if( action == doSelect ) + result = current->command; + } + + if( result != 0 && commandEnabled(result) ) + { + action = doReturn; + clearEvent(e); + } + else + result = 0; + } while( action != doReturn ); + + if( e.what != evNothing && + (parentMenu != 0 || e.what == evCommand)) + putEvent(e); + if( current != 0 ) + { + menu->deflt = current; + current = 0; + drawView(); + } + return result; +} + +TMenuItem *TMenuView::findItem( char ch ) +{ + if( !ch ) return 0; + ch = TVCodePage::toUpper(ch); + TMenuItem *p = menu->items; + while( p != 0 ) + { + if( p->name != 0 && !p->disabled ) + { + const char *loc = strchr( TVIntl::getText(p->name,p->intlName), '~' ); + if( loc != 0 && TGKey::CompareASCII(ch,TVCodePage::toUpper(loc[1])) ) + return p; + } + p = p->next; + } + return 0; +} + +TRect TMenuView::getItemRect( TMenuItem * ) +{ + return TRect( 0, 0, 0, 0 ); +} + +ushort TMenuView::getHelpCtx() +{ + TMenuView *c = this; + + while( c != 0 && + (c->current == 0 || + c->current->helpCtx == hcNoContext || + c->current->name == 0 ) + ) + c = c->parentMenu; + + if( c != 0 ) + return c->current->helpCtx; + else + return hcNoContext; +} + +TPalette& TMenuView::getPalette() const +{ + static TPalette palette( cpMenuView, sizeof( cpMenuView )-1 ); + return palette; +} + +Boolean TMenuView::updateMenu( TMenu *menu ) +{ + if (!menu) return False; + Boolean res = False; + for( TMenuItem *p = menu->items; p != 0; p = p->next ) + { + if( p->name != 0 ) + { + if( p->command == 0 ) + { + if (updateMenu(p->subMenu) == True) + res = True; + } + else + { + Boolean commandState = commandEnabled(p->command); + if( p->disabled == commandState ) + { + p->disabled = Boolean(!commandState); + res = True; + } + } + } + } + return res; +} + +void TMenuView::do_a_select( TEvent& event ) +{ + putEvent( event ); + event.message.command = owner->execView(this); + if( event.message.command != 0 && commandEnabled(event.message.command) ) + { + event.what = evCommand; + event.message.infoPtr = 0; + putEvent(event); + } + clearEvent(event); +} + +/**[txh]******************************************************************** + + Description: + This is the code to look-up an item from a key. Used by handleEvent. + + Return: True if the item was found. + +***************************************************************************/ + +Boolean TMenuView::keyToItem(TEvent &event) +{ + if (findItem(TGKey::GetAltChar(event.keyDown.keyCode, + event.keyDown.charScan.charCode))) + { + putEvent(event); + do_a_select(event); + return True; + } + return False; +} + +/**[txh]******************************************************************** + + Description: + This is the code to look-up a short cut from a key. Used by handleEvent. + + Return: True if the item was found. + +***************************************************************************/ + +Boolean TMenuView::keyToHotKey(TEvent &event) +{ + TMenuItem *p=hotKey(event.keyDown.keyCode); + if (p && commandEnabled(p->command)) + { + event.what=evCommand; + event.message.command=p->command; + event.message.infoPtr=0; + putEvent(event); + clearEvent(event); + } + return p ? True : False; +} + +void TMenuView::handleEvent( TEvent& event ) +{ + if( menu != 0 ) + switch (event.what) + { + case evMouseDown: + do_a_select(event); + break; + case evKeyDown: + if(! keyToItem(event) ) + keyToHotKey(event); + break; + case evCommand: + if( event.message.command == cmMenu ) + do_a_select(event); + break; + case evBroadcast: + if( event.message.command == cmCommandSetChanged ) + { + if( updateMenu(menu) ) + drawView(); + } + break; + } +} + + +TMenuItem *TMenuView::findHotKey( TMenuItem *p, ushort keyCode ) +{ + + while( p != 0 ) + { + if( p->name != 0 ) + { + if( p->command == 0 ) + { + TMenuItem *T; + if( (T = findHotKey( p->subMenu->items, keyCode )) != 0 ) + return T; + } + else if( !p->disabled && + p->keyCode != kbNoKey && + p->keyCode == keyCode + ) + return p; + } + p = p->next; + } + return 0; +} + +TMenuItem *TMenuView::hotKey( ushort keyCode ) +{ + return findHotKey( menu->items, keyCode ); +} + +TMenuView *TMenuView::newSubView( const TRect& bounds, + TMenu *aMenu, + TMenuView *aParentMenu + ) +{ + return new TMenuBox( bounds, aMenu, aParentMenu ); +} + +#if !defined( NO_STREAM ) +void TMenuView::writeMenu( opstream& os, TMenu *menu ) +{ + uchar tok = 0xFF; + for( TMenuItem *item = menu->items; item != 0; item = item->next ) + { + os << tok; + os.writeString( item->name ); + os << item->command << (short)(item->disabled) + << item->keyCode << item->helpCtx; + if( item->name != 0 ) + { + if( item->command == 0 ) + writeMenu( os, item->subMenu ); + else + os.writeString( item->param ); + } + } + tok = 0; + os << tok; +} + +void TMenuView::write( opstream& os ) +{ + TView::write( os ); + writeMenu( os, menu ); +} + +TMenu *TMenuView::readMenu( ipstream& is ) +{ + TMenu *menu = new TMenu; + TMenuItem **last = &(menu->items); + TMenuItem *item = 0; + uchar tok; + is >> tok; + while( tok != 0 ) + { + assert( tok == 0xFF ); + item = new TMenuItem( (const char *)NULL, 0, (TMenu *)NULL ); + *last = item; + last = &(item->next); + item->name = is.readString(); + item->intlName = NULL; + short temp; + is >> item->command >> temp + >> item->keyCode >> item->helpCtx; + item->disabled = Boolean( temp ); + if( item->name != 0 ) + { + if( item->command == 0 ) + item->subMenu = readMenu( is ); + else + item->param = is.readString(); + } + is >> tok; + } + *last = 0; + menu->deflt = menu->items; + return menu; +} + +void *TMenuView::read( ipstream& is ) +{ + TView::read( is ); + menu = readMenu( is ); + parentMenu = 0; + current = 0; + return this; +} + +TStreamable *TMenuView::build() +{ + return new TMenuView( streamableInit ); +} + +TMenuView::TMenuView( StreamableInit ) : TView( streamableInit ) +{ +} +#endif // NO_STREAM + + diff --git a/tvision/classes/tmonosel.cc b/tvision/classes/tmonosel.cc new file mode 100644 index 0000000..8eb2162 --- /dev/null +++ b/tvision/classes/tmonosel.cc @@ -0,0 +1,91 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Salvador E. Tropea to compile for 64 bits architectures. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_string + +#define Uses_TKeys +#define Uses_TMonoSelector +#define Uses_TSItem +#define Uses_TEvent +#define Uses_TDrawBuffer +#define Uses_TGroup +#define Uses_TRect +#define Uses_opstream +#define Uses_ipstream +#include + +const uchar monoColors[] = { 0x07, 0x0F, 0x01, 0x70, 0x09 }; + +TMonoSelector::TMonoSelector( const TRect& bounds ) : + TCluster( bounds, new TSItem( _("Normal"), + new TSItem( _("Highlight"), + new TSItem( _("Underline"), + new TSItem( _("Inverse"), 0 ))))) +{ + eventMask |= evBroadcast; +} + +void TMonoSelector::draw() +{ + drawBox( button, 0x07 ); +} + +void TMonoSelector::handleEvent( TEvent& event ) +{ + TCluster::handleEvent( event ); + if( event.what == evBroadcast && event.message.command == cmColorSet ) + { + value = event.message.infoLong; + drawView(); + } +} + +Boolean TMonoSelector::mark( int item ) +{ + return Boolean(monoColors[item] == (uchar)value); +} + +void TMonoSelector::newColor() +{ + message( owner, evBroadcast, cmColorForegroundChanged, + (void *)(uipointer)(value & 0x0F) ); + message( owner, evBroadcast, cmColorBackgroundChanged, + (void *)(uipointer)((value >> 4) & 0x0F)); +} + +void TMonoSelector::press( int item ) +{ + value = monoColors[item]; + newColor(); +} + +void TMonoSelector::movedTo( int item ) +{ + value = monoColors[item]; + newColor(); +} + +#if !defined( NO_STREAM ) +TStreamable *TMonoSelector::build() +{ + return new TMonoSelector( streamableInit ); +} + +TMonoSelector::TMonoSelector( StreamableInit ) : TCluster( streamableInit ) +{ +} +#endif // NO_STREAM + + diff --git a/tvision/classes/tmouse.cc b/tvision/classes/tmouse.cc new file mode 100644 index 0000000..10db771 --- /dev/null +++ b/tvision/classes/tmouse.cc @@ -0,0 +1,27 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#define Uses_TEvent +#include + +TMouse::TMouse() +{ + show(); +} + +TMouse::~TMouse() +{ + hide(); +} + + diff --git a/tvision/classes/tnscolle.cc b/tvision/classes/tnscolle.cc new file mode 100644 index 0000000..86a124a --- /dev/null +++ b/tvision/classes/tnscolle.cc @@ -0,0 +1,235 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Vadim Beloborodov to be used on WIN32 console +Modified by Salvador E. Tropea (atReplace and other stuff) + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_string +#define Uses_abort +#define Uses_TNSCollection +#include + +TNSCollection::TNSCollection( ccIndex aLimit, ccIndex aDelta ) : + items( 0 ), + count( 0 ), + limit( 0 ), + delta( aDelta ), + shouldDelete( True ) +{ + setLimit( aLimit ); +} + +TNSCollection::TNSCollection() : + items( 0 ), + count( 0 ), + limit( 0 ), + delta( 0 ), + shouldDelete( True ) +{ + items = 0; +} + +TNSCollection::~TNSCollection() +{ + delete[] items; +} + +void TNSCollection::shutDown() +{ + if( shouldDelete ) + freeAll(); + else + count = 0; + setLimit(0); + TObject::shutDown(); +} + +void TNSCollection::atRemove( ccIndex index ) +{ + if( index < 0 || index >= count ) + error(1,0); + + count--; + CLY_memcpy( &items[index], &items[index+1], (count-index)*sizeof(void *) ); +} + +void TNSCollection::atFree( ccIndex index ) +{ + void *item = at( index ); // It could be: (*this)[index]; + atRemove( index ); + freeItem( item ); +} + +void TNSCollection::atInsert(ccIndex index, void *item) +{ + if( index < 0 ) + error(1,0); + if( count == limit ) + setLimit(count + delta); + + memmove( &items[index+1], &items[index], (count-index)*sizeof(void *) ); + count++; + + items[index] = item; +} + +void TNSCollection::atPut( ccIndex index, void *item ) +{ + if( index >= count ) + error(1,0); + + items[index] = item; +} + +// by SET +void TNSCollection::atReplace( ccIndex index, void *item ) +{ + freeItem( at( index ) ); + atPut( index, item ); +} + +void TNSCollection::remove( void *item ) +{ + atRemove( indexOf(item) ); +} + +void TNSCollection::removeAll() +{ + count = 0; +} + +void TNSCollection::error( ccIndex /* code */, ccIndex ) +{ +#if 0 + exit(212 - code); +#else + abort(); +#endif +} + +void *TNSCollection::firstThat( ccTestFunc Test, void *arg ) +{ + for( ccIndex i = 0; i < count; i++ ) + { + if( Test( items[i], arg ) == True ) + return items[i]; + } + return 0; +} + +void *TNSCollection::lastThat( ccTestFunc Test, void *arg ) +{ + for( ccIndex i = count; i > 0; i-- ) + { + if( Test( items[i-1], arg ) == True ) + return items[i-1]; + } + return 0; +} + +void TNSCollection::forEach( ccAppFunc action, void *arg ) +{ + for( ccIndex i = 0; i < count; i++ ) + action( items[i], arg ); +} + +// Avoid replacing free by MSS's macro +#include + +void TNSCollection::free( void *item ) +{ + remove( item ); + freeItem( item ); +} + +#include + +void TNSCollection::freeAll() +{ + for( ccIndex i = 0; i < count; i++ ) + freeItem( at(i) ); + count = 0; +} + +void TNSCollection::freeItem( void *item ) +{ + delete[] (char *)item; +} + +ccIndex TNSCollection::indexOf(void *item) +{ + for( ccIndex i = 0; i < count; i++ ) + if( item == items[i] ) + return i; + + error(1,0); + return -1; +} + +ccIndex TNSCollection::insert( void *item ) +{ + ccIndex loc = count; + atInsert( count, item ); + return loc; +} + +void TNSCollection::pack() +{ + if (count == 0) return; + void **curDst = items; + void **curSrc = items; + void **last = items + count; + while( curSrc < last ) + { + if( *curSrc != 0 ) + *curDst++ = *curSrc; + curSrc++; + } +} + +void TNSCollection::setLimit(ccIndex aLimit) +{ + if( aLimit < count ) + aLimit = count; + if( aLimit > maxCollectionSize) + aLimit = maxCollectionSize; + if( aLimit != limit ) + { + void **aItems; + if (aLimit == 0 ) + aItems = 0; + else + { + aItems = new void *[aLimit]; + if( count != 0 && items ) + memcpy( aItems, items, count*sizeof(void *) ); + } + if (items) + delete[] items; + items = aItems; + limit = aLimit; + } +} + +/**[txh]******************************************************************** + + Description: + Just like at() but not inline and easier to call in some cases. + +***************************************************************************/ + +void *TNSCollection::operator[](ccIndex i) +{ + if (i<0 || i>=count) + error(1,0); + return items[i]; +} diff --git a/tvision/classes/tnssorte.cc b/tvision/classes/tnssorte.cc new file mode 100644 index 0000000..6d43685 --- /dev/null +++ b/tvision/classes/tnssorte.cc @@ -0,0 +1,114 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#define Uses_TNSSortedCollection +#include + + +ccIndex TNSSortedCollection::indexOf(void *item) +{ + ccIndex i; + + if( search( keyOf(item), i ) == 0 ) + return ccNotFound; + else + { + if( duplicates ) + { + while( i < count && item != items[i] ) + i++; + } + if( i < count ) + return i; + else + return ccNotFound; + } +} + +ccIndex TNSSortedCollection::insert( void *item ) +{ + ccIndex i; + if( search( keyOf(item), i ) == 0 || duplicates ) // order dependency! + atInsert( i, item ); // must do Search + // before calling + // AtInsert + return i; +} + +void *TNSSortedCollection::keyOf( void *item ) +{ + return item; +} + +Boolean TNSSortedCollection::search( void *key, ccIndex& index ) +{ + ccIndex l = 0; + ccIndex h = count - 1; + Boolean res = False; + // The following is good to avoid problems but have a huge draw-back: + // keys can't be 0. In some cases 0 *is* a valid key and in this case + // the search will be skipped producing nasty bugs. + //if ( !key ) return False; + while( l <= h ) + { + ccIndex i = (l + h) >> 1; + ccIndex c = compare( keyOf( items[i] ), key ); + if( c < 0 ) + l = i + 1; + else + { + h = i - 1; + if( c == 0 ) + { + res = True; + if( !duplicates ) + l = i; + } + } + } + index = l; + return res; +} + +/**[txh]******************************************************************** + + Description: + It sorts the collection again. This is useful when the value returned by +keyOf can be changed and you need to sort the collection according to the +new value returned by keyOf. + It is currently implemented using buble sort algorithm, a better solution +is welcome. + Added by SET. + +***************************************************************************/ + +void TNSSortedCollection::reSort() +{ + Boolean sorted; + do + { + sorted=True; + for (int i=1; i + +TObject::~TObject() +{ +} + +void TObject::shutDown() +{ +} diff --git a/tvision/classes/tpalette.cc b/tvision/classes/tpalette.cc new file mode 100644 index 0000000..6ee1a09 --- /dev/null +++ b/tvision/classes/tpalette.cc @@ -0,0 +1,51 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Vadim Beloborodov to be used on WIN32 console + * + * + */ + +#define Uses_string //memcpy() +#define Uses_TPalette +#include + +TPalette::TPalette( const char* d, ushort len ) : + data( new uchar[ len+1 ] ) +{ + data[0] = len; + memcpy( data+1, d, len ); +} + +TPalette::TPalette( const TPalette& tp ) : + data( new uchar[ tp.data[0]+1 ] ) +{ + memcpy( data, tp.data, tp.data[0]+1 ); +} + +TPalette::~TPalette() +{ + delete[] data; +} + +TPalette& TPalette::operator = ( const TPalette& tp ) +{ + if( data != tp.data ) + { + if( data[0] != tp.data[0] ) + { + delete[] data; + data = new uchar[ tp.data[0]+1 ]; + data[0] = tp.data[0]; + } + memcpy( data+1, tp.data+1, data[0] ); + } + return *this; +} + + diff --git a/tvision/classes/tparamte.cc b/tvision/classes/tparamte.cc new file mode 100644 index 0000000..075b1f3 --- /dev/null +++ b/tvision/classes/tparamte.cc @@ -0,0 +1,96 @@ +/*------------------------------------------------------------*/ +/* filename - tparamte.cc */ +/* */ +/* function(s) */ +/* TParamText member functions */ +/*------------------------------------------------------------*/ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + * Modified by Salvador E. Tropea (SET) for RHTVision port. + * + * Big Warning!!!!! This code uses a 256 bytes buffer and doesn't check + * for overflow. + * I added: + * 1) The limit is now a constant defined in tparamTextMaxLen, so you can + * adjust it. + * 2) If SAFE_CODE is defined (default) the setText() member checks the + * lenght of the string. I use snprintf to limit the size. + * + * Portability note: + * getText( char *s, int maxLen ) and BTV uses: getText( char *s ) + * That's because Robert modified TStaticText, I think that's good, asking + * to write in a string without knowing the length is a very bad idea. + * + */ +#define Uses_stdio +#define Uses_stdarg +#define Uses_string +#define Uses_snprintf + +#define Uses_TParamText +#include + +TParamText::TParamText( const TRect& bounds ) : + TStaticText(bounds, 0 ), + str( new char [tparamTextMaxLen] ) +{ + str[0] = EOS; +} + +TParamText::~TParamText() +{ + delete[] str; +} + +// , int maxLen ) isn't part of TV 2.0 +void TParamText::getText( char *s, int maxLen ) +{ + if( str == 0 ) + *s = EOS; + else + { + strncpy( s, str, maxLen ); + s[maxLen] = 0; + } +} + +int TParamText::getTextLen() +{ + return (str != 0) ? strlen( str ) : 0; +} + +void TParamText::setText( const char *fmt, ... ) +{ + va_list ap; + + #ifdef SAFE_CODE + // Slow but we can check the overflow + va_start( ap, fmt ); + CLY_vsnprintf(str, (size_t)tparamTextMaxLen, fmt, ap); + va_end( ap ); + str[tparamTextMaxLen-1]=0; + #else + va_start( ap, fmt ); + vsprintf( str, fmt, ap ); + va_end( ap ); + #endif + + drawView(); +} + +#if !defined(NO_STREAM) + +TStreamable *TParamText::build() +{ + return new TParamText( streamableInit ); +} + +TParamText::TParamText( StreamableInit ) : TStaticText( streamableInit ) +{ +} + +#endif diff --git a/tvision/classes/tpoint.cc b/tvision/classes/tpoint.cc new file mode 100644 index 0000000..7a1dd8c --- /dev/null +++ b/tvision/classes/tpoint.cc @@ -0,0 +1,42 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#define Uses_TPoint +#include + +TPoint operator - ( const TPoint& one, const TPoint& two ) +{ + TPoint result; + result.x = one.x - two.x; + result.y = one.y - two.y; + return result; +} + +TPoint operator + ( const TPoint& one, const TPoint& two ) +{ + TPoint result; + result.x = one.x + two.x; + result.y = one.y + two.y; + return result; +} + +int operator == ( const TPoint& one, const TPoint& two ) +{ + return one.x == two.x && one.y == two.y; +} + +int operator!= ( const TPoint& one, const TPoint& two ) +{ + return one.x != two.x || one.y != two.y; +} + diff --git a/tvision/classes/tprogini.cc b/tvision/classes/tprogini.cc new file mode 100644 index 0000000..85f9280 --- /dev/null +++ b/tvision/classes/tprogini.cc @@ -0,0 +1,53 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#define Uses_TProgram +#define Uses_TStatusLine +#define Uses_TDeskTop +#define Uses_TMenuBar +#define Uses_TScreen +#define Uses_TVConfigFile +#include + +TScreen *TProgInit::tsc=NULL; +TVMainConfigFile *TProgInit::config=NULL; + +TProgInit::TProgInit( TStatusLine *(*cStatusLine)( TRect ), + TMenuBar *(*cMenuBar)( TRect ), + TDeskTop *(*cDeskTop )( TRect ) + ) : + createStatusLine( cStatusLine ), + createMenuBar( cMenuBar ), + createDeskTop( cDeskTop ) +{ + // Load the configuration file + if (!config) + config=new TVMainConfigFile(); + config->Load(); + // Read common settings + long aux; + if (config->Search("ShowCursorEver",aux)) + TScreen::setShowCursorEver(aux ? True : False); + if (config->Search("DontMoveHiddenCursor",aux)) + TScreen::setDontMoveHiddenCursor(aux ? True : False); + + tsc=new TScreen(); +} + +TProgInit::~TProgInit() +{ + delete tsc; + delete config; + tsc=NULL; + config=NULL; +} diff --git a/tvision/classes/tprogram.cc b/tvision/classes/tprogram.cc new file mode 100644 index 0000000..6a70ab4 --- /dev/null +++ b/tvision/classes/tprogram.cc @@ -0,0 +1,409 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Salvador E. Tropea (release CPU and other stuff) +Modified by Salvador E. Tropea to compile for 64 bits architectures. +Modified by Salvador E. Tropea to disable Alt+N stuff. + + * + * + */ + +#define Uses_TKeys +#define Uses_TProgram +#define Uses_TEvent +#define Uses_TScreen +#define Uses_TStatusLine +#define Uses_TMenu +#define Uses_TMenuItem +#define Uses_TGroup +#define Uses_TDeskTop +#define Uses_TEventQueue +#define Uses_TMenuBar +#define Uses_TStatusDef +#define Uses_TStatusItem +#define Uses_TPalette +#define Uses_TGKey +#define Uses_TVOSClipboard +#include + +#include + +// Public variables + +TStatusLine * TProgram::statusLine = 0; +TMenuBar * TProgram::menuBar = 0; +TDeskTop * TProgram::deskTop = 0; +TProgram * TProgram::application = 0; +int TProgram::appPalette = apColor; +TEvent TProgram::pending; +clock_t TProgram::lastIdleClock = 0; +clock_t TProgram::inIdleTime = 0; +Boolean TProgram::inIdle = False; +char TProgram::doNotReleaseCPU = 0; +char TProgram::doNotHandleAltNumber = 0; + +extern TPoint shadowSize; + +TProgram::TProgram() : + TProgInit( &TProgram::initStatusLine, + &TProgram::initMenuBar, + &TProgram::initDeskTop + ), + TGroup( TRect( 0,0,TScreen::screenWidth,TScreen::screenHeight ) ) +{ + application = this; + initScreen(); + state = sfVisible | sfSelected | sfFocused | sfModal | sfExposed; + options = 0; + syncScreenBuffer(); + + if( TScreen::noUserScreen() ) + disableCommand( cmCallShell ); + + if( createStatusLine != 0 && + (statusLine = createStatusLine( getExtent() )) != 0 + ) + insert(statusLine); + + if( createMenuBar != 0 && + (menuBar = createMenuBar( getExtent() )) != 0 + ) + insert(menuBar); + + if( createDeskTop != 0 && + (deskTop = createDeskTop( getExtent() )) != 0 + ) + insert(deskTop); + +} + +TProgram::~TProgram() +{ + application = 0; + if (TVOSClipboard::destroy) + TVOSClipboard::destroy(); +} + +void TProgram::shutDown() +{ + statusLine = 0; + menuBar = 0; + deskTop = 0; + TGroup::shutDown(); +} + +inline Boolean hasMouse( TView *p, void *s ) +{ + return Boolean( (p->state & sfVisible) != 0 && + p->mouseInView( ((TEvent *)s)->mouse.where )); +} + +#ifndef TVOS_UNIX +inline +clock_t Clock(void) +{ + return clock(); +} +#else +/* + In Linux clock returns time consumed by our program, so if ourprogram +sleeps it doesn't count so the screen saver and clock aren'tupdated. + Instead we must use gettimeofday. +*/ + +#include + +clock_t Clock(void) +{ + static int firstCall=1; + static struct timeval ref; + struct timeval cur; + clock_t ret; + + // If that's the first time take the value as reference + if (firstCall) + { + gettimeofday(&ref,0); + firstCall=0; + } + // Current time + gettimeofday(&cur,0); + // Substract the reference + cur.tv_sec-=ref.tv_sec; + if (cur.tv_usechandleEvent( event ); + } +} + +TPalette& TProgram::getPalette() const +{ + static TPalette color ( cpColor, sizeof( cpColor )-1 ); + static TPalette blackwhite( cpBlackWhite, sizeof( cpBlackWhite )-1 ); + static TPalette monochrome( cpMonochrome, sizeof( cpMonochrome )-1 ); + static TPalette *palettes[] = + { + &color, + &blackwhite, + &monochrome + }; + return *(palettes[appPalette]); +} + +void TProgram::handleEvent( TEvent& event ) +{ + if( !doNotHandleAltNumber && event.what == evKeyDown ) + { + char c = TGKey::GetAltChar( event.keyDown.keyCode, event.keyDown.charScan.charCode ); + if( c >= '1' && c <= '9' ) + { + if (current->valid(cmReleasedFocus)) + { + if( message( deskTop, + evBroadcast, + cmSelectWindowNum, + (void *)(uipointer)(c - '0') + ) != 0 ) + clearEvent( event ); + } + } + } + + TGroup::handleEvent( event ); + if( event.what == evCommand && event.message.command == cmQuit ) + { + endModal( cmQuit ); + clearEvent( event ); + } +} + +void TProgram::idle() +{ + if( statusLine != 0 ) + statusLine->update(); + + if( commandSetChanged == True ) + { + message( this, evBroadcast, cmCommandSetChanged, 0 ); + commandSetChanged = False; + } + // SET: Release the CPU unless the user doesn't want it. + if( !doNotReleaseCPU ) + { + CLY_ReleaseCPU(); // defined in ticks.cc + } +} + +TDeskTop *TProgram::initDeskTop( TRect r ) +{ + if (menuBar) + r.a.y += menuBar->size.y; + else + r.a.y++; + if (statusLine) + r.b.y -= statusLine->size.y; + else + r.b.y--; + return new TDeskTop( r ); +} + +TMenuBar *TProgram::initMenuBar( TRect r ) +{ + r.b.y = r.a.y + 1; + return new TMenuBar( r, (TMenu *)0 ); +} + +void TProgram::initScreen() +{ + if( !TDisplay::dual_display && (TScreen::screenMode & 0x00FF) != TDisplay::smMono ) + { + if( (TScreen::screenMode & TDisplay::smFont8x8) != 0 ) + shadowSize.x = 1; + else + shadowSize.x = 2; + shadowSize.y = 1; + showMarkers = False; + if( (TScreen::screenMode & 0x00FF) == TDisplay::smBW80 ) + appPalette = apBlackWhite; + else + appPalette = apColor; + } + else + { + + shadowSize.x = 0; + shadowSize.y = 0; + showMarkers = True; + appPalette = apMonochrome; + } +} + +TStatusLine *TProgram::initStatusLine( TRect r ) +{ + r.a.y = r.b.y - 1; + return new TStatusLine( r, + *new TStatusDef( 0, 0xFFFF ) + + *new TStatusItem( __("~Alt-X~ Exit"), kbAltX, cmQuit ) + + *new TStatusItem( 0, kbF10, cmMenu ) + + *new TStatusItem( 0, kbAltF3, cmClose ) + + *new TStatusItem( 0, kbF5, cmZoom ) + + *new TStatusItem( 0, kbCtrlF5, cmResize ) + ); +} + +void TProgram::outOfMemory() +{ +} + +void TProgram::putEvent( TEvent & event ) +{ + pending = event; +} + +void TProgram::run() +{ + execute(); +} + +void TProgram::setScreenMode( ushort mode, char *command ) +{ + TRect r; + + TMouse::hide(); + if (!TDisplay::dual_display) + { + if (mode==0xFFFF && command) + TScreen::setVideoModeExt( command ); + else + TScreen::setVideoMode( mode ); + } + initScreen(); + syncScreenBuffer(); + r = TRect( 0, 0, TScreen::screenWidth, TScreen::screenHeight ); + changeBounds( r ); + setState(sfExposed, False); + redraw(); + setState(sfExposed, True); + TMouse::show(); +} + +/**[txh]******************************************************************** + + Description: + Changes the screen mode to the closest resolution available. The @var{fW} +and @var{fH} is just a hint about the preferred font size and isn't +mandatory. If you really want to get a specific font size your application +should provide the font using a call back. + +***************************************************************************/ + +// SET +void TProgram::setScreenMode( unsigned w, unsigned h, int fW, int fH ) +{ + TRect r; + + TMouse::hide(); + if (TScreen::setVideoModeRes( w, h, fW, fH )) + { + initScreen(); + syncScreenBuffer(); + r = TRect( 0, 0, TScreen::screenWidth, TScreen::screenHeight ); + changeBounds( r ); + setState(sfExposed, False); + redraw(); + setState(sfExposed, True); + } + TMouse::show(); +} + +TView* TProgram::validView(TView* p) +{ + if( p == 0 ) + return 0; + if( lowMemory() ) + { + CLY_destroy( p ); + outOfMemory(); + return 0; + } + if( !p->valid( cmValid ) ) + { + CLY_destroy( p ); + return 0; + } + return p; +} + +void TProgram::syncScreenBuffer() +{ + buffer = TScreen::screenBuffer; +} + diff --git a/tvision/classes/tpwobj.cc b/tvision/classes/tpwobj.cc new file mode 100644 index 0000000..4b21ad8 --- /dev/null +++ b/tvision/classes/tpwobj.cc @@ -0,0 +1,20 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#define Uses_TPWrittenObjects +#include + +TPWObj::TPWObj( const void *adr, P_id_type id ) : address( adr ), ident( id ) +{ +} + diff --git a/tvision/classes/tpwreado.cc b/tvision/classes/tpwreado.cc new file mode 100644 index 0000000..b71b34b --- /dev/null +++ b/tvision/classes/tpwreado.cc @@ -0,0 +1,41 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#define Uses_TPReadObjects +#include + +#include + +TPReadObjects::TPReadObjects() : TNSCollection( 5, 5 ), curId( 0 ) +{ + shouldDelete = False; +} + +TPReadObjects::~TPReadObjects() +{ +} + +void TPReadObjects::registerObject( const void *adr ) +{ + ccIndex loc = insert( (void *)adr ); + assert( (unsigned)loc == curId); // to be sure that TNSCollection + // continues to work the way + // it does now... + curId++; // Increment moved out of assertion check... +} + +const void *TPReadObjects::find( P_id_type id ) +{ + return at( id ); +} + diff --git a/tvision/classes/tpwritte.cc b/tvision/classes/tpwritte.cc new file mode 100644 index 0000000..3236382 --- /dev/null +++ b/tvision/classes/tpwritte.cc @@ -0,0 +1,62 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#define Uses_TPWrittenObjects +#define Uses_TStreamableClass +#include + +TPWrittenObjects::TPWrittenObjects() : TNSSortedCollection( 5, 5 ), curId( 0 ) +{ + // SET: Why this? it just leaks memory, anybody knows? + //shouldDelete = False; +} + +TPWrittenObjects::~TPWrittenObjects() +{ +} + +void TPWrittenObjects::registerObject( const void *adr ) +{ + TPWObj *o = new TPWObj( adr, curId++ ); + insert( o ); +} + +void TPWrittenObjects::freeItem( void *item ) +{ + delete (TPWObj *)item; +} + +P_id_type TPWrittenObjects::find( const void *d ) +{ + ccIndex loc; + if( search( (void *)d, loc ) ) + return ((TPWObj *)at( loc ))->ident; + else + return P_id_notFound; +} + +void *TPWrittenObjects::keyOf( void *d ) +{ + return (void *)((TPWObj *)d)->address; +} + +int TPWrittenObjects::compare( void *o1, void *o2 ) +{ + if( o1 == o2 ) + return 0; + else if( ((char *)o1)+1 < ((char *)o2)+1 ) // force normalization + return -1; + else + return 1; +} + diff --git a/tvision/classes/tpxvalid.cc b/tvision/classes/tpxvalid.cc new file mode 100644 index 0000000..4cf8bea --- /dev/null +++ b/tvision/classes/tpxvalid.cc @@ -0,0 +1,500 @@ +/*------------------------------------------------------------*/ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + * Modified by Salvador E. Tropea. Covered by the GPL license. + * * Change NO_STREAM usage. + * * Fixed the code to avoid buffer overflows. + * * Modified to use TVCodePage. + */ + +#define Uses_TPXPictureValidator +#define Uses_MsgBox +#define Uses_AllocLocal +#define Uses_TVCodePage +#include + +// TPXPictureValidator + +const char * TPXPictureValidator::errorMsg = __("Error in picture format.\n %s"); + +TPXPictureValidator::TPXPictureValidator(const char* aPic, Boolean autoFill) + : TValidator() +{ + char s[1]; + + pic = newStr(aPic); + if ( autoFill ) + options |= voFill; + s[0] = 0; + if (picture(s, False) != prEmpty) + status = vsSyntax; +} + +#if !defined( NO_STREAM ) + +TPXPictureValidator::TPXPictureValidator( StreamableInit s ) : TValidator(s) +{ +} + +TStreamable * TPXPictureValidator::build() +{ + return (TStreamable *) new TPXPictureValidator(streamableInit); +} + +void TPXPictureValidator::write( opstream& os ) +{ + TValidator::write(os); + os.writeString(pic); +} + +void* TPXPictureValidator::read( ipstream& is ) +{ + TValidator::read(is); + pic = is.readString(); + index = jndex = 0; + + return this; +} + +#endif // !defined( NO_STREAM ) + +TPXPictureValidator::~TPXPictureValidator() +{ + delete pic; +}; + +void TPXPictureValidator::error() +{ + messageBox(mfError | mfOKButton, errorMsg, pic); +} + +Boolean TPXPictureValidator::isValidInput(char* s, Boolean suppressFill) +{ + Boolean doFill = Boolean(((options&voFill)!=0) && !suppressFill); + + return Boolean((pic==0) || (picture( (char*)s, doFill) != prError)); +} + +Boolean TPXPictureValidator::isValid(const char* s) +{ + // SET: Modified to allocate memory and avoid buffer overflows. + int l = strlen(s) + 1; + AllocLocalStr(str, l); + strcpy(str, s); + + return Boolean((pic == 0) || (picture(str, False) == prComplete)); +} + +static inline +Boolean isSpecial(char ch, const char* special) +{ + return strchr(special, ch) ? True : False; +} + +static inline +Boolean isComplete(TPicResult result) +{ + return Boolean((result == prComplete) || (result == prAmbiguous)); +} + +static inline +Boolean isIncomplete(TPicResult result) +{ + return Boolean( (result == prIncomplete) || (result == prIncompNoFill) ); +} + + +// TPXPictureValidator members + +// Consume input +void TPXPictureValidator::consume(char ch, char* input) +{ + input[jndex] = ch; + index++; + jndex++; +} + +// Skip a character or a picture group + +void TPXPictureValidator::toGroupEnd(int& i, int termCh) +{ + int brkLevel, brcLevel; + + brkLevel = 0; + brcLevel = 0; + do { + if (i == termCh) + return; + else + switch (pic[i]) + { + case '[': brkLevel++; break; + case ']': brkLevel--; break; + case '{': brcLevel++; break; + case '}': brcLevel--; break; + case ';': i++; break; + } + i++; + } while (! ((brkLevel == 0) && (brcLevel == 0))); +} + +// Find the a comma separator +Boolean TPXPictureValidator::skipToComma(int termCh) +{ + do { + toGroupEnd(index, termCh); + } while (! ( (index == termCh) || (pic[index] == ','))); + + if (pic[index] == ',') + index++; + return Boolean(index < termCh); +} + +// Calclate the end of a group +int TPXPictureValidator::calcTerm(int termCh) +{ + int k = index; + toGroupEnd(k, termCh); + return k; +} + +// The next group is repeated X times } +TPicResult TPXPictureValidator::iteration(char* input, int inTerm) +{ + int itr, k, l; + TPicResult rslt; + int termCh; + + itr = 0; + rslt = prError; + + index++; // Skip '*' + + // Retrieve number + + while (TVCodePage::isNumber(pic[index])) + { + itr = itr * 10 + (pic[index] - '0'); + index++; + } + + k = index; + termCh = calcTerm(inTerm); + + // If Itr is 0 allow any number, otherwise enforce the number + if (itr != 0) + { + for (l = 1; l <= itr; l++) + { + index = k; + rslt = process(input,termCh); + if ( ! isComplete(rslt)) + { + // Empty means incomplete since all are required + if (rslt == prEmpty) + rslt = prIncomplete; + + return rslt; + } + } + } + else + { + do { + index = k; + rslt = process(input, termCh); + } while (rslt == prComplete); + + if ((rslt == prEmpty) || (rslt == prError)) + { + index++; + rslt = prAmbiguous; + } + } + index = termCh; + + return rslt; +} + +// Process a picture group +TPicResult TPXPictureValidator::group(char* input, int inTerm) +{ + TPicResult rslt; + int termCh; + + termCh = calcTerm(inTerm); + index++; + rslt = process(input, termCh - 1); + + if (! isIncomplete(rslt)) + index = termCh; + + return rslt; +} + + +TPicResult TPXPictureValidator::checkComplete(TPicResult rslt, int termCh) +{ + int j = index; + Boolean Status=True; + + if (isIncomplete(rslt)) + { + // Skip optional pieces + while (Status) + switch (pic[j]) + { + case '[': + toGroupEnd(j, termCh); + break; + case '*': + if (! TVCodePage::isNumber(pic[j + 1])) + j++; + toGroupEnd(j, termCh); + break; + + default: + Status = False; + } + + if (j == termCh) + rslt = prAmbiguous; + } + + return rslt; +} + + +TPicResult TPXPictureValidator::scan(char* input, int termCh) +{ + char ch; + TPicResult rslt, rScan; + + rScan = prError; + rslt = prEmpty; + + while ( (index != termCh) && (pic[index] != ',')) + { + if ((size_t)jndex >= strlen(input)) + return checkComplete(rslt, termCh); + + ch = input[jndex]; + switch (pic[index]) + { + case '#': + if (! TVCodePage::isNumber(ch)) + return prError; + else + consume(ch, input); + break; + case '?': + if (! TVCodePage::isAlpha(ch)) + return prError; + else + consume(ch, input); + break; + case '&': + if (! TVCodePage::isAlpha(ch)) + return prError; + else + consume(TVCodePage::toUpper(ch), input); + break; + case '!': + consume(TVCodePage::toUpper(ch), input); + break; + case '@': + consume(ch, input); + break; + case '*': + + rslt = iteration(input,termCh); + if (! isComplete(rslt)) + return rslt; + + if (rslt == prError) + rslt = prAmbiguous; + break; + + case '{': + + rslt = group(input, termCh); + if (! isComplete(rslt)) + return rslt; + + break; + case '[': + + rslt = group(input, termCh); + if (isIncomplete(rslt)) + return rslt; + if (rslt == prError) + rslt = prAmbiguous; + + break; + + default: + + if (pic[index] == ';') + index++; + if (TVCodePage::toUpper(pic[index]) != TVCodePage::toUpper(ch)) + { + if (ch == ' ') + ch = pic[index]; + else + return rScan; + } + + consume(pic[index], input); + } + + if (rslt == prAmbiguous) + rslt = prIncompNoFill; + else + rslt = prIncomplete; + } + + if (rslt == prIncompNoFill) + return prAmbiguous; + else + return prComplete; +} + +TPicResult TPXPictureValidator::process(char* input, int termCh) +{ + + TPicResult rslt, rProcess; + Boolean incomp; + int oldI, oldJ, incompJ=0, incompI=0; + + incomp = False; + oldI = index; + oldJ = jndex; + do { + rslt = scan(input, termCh); + + // Only accept completes if they make it farther in the input + // stream from the last incomplete + + if ( (rslt == prComplete) && incomp && (jndex < incompJ)) + { + rslt = prIncomplete; + jndex = incompJ; + } + + if ((rslt == prError) || (rslt == prIncomplete)) + { + rProcess = rslt; + + if (! incomp && (rslt == prIncomplete) ) + { + incomp = True; + incompI = index; + incompJ = jndex; + } + index = oldI; + jndex = oldJ; + if (! skipToComma(termCh)) + { + if ( incomp ) + { + rProcess = prIncomplete; + index = incompI; + jndex = incompJ; + } + return rProcess; + } + oldI = index; + } + } while (!((rslt != prError) && (rslt != prIncomplete))); + + if ((rslt == prComplete) && incomp) + return prAmbiguous; + else + return rslt; +} + +Boolean TPXPictureValidator::syntaxCheck() +{ + + int i, len; + int brkLevel, brcLevel; + + if (!pic || (strlen(pic) == 0)) + return False; + + if (pic[strlen(pic)-1] == ';') + return False; + + i = 0; + brkLevel = 0; + brcLevel = 0; + + len = strlen(pic); + while (i < len) + { + switch (pic[i]) + { + case '[': brkLevel++; break; + case ']': brkLevel--; break; + case '{': brcLevel++; break; + case '}': brcLevel--; break; + case ';': i++; break; + } + i++; + } + + return Boolean( (brkLevel == 0) && (brcLevel == 0) ); +} + +TPicResult TPXPictureValidator::picture(char* input, Boolean autoFill) +{ + Boolean reprocess; + TPicResult rslt; + + if (!syntaxCheck()) + return prSyntax; + + if (!input || strlen(input)==0) + return prEmpty; + + jndex = 0; + index = 0; + + rslt = process(input, strlen(pic)); + + if ((rslt != prError) && ((size_t)jndex < strlen(input))) + rslt = prError; + + if ((rslt == prIncomplete) && autoFill) + { + reprocess = False; + + while (((size_t)index < strlen(pic)) && !isSpecial(pic[index], "#?&!@*{}[]")) + { + if (pic[index] == ';') + index++; + int end = strlen(input); + input[end] = pic[index]; + input[end+1] = 0; + index++; + reprocess = True; + } + + jndex = 0; + index = 0; + if (reprocess) + rslt = process(input, strlen(pic)); + } + + if (rslt == prAmbiguous) + return prComplete; + else if (rslt == prIncompNoFill) + return prIncomplete; + else + return rslt; +} + diff --git a/tvision/classes/tradiobu.cc b/tvision/classes/tradiobu.cc new file mode 100644 index 0000000..fcc3a43 --- /dev/null +++ b/tvision/classes/tradiobu.cc @@ -0,0 +1,98 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Added TRadioButtons32 and code page stuff by Salvador Eduardo Tropea. + + * + * + */ + +#define Uses_TRadioButtons +#define Uses_TStreamableClass +#include + +void TRadioButtons::draw() +{ + drawBox( button, check ); +} + +Boolean TRadioButtons::mark( int item ) +{ + return Boolean( (uint32)item == value ); +} + +void TRadioButtons::press( int item ) +{ + value = item; + TCluster::press(item); + evaluateMasks(); +} + +void TRadioButtons::movedTo( int item ) +{ + value = item; + TCluster::movedTo(item); + evaluateMasks(); +} + +void TRadioButtons::setData( void * rec ) +{ + TCluster::setData(rec); + sel = value; + evaluateMasks(); +} + +void TRadioButtons::evaluateMasks() +{ + if( !enableMasks ) + return; + int i; + unsigned mask, theMask; + + theMask = enableMasks[value]; + for( i = 0, mask = 1; i < enableCViews; mask <<= 1, i++ ) + { + TView *view = enableViews[i]; + if( theMask & mask ) + {// Enable this view + if( view->state & sfDisabled ) + view->setState( sfDisabled, False ); + } + else + {// Disable this view + if( !( view->state & sfDisabled ) ) + view->setState( sfDisabled, True ); + } + } +} + +uint32 TRadioButtons32::dataSize() +{ + return 4; +} + +#if !defined( NO_STREAM ) +TStreamable *TRadioButtons::build() +{ + return new TRadioButtons( streamableInit ); +} + +TRadioButtons::TRadioButtons( StreamableInit ) : TCluster( streamableInit ) +{ +} + +TStreamable *TRadioButtons32::build() +{ + return new TRadioButtons32( streamableInit ); +} + +TRadioButtons32::TRadioButtons32( StreamableInit ) : TRadioButtons( streamableInit ) +{ +} +#endif // NO_STREAM + diff --git a/tvision/classes/trangeva.cc b/tvision/classes/trangeva.cc new file mode 100644 index 0000000..58c96fa --- /dev/null +++ b/tvision/classes/trangeva.cc @@ -0,0 +1,142 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Heavily modified by Salvador E. Tropea (SET) to properly accept Hexadecimal +and octal numbers. Thanks to Andris Pavenis for suggestions. + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_stdlib +#define Uses_string +#define Uses_limits +#define Uses_stdio + +#define Uses_ipstream +#define Uses_opstream +#define Uses_TRangeValidator +#define Uses_MsgBox +#include + +// SET: Added hexadecimal letters +#define CT_VALID_CHARS "xX0123456789ABCDEFabcdef" +const char *ctValidChars="-+" CT_VALID_CHARS; +const char *ctValidCharsPos=ctValidChars+1; +const char *ctValidCharsNeg="-" CT_VALID_CHARS; + +TRangeValidator::TRangeValidator() : + TFilterValidator(ctValidChars) +{ + min = LONG_MIN; + max = LONG_MAX; +} + +TRangeValidator::TRangeValidator(long aMin,long aMax) : + TFilterValidator(ctValidChars) +{ + min = aMin; + max = aMax; + if (min >= 0) strcpy(validChars,ctValidCharsPos); + if (min < 0 && max < 0) strcpy(validChars,ctValidCharsNeg); +} + +void TRangeValidator::error() +{ + if (min >= 0) + messageBox(mfError|mfOKButton,__("Value not in the range %lu to %lu"), + (unsigned long)min,(unsigned long)max); + else + messageBox(mfError|mfOKButton,__("Value not in the range %li to %li"), + min,max); + // SET: Replaced %U and %D because MSVC lacks it +} + +static long get_val(const char *buf) +{ // SET: Changed to use strtol + char *end; + return strtol(buf,&end,0); +} + +static unsigned long get_uval(const char *buf) +{ // SET: Changed to use strtoul + char *end; + return strtoul(buf,&end,0); +} + + +Boolean TRangeValidator::isValid(const char *S) +{ + long value; + if (TFilterValidator::isValid(S) == False) return False; + if (min >= 0) + value = get_uval(S); + else + value = get_val(S); + if (min >= 0) + { + if ((unsigned long)value < (unsigned long)min || + (unsigned long)value > (unsigned long)max) + return False; + } + else + { + if (value < min || value > max) return False; + } + return True; +} + +ushort TRangeValidator::transfer(char *S,void * Buffer, + TVTransfer Flag) +{ + if (!(options & voTransfer)) return 0; + switch (Flag) + { + case vtGetData: + if (min >= 0) + *((unsigned long *)Buffer) = get_uval(S); + else + *((long *)Buffer) = get_val(S); + break; + case vtSetData: + if (min >= 0) + sprintf(S,"%lu",*((unsigned long *)Buffer)); + else + sprintf(S,"%ld",*((long *)Buffer)); + break; + default: + break; + } + return sizeof(long); +} + +#if !defined( NO_STREAM ) +TRangeValidator::TRangeValidator(StreamableInit) : + TFilterValidator(streamableInit) +{ +} + +TStreamable * TRangeValidator::build() +{ + return (TStreamable *) new TRangeValidator(streamableInit); +} + +void TRangeValidator::write(opstream & os) +{ + TFilterValidator::write(os); + os << min << max; +} + +void * TRangeValidator::read(ipstream & is) +{ + TFilterValidator::read(is); + is >> min >> max; + return this; +} +#endif // NO_STREAM + diff --git a/tvision/classes/trescoll.cc b/tvision/classes/trescoll.cc new file mode 100644 index 0000000..982e999 --- /dev/null +++ b/tvision/classes/trescoll.cc @@ -0,0 +1,60 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#define Uses_TResourceCollection +#define Uses_TResourceItem +#include + +TResourceCollection::TResourceCollection( ccIndex aLimit, ccIndex aDelta) : + TStringCollection( aLimit, aDelta) +{ +} + +void TResourceCollection::freeItem( void* item ) +{ + delete ((TResourceItem*)item)->key; + delete((TResourceItem*)item); +} + +void* TResourceCollection::keyOf( void* item ) +{ + return ((TResourceItem *)item)->key; +} + +#if !defined( NO_STREAM ) +TStreamable *TResourceCollection::build() +{ + return new TResourceCollection( streamableInit ); +} + +void TResourceCollection::writeItem( void *obj, opstream& os ) +{ + + os << ((TResourceItem *)obj)->pos; + os << ((TResourceItem *)obj)->size; + os.writeString(((TResourceItem *)obj)->key); + +} + +void *TResourceCollection::readItem( ipstream& is ) +{ + TResourceItem *obj; + + obj = new TResourceItem; + is >> obj->pos; + is >> obj->size; + obj->key = is.readString(); + return (void *)obj; +} +#endif // NO_STREAM + diff --git a/tvision/classes/tresfile.cc b/tvision/classes/tresfile.cc new file mode 100644 index 0000000..300c1ed --- /dev/null +++ b/tvision/classes/tresfile.cc @@ -0,0 +1,194 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified to compile with gcc v3.x by Salvador E. Tropea, with the help of +Andris Pavenis. + + * + * + */ + +#define Uses_TResourceFile +#define Uses_TResourceItem +#define Uses_fpstream +#define Uses_filelength +#define Uses_TCollection +#define Uses_TStringCollection +#define Uses_TResourceCollection +#include + +UsingNamespaceStd + +const long rStreamMagic = 0x52504246uL; // 'FBPR' + +#pragma pack(1) + +struct Count_type +{ + ushort lastCount CLY_Packed; + ushort pageCount CLY_Packed; +}; + +struct Info_type +{ + ushort infoType CLY_Packed; + long infoSize CLY_Packed; +}; + +struct THeader +{ + ushort signature CLY_Packed; + union + { + Count_type count; + Info_type info; + } CLY_Packed; +}; + +#pragma pack() + +TResourceFile::TResourceFile( fpstream *aStream ) : TObject() +{ + THeader *header; + int found; + int repeat; + long streamSize; + + stream = aStream; + basePos = stream->tellp(); + streamSize = stream->filelength(); + header = new THeader; + found = 0; + do { + repeat = 0; + if ((unsigned long)basePos <= (streamSize - sizeof(THeader))) + { + stream->seekg(basePos, CLY_IOSBeg); + stream->readBytes(header, sizeof(THeader)); + if (header->signature == 0x5a4d) + { + basePos += ((header->count.pageCount * 512L) - + (-header->count.lastCount & 511)); + repeat = 1; + } + else if (header->signature == 0x4246) + { + if (header->info.infoType == 0x5250) + found = 1; + else + { + basePos += + header->info.infoSize + 16 - (header->info.infoSize)%16; + repeat = 1; + } + } + } + } while (repeat); + + if (found) + { + stream->seekg(basePos + CLY_StreamPosT(sizeof(long) * 2), CLY_IOSBeg); + long aux; + *stream >> aux; + indexPos=aux; + stream->seekg(basePos + indexPos, CLY_IOSBeg); + *stream >> index; + } + else + { + indexPos = sizeof(long) * 3; + index = new TResourceCollection(0, 8); + } + delete header; +} + +TResourceFile::~TResourceFile() +{ + flush(); + CLY_destroy( (TCollection *)index ); + delete(stream); +} + +short TResourceFile::count() +{ + return index->getCount(); +} + +// Avoid replacing free by MSS's macro +#include + +void TResourceFile::remove( const char *key ) +{ + int i; + + if (index->search( (char *)key, i)) + { + index->free(index->at(i)); + modified = True; + } +} + +#include + +void TResourceFile::flush() +{ + long lenRez; + + if (modified == True) + { + stream->seekg(basePos + indexPos, CLY_IOSBeg); + *stream << index; + lenRez = stream->tellp() - basePos - CLY_StreamPosT(sizeof(long) * 2); + stream->seekg(basePos, CLY_IOSBeg); + *stream << rStreamMagic; + *stream << lenRez; + *stream << long(indexPos); + stream->flush(); + modified = False; + } +} + +void *TResourceFile::get( const char *key) +{ + int i; + void *p; + + if (! index->search((char *)key, i)) + return 0; + stream->seekg(basePos + CLY_StreamPosT(((TResourceItem*)(index->at(i)))->pos), + CLY_IOSBeg); + *stream >> p; + return p; +} + +const char *TResourceFile::keyAt(short i) +{ + return ((TResourceItem*)(index->at(i)))->key; +} + +void TResourceFile::put(TStreamable *item, const char *key) +{ + int i; + TResourceItem *p; + + if (index->search( (char *)key, i)) + p = (TResourceItem*)(index->at(i)); + else + { + p = new TResourceItem; + p->key = newStr(key); + index->atInsert(i, p); + } + p->pos = indexPos; + stream->seekp(basePos + indexPos, CLY_IOSBeg); + *stream << item; + indexPos = stream->tellp() - basePos; + p->size = indexPos - CLY_StreamPosT(p->pos); + modified = True; +} + diff --git a/tvision/classes/tscreen.cc b/tvision/classes/tscreen.cc new file mode 100644 index 0000000..47c875f --- /dev/null +++ b/tvision/classes/tscreen.cc @@ -0,0 +1,454 @@ +/**[txh]******************************************************************** + + Copyright 2001-2009 by Salvador E. Tropea + This file is covered by the GPL license. + + Module: Screen + Include: TScreen + Comments: + This is the base class for medium level screen output. + Most members are pointers to functions defined by each platform dependent +driver. Default members are provided. + This is a complete new file created from concepts that José Angel Sanchez +Caso provide me and coded from scratch. The names of some members are the +same used in original Turbo Vision for compatibility purposes. + +***************************************************************************/ + +#define Uses_stdio +#define Uses_stdlib +#define Uses_string +#define Uses_unistd +#define Uses_AllocLocal +#define Uses_ctype +#define Uses_TScreen +#define Uses_TVConfigFile +#define Uses_TGKey +#include +#include + +static void dummy() {} + +/***************************************************************************** + Data members initialization +*****************************************************************************/ + +ushort TScreen::startupMode=0; +ushort TScreen::screenMode=0; +ushort TScreen::startupCursor=0; +ushort TScreen::cursorLines=0; +uchar TScreen::screenWidth=80; +uchar TScreen::screenHeight=25; +Boolean TScreen::hiResScreen=False; +Boolean TScreen::checkSnow=False; +ushort *TScreen::screenBuffer=NULL; +char TScreen::suspended=1; +char TScreen::initialized=0; +char TScreen::initCalled=0; +char TScreen::useSecondaryFont=0; +uint32 TScreen::flags0=0; +TScreen *TScreen::driver=NULL; +const char + *TScreen::currentDriverShortName=NULL; +TVScreenFontRequestCallBack + TScreen::frCB=NULL; +long TScreen::forcedAppCP=-1, + TScreen::forcedScrCP=-1, + TScreen::forcedInpCP=-1; +int TScreen::maxAppHelperHandlers=8; + +/***************************************************************************** + Function pointer members initialization +*****************************************************************************/ + +void (*TScreen::setVideoMode)(ushort mode) =TScreen::defaultSetVideoMode; +void (*TScreen::setVideoModeExt)(char *mode) =TScreen::defaultSetVideoModeExt; +void (*TScreen::clearScreen)() =TScreen::defaultClearScreen; +void (*TScreen::setCrtData)() =TScreen::defaultSetCrtData; +ushort (*TScreen::fixCrtMode)(ushort mode) =TScreen::defaultFixCrtMode; +void (*TScreen::Suspend)() =dummy; +void (*TScreen::Resume)() =dummy; +ushort (*TScreen::getCharacter)(unsigned offset)=TScreen::defaultGetCharacter; +void (*TScreen::getCharacters)(unsigned offset, ushort *buf, unsigned count) + =TScreen::defaultGetCharacters; +void (*TScreen::setCharacter)(unsigned offset, ushort value) + =TScreen::defaultSetCharacter; +void (*TScreen::setCharacters)(unsigned offset, ushort *values, unsigned count) + =TScreen::defaultSetCharacters; +int (*TScreen::System_p)(const char *command, pid_t *pidChild, int in, + int out, int err) + =TScreen::defaultSystem; +int (*TScreen::getFontGeometry)(unsigned &w, unsigned &h) + =TScreen::defaultGetFontGeometry; +int (*TScreen::getFontGeometryRange)(unsigned &wmin, unsigned &hmin, + unsigned &umax, unsigned &hmax) + =TScreen::defaultGetFontGeometryRange; +int (*TScreen::setFont_p)(int changeP, TScreenFont256 *fontP, + int changeS, TScreenFont256 *fontS, + int fontCP, int appCP) + =TScreen::defaultSetFont; +void (*TScreen::restoreFonts)() =TScreen::defaultRestoreFonts; +int (*TScreen::setVideoModeRes_p)(unsigned w, unsigned h, int fW, int fH) + =TScreen::defaultSetVideoModeRes; +TScreen::appHelperHandler (*TScreen::openHelperApp)(AppHelper kind) + =TScreen::defaultOpenHelperApp; +Boolean (*TScreen::closeHelperApp)(appHelperHandler id) + =TScreen::defaultCloseHelperApp; +Boolean (*TScreen::sendFileToHelper)(appHelperHandler id, const char *file, void *extra) + =TScreen::defaultSendFileToHelper; +const char *(*TScreen::getHelperAppError)() =TScreen::defaultGetHelperAppError; + + +/***************************************************************************** + Default behaviors for the members +*****************************************************************************/ + +void TScreen::defaultSetVideoMode(ushort mode) +{// Set the screen mode + setCrtMode(fixCrtMode(mode)); + // Cache the data about it and initialize related stuff + setCrtData(); +} + +void TScreen::defaultSetVideoModeExt(char *mode) +{// Set the screen mode + setCrtModeExt(mode); + // Cache the data about it and initialize related stuff + setCrtData(); +} + +int TScreen::defaultSetVideoModeRes(unsigned w, unsigned h, int fW, int fH) +{// Set the screen mode + int ret=setCrtModeRes(w,h,fW,fH); + if (ret) + // Cache the data about it and initialize related stuff + setCrtData(); + return ret; +} + +void TScreen::defaultClearScreen() +{ + TDisplay::clearScreen(screenWidth,screenHeight); +} + +void TScreen::defaultSetCrtData() +{ + screenMode =getCrtMode(); + screenWidth =getCols(); + screenHeight=getRows(); + hiResScreen =Boolean(screenHeight>25); + cursorLines =getCursorType(); + setCursorType(0); +} + +ushort TScreen::defaultFixCrtMode(ushort mode) +{ + return mode; +} + +ushort TScreen::defaultGetCharacter(unsigned offset) +{ + return screenBuffer[offset]; +} + +void TScreen::defaultGetCharacters(unsigned offset, ushort *buf, unsigned count) +{ + memcpy(buf,screenBuffer+offset,count*sizeof(ushort)); +} + +void TScreen::defaultSetCharacter(unsigned offset, ushort value) +{ + screenBuffer[offset]=value; +} + +void TScreen::defaultSetCharacters(unsigned offset, ushort *values, unsigned count) +{ + memcpy(screenBuffer+offset,values,count*2); +} + +int TScreen::defaultSystem(const char *command, pid_t *pidChild, int in, int out, + int err) +{ + // fork mechanism not available + if (pidChild) + *pidChild=0; + // If the caller asks for redirection replace the requested handles + if (in!=-1) + dup2(in,STDIN_FILENO); + if (out!=-1) + dup2(out,STDOUT_FILENO); + if (err!=-1) + dup2(err,STDERR_FILENO); + return system(command); +} + +int TScreen::defaultGetFontGeometry(unsigned &, unsigned &) { return 0; } +int TScreen::defaultGetFontGeometryRange(unsigned &, unsigned &, + unsigned &, unsigned &) { return 0; } +int TScreen::defaultSetFont(int , TScreenFont256 *, int , TScreenFont256 *, + int, int) { return 0; } +void TScreen::defaultRestoreFonts() {} + +TScreen::appHelperHandler TScreen::defaultOpenHelperApp(TScreen::AppHelper) +{ return -1; } +Boolean TScreen::defaultCloseHelperApp(appHelperHandler) { return False; } +Boolean TScreen::defaultSendFileToHelper(appHelperHandler, const char *, void *) +{ return False; } +const char *TScreen::defaultGetHelperAppError() +{ + return __("This feature isn't implemented by the current driver."); +} + +/***************************************************************************** + Real members +*****************************************************************************/ + +struct stDriver +{ + // Test function for this driver + drvChecker driver; + // The drivers with more priority are tried first + int priority; + // Configuration section name for this driver + const char *name; +}; + +#ifdef TV_Disable_WinGr_Driver + #define TV_WinGr_Driver_Entry +#else + #define TV_WinGr_Driver_Entry { TV_WinGrDriverCheck, 80, "WinGr" }, +#endif + +static +stDriver Drivers[]= +{ + #ifdef TVOS_DOS + { TV_DOSDriverCheck, 100, "DOS" }, + #endif + + #ifdef TVOS_UNIX + #ifdef HAVE_X11 + { TV_XDriverCheck, 100, "X11" }, + #endif // HAVE_X11 + #ifdef TVOSf_Linux + { TV_LinuxDriverCheck, 90, "Linux" }, + #endif + #ifdef TVOSf_QNXRtP + { TV_QNXRtPDriverCheck, 90, "QNX" }, + #else + #ifdef TVOSf_QNX4 + { TV_QNX4DriverCheck, 90, "QNX4" }, + #endif // TVOSf_QNX4 + { TV_XTermDriverCheck, 60, "XTerm" }, + #ifdef HAVE_NCURSES + { TV_UNIXDriverCheck, 10, "UNIX" }, + #endif + #endif // TVOSf_QNXRtP + #endif + + #ifdef TVOS_Win32 + #ifdef HAVE_X11 + // This is experimental, but believe it or not Cygwin have X11 support + { TV_XDriverCheck, 100, "X11" }, + #endif // HAVE_X11 + #ifdef TVOSf_NT + { TV_WinNTDriverCheck, 90, "WinNT" }, + TV_WinGr_Driver_Entry + { TV_Win32DriverCheck, 50, "Win32" }, + #else + { TV_Win32DriverCheck, 90, "Win32" }, + TV_WinGr_Driver_Entry + { TV_WinNTDriverCheck, 50, "WinNT" }, + #endif + #endif + + #ifdef HAVE_ALLEGRO + { TV_AlconDriverCheck, 30, "AlCon" }, + #endif +}; + +const int nDrivers=sizeof(Drivers)/sizeof(stDriver); + +static +int cmpDrivers(const void *v1, const void *v2) +{ + int p1=((stDriver *)v1)->priority; + int p2=((stDriver *)v2)->priority; + return (p1p2); +} + +/**[txh]******************************************************************** + + Description: + This constructor is called when the TApplication object is created. The +TProgramInit constructor creates a dynamic copy instance of a TScreen +object.@* + Actually it calls the detection routines to determine the best driver +available. If non is found prints and error to the stderr output and aborts +the execution. + +***************************************************************************/ + +TScreen::TScreen() : + TDisplay() +{ + // When the real drivers creates a derived class they will call this + // constructor so we must avoid getting in an infinite loop. + // I know that's tricky but it helps to maintain compatibility with the + // old class structure. + if (initCalled) + return; + initCalled=1; + + // Check if the user changed priorities + int changed=0,i; + long priority; + for (i=0; i +#define Uses_string + +#define Uses_TKeys +#define Uses_TScrollBar +#define Uses_TRect +#define Uses_TDrawBuffer +#define Uses_TEvent +#define Uses_TGroup +#define Uses_opstream +#define Uses_ipstream +#define Uses_TPalette +#define Uses_TScreen +#include + +#define cpScrollBar "\x04\x05\x05" + +// Constants for the scroll bar components +const int csbUp=0, + csbDown=1, + csbDark=2, + csbMark=3, + csbBright=4; + +TScrollBar::TScrollBar( const TRect& bounds ) : + TView( bounds ), + value( 0 ), + minVal( 0 ), + maxVal( 0 ), + pgStep( 1 ), + arStep( 1 ) +{ + if( size.x == 1 ) + { + growMode = gfGrowLoX | gfGrowHiX | gfGrowHiY; + memcpy( chars, vChars, sizeof(vChars) ); + } + else + { + growMode = gfGrowLoY | gfGrowHiX | gfGrowHiY; + memcpy( chars, hChars, sizeof(hChars) ); + } + // This class can be "Braille friendly" + if (TScreen::getShowCursorEver()) + state |= sfCursorVis; +} + +void TScrollBar::draw() +{ + drawPos(getPos()); +} + +void TScrollBar::drawPos( int pos ) +{ + TDrawBuffer b; + char *aChars; + + // SET: If we can't remap characters use the originals + /*if (TScreen::codePageVariable()) + aChars=chars; + else*/ + // Unless somebody really needs the old behavior I'll just use it. + aChars=size.x==1 ? vChars : hChars; + + int s = getSize() - 1; + b.moveChar( 0, aChars[csbUp], getColor(2), 1 ); + if( maxVal == minVal ) + { + char unFilled=TScreen::avoidMoire ? TView::noMoireUnFill : aChars[csbDark]; + b.moveChar( 1, unFilled, getColor(1), s-1 ); + } + else + { + char filled =TScreen::avoidMoire ? TView::noMoireFill : aChars[csbBright]; + b.moveChar( 1, filled, getColor(1), s-1 ); + b.moveChar( pos, aChars[csbMark], getColor(3), 1 ); + if( state & sfFocused ) + { + setCursor( pos , 0 ); + resetCursor(); + } + } + + b.moveChar( s, aChars[csbDown], getColor(2), 1 ); + writeBuf( 0, 0, size.x, size.y, b ); +} + +TPalette& TScrollBar::getPalette() const +{ + static TPalette palette( cpScrollBar, sizeof( cpScrollBar )-1 ); + return palette; +} + +int32 TScrollBar::getPos() +{ + int32 r = maxVal - minVal; + if( r == 0 ) + return 1; + else + return int32(( ((long(value - minVal) * (getSize() - 3)) + (r >> 1)) / r) + 1); +} + +int TScrollBar::getSize() +{ + int s; + + if( size.x == 1 ) + s = size.y; + else + s = size.x; + + return max( 3, s ); +} + +static TPoint mouse; +static int32 p, s; +static TRect extent; + +int TScrollBar::getPartCode() +{ + int part= - 1; + if( extent.contains(mouse) ) + { + int mark = (size.x == 1) ? mouse.y : mouse.x; + + if (mark == p) + part= sbIndicator; + else + { + if( mark < 1 ) + part = sbLeftArrow; + else if( mark < p ) + part= sbPageLeft; + else if( mark < s ) + part= sbPageRight; + else + part= sbRightArrow; + + if( size.x == 1 ) + part += 4; + } + } + return part; +} + +void TScrollBar::handleEvent( TEvent& event ) +{ + Boolean Tracking; + int i=0, clickPart; + + TView::handleEvent(event); + switch( event.what ) + { + case evMouseDown: + message(owner, evBroadcast, cmScrollBarClicked,this); // Clicked() + mouse = makeLocal( event.mouse.where ); + extent = getExtent(); + extent.grow(1, 1); + p = getPos(); + s = getSize() - 1; + clickPart= getPartCode(); + if( clickPart != sbIndicator ) + { + do { + mouse = makeLocal( event.mouse.where ); + if( getPartCode() == clickPart ) + setValue(value + scrollStep(clickPart) ); + } while( mouseEvent(event, evMouseAuto) ); + } + else + { + do { + mouse = makeLocal( event.mouse.where ); + Tracking = extent.contains(mouse); + if( Tracking ) + { + if( size.x == 1 ) + i = mouse.y; + else + i = mouse.x; + i = max( i, 1 ); + i = min( i, s-1 ); + } + else + i = getPos(); + if(i != p ) + { + drawPos(i); + p = i; + } + } while( mouseEvent(event,evMouseMove) ); + if( Tracking && s > 2 ) + { + s -= 2; + setValue( int(((long(p - 1) * (maxVal - minVal) + (s >> 1)) / s) + minVal)); + } + } + clearEvent(event); + break; + case evKeyDown: + if( (state & sfVisible) != 0 ) + { + clickPart = sbIndicator; + if( size.y == 1 ) + switch( ctrlToArrow(event.keyDown.keyCode) ) + { + case kbLeft: + clickPart = sbLeftArrow; + break; + case kbRight: + clickPart = sbRightArrow; + break; + case kbCtrlLeft: + clickPart = sbPageLeft; + break; + case kbCtrlRight: + clickPart = sbPageRight; + break; + case kbHome: + i = minVal; + break; + case kbEnd: + i = maxVal; + break; + default: + return; + } + else + switch( ctrlToArrow(event.keyDown.keyCode) ) + { + case kbUp: + clickPart = sbUpArrow; + break; + case kbDown: + clickPart = sbDownArrow; + break; + case kbPgUp: + clickPart = sbPageUp; + break; + case kbPgDn: + clickPart = sbPageDown; + break; + case kbCtrlPgUp: + i = minVal; + break; + case kbCtrlPgDn: + i = maxVal; + break; + default: + return; + } + message(owner,evBroadcast,cmScrollBarClicked,this); // Clicked + if( clickPart != sbIndicator ) + i = value + scrollStep(clickPart); + setValue(i); + clearEvent(event); + } + } +} + +void TScrollBar::scrollDraw() +{ + message(owner, evBroadcast, cmScrollBarChanged,this); +} + +int TScrollBar::scrollStep( int part ) +{ + int step; + + if( !(part & 2) ) + step = arStep; + else + step = pgStep; + if( !(part & 1) ) + return -step; + else + return step; +} + +void TScrollBar::setParams( int32 aValue, + int32 aMin, + int32 aMax, + int aPgStep, + int aArStep + ) +{ + int32 sValue; + + aMax = max( aMax, aMin ); + aValue = max( aMin, aValue ); + aValue = min( aMax, aValue ); + sValue = value; + if( sValue != aValue || minVal != aMin || maxVal != aMax ) + { + value = aValue; + minVal = aMin; + maxVal = aMax; + drawView(); + if( sValue != aValue ) + scrollDraw(); + } + pgStep = aPgStep; + arStep = aArStep; +} + +void TScrollBar::setRange( int32 aMin, int32 aMax ) +{ + setParams( value, aMin, aMax, pgStep, arStep ); +} + +void TScrollBar::setStep( int aPgStep, int aArStep ) +{ + setParams( value, minVal, maxVal, aPgStep, aArStep ); +} + +void TScrollBar::setValue( int32 aValue ) +{ + setParams( aValue, minVal, maxVal, pgStep, arStep ); +} + +#if !defined( NO_STREAM ) +void TScrollBar::write( opstream& os ) +{ + TView::write( os ); + os << value << minVal << maxVal << pgStep << arStep; + os.writeBytes(chars, sizeof(chars)); +} + +void *TScrollBar::read( ipstream& is ) +{ + TView::read( is ); + is >> value >> minVal >> maxVal >> pgStep >> arStep; + is.readBytes(chars, sizeof(TScrollChars)); + return this; +} + +TStreamable *TScrollBar::build() +{ + return new TScrollBar( streamableInit ); +} + +TScrollBar::TScrollBar( StreamableInit ) : TView( streamableInit ) +{ +} +#endif // NO_STREAM + diff --git a/tvision/classes/tscrolle.cc b/tvision/classes/tscrolle.cc new file mode 100644 index 0000000..14eb837 --- /dev/null +++ b/tvision/classes/tscrolle.cc @@ -0,0 +1,215 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Salvador E. Tropea to support mouse wheels and other things. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#include +#define Uses_string + +#define Uses_TScroller +#define Uses_TScrollBar +#define Uses_TEvent +#define Uses_TRect +#define Uses_opstream +#define Uses_ipstream +#define Uses_TPalette +#define Uses_TScreen +#include + +#define cpScroller "\x06\x07" + +int TScroller::defaultWheelStep=5; + +TScroller::TScroller( const TRect& bounds, + TScrollBar *aHScrollBar, + TScrollBar *aVScrollBar) : + TView( bounds ), + drawLock( 0 ), + drawFlag( False ), + hScrollBar( aHScrollBar ), + vScrollBar( aVScrollBar ) +{ + delta.x = delta.y = limit.x = limit.y = 0; + options |= ofSelectable; + eventMask |= evBroadcast; + wheelStep = defaultWheelStep; + // This class can be "Braille friendly" + if (TScreen::getShowCursorEver()) + state |= sfCursorVis; +} + +void TScroller::shutDown() +{ + hScrollBar = 0; + vScrollBar = 0; + TView::shutDown(); +} + +void TScroller::changeBounds( const TRect& bounds ) +{ + setBounds(bounds); + drawLock++; + setLimit(limit.x, limit.y); + drawLock--; + drawFlag = False; + drawView(); +} + +void TScroller::checkDraw() +{ + if( drawLock == 0 && drawFlag != False ) + { + drawFlag = False; + drawView(); + } +} + +TPalette& TScroller::getPalette() const +{ + static TPalette palette( cpScroller, sizeof( cpScroller )-1 ); + return palette; +} + +void TScroller::handleEvent(TEvent& event) +{ + TView::handleEvent(event); + + if( event.what == evBroadcast && + event.message.command == cmScrollBarChanged && + ( event.message.infoPtr == hScrollBar || + event.message.infoPtr == vScrollBar ) + ) + scrollDraw(); + else + if( vScrollBar && event.what == evMouseDown) + { + if( event.mouse.buttons==mbButton4 ) + { + vScrollBar->setValue( vScrollBar->value - wheelStep ); + clearEvent( event ); + } + else if( event.mouse.buttons==mbButton5 ) + { + vScrollBar->setValue( vScrollBar->value + wheelStep ); + clearEvent( event ); + } + } +} + +void TScroller::scrollDraw() +{ + TPoint d; + + if( hScrollBar != 0 ) + d.x = hScrollBar->value; + else + d.x = 0; + + if( vScrollBar != 0 ) + d.y = vScrollBar->value; + else + d.y = 0; + + if( d.x != delta.x || d.y != delta.y ) + { + setCursor( cursor.x + delta.x - d.x, cursor.y + delta.y - d.y ); + delta = d; + if( drawLock != 0 ) + drawFlag = True; + else + drawView(); + } +} + +void TScroller::scrollTo( int32 x, int32 y ) +{ + drawLock++; + if( hScrollBar != 0 ) + hScrollBar->setValue(x); + if( vScrollBar != 0 ) + vScrollBar->setValue(y); + drawLock--; + checkDraw(); +} + +void TScroller::setLimit( int32 x, int32 y ) +{ + limit.x = x; + limit.y = y; + drawLock++; + if( hScrollBar != 0 ) + hScrollBar->setParams( hScrollBar->value, + 0, + x - size.x, + size.x, + 1 + ); + if( vScrollBar != 0 ) + vScrollBar->setParams( vScrollBar->value, + 0, + y - size.y, + size.y, + 1 + ); + drawLock--; + checkDraw(); +} + +void TScroller::showSBar( TScrollBar *sBar ) +{ + if( sBar != 0 ) + { + if( getState(sfActive | sfSelected) != 0 ) + sBar->show(); + else + sBar->hide(); + } +} + +void TScroller::setState( ushort aState, Boolean enable ) +{ + TView::setState(aState, enable); + if( (aState & (sfActive | sfSelected)) != 0 ) + { + showSBar(hScrollBar); + showSBar(vScrollBar); + } +} + +#if !defined( NO_STREAM ) +void TScroller::write( opstream& os ) +{ + TView::write( os ); + os << hScrollBar << vScrollBar << delta << limit; +} + +void *TScroller::read( ipstream& is ) +{ + TView::read( is ); + is >> hScrollBar >> vScrollBar >> delta >> limit; + drawLock = 0; + drawFlag = False; + wheelStep= defaultWheelStep; + return this; +} + +TStreamable *TScroller::build() +{ + return new TScroller( streamableInit ); +} + +TScroller::TScroller( StreamableInit ) : TView( streamableInit ) +{ +} +#endif // NO_STREAM + diff --git a/tvision/classes/tsortedc.cc b/tvision/classes/tsortedc.cc new file mode 100644 index 0000000..a7a2f0e --- /dev/null +++ b/tvision/classes/tsortedc.cc @@ -0,0 +1,40 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#define Uses_opstream +#define Uses_ipstream +#define Uses_TSortedCollection +#include + +#if !defined( NO_STREAM ) +void TSortedCollection::write( opstream& os ) +{ + TCollection::write( os ); + os << (int)duplicates; +} + +void *TSortedCollection::read( ipstream& is ) +{ + TCollection::read( is ); + int temp; + is >> temp; + duplicates = Boolean(temp); + return this; +} + +TSortedCollection::TSortedCollection( StreamableInit ) : + TCollection( streamableInit ) +{ +} +#endif // NO_STREAM + diff --git a/tvision/classes/tsortedl.cc b/tvision/classes/tsortedl.cc new file mode 100644 index 0000000..4c1e60c --- /dev/null +++ b/tvision/classes/tsortedl.cc @@ -0,0 +1,188 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Salvador E. Tropea to add functionality. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_ctype +#define Uses_limits +#define Uses_string +#define Uses_TKeys +#define Uses_TEvent +#define Uses_TSortedListBox +#define Uses_TSortedCollection +#include + +#if 0 + extern unsigned short getshiftstate(void); + #define shiftKeys (char)(getshiftstate() & 0xff) +#else + #define shiftKeys (char)(event.keyDown.shiftState & 0xFF) +#endif + +TSortedListBox::TSortedListBox( const TRect& bounds, + ushort aNumCols, + TScrollBar *aScrollBar) : + TListBox(bounds, aNumCols, aScrollBar), + shiftState( 0 ), + searchPos( USHRT_MAX ) +{ + showCursor(); + setCursor(1, 0); +} + +// SET: +TSortedListBox::TSortedListBox( const TRect& bounds, + ushort aNumCols, + TScrollBar *aHScrollBar, + TScrollBar *aVScrollBar, + Boolean aCenterOps) : + TListBox(bounds, aNumCols, aHScrollBar, aVScrollBar, aCenterOps), + shiftState( 0 ), + searchPos( USHRT_MAX ) +{ + showCursor(); + setCursor(1, 0); +} + +static Boolean TVision_equal( const char *s1, const char *s2, ushort count) +{ + return Boolean( strncasecmp( s1, s2, count ) == 0 ); +} + +void TSortedListBox::handleEvent(TEvent& event) +{ + char curString[256], newString[256]; + void* k; + int value, oldPos, oldValue; + + oldValue = focused; + TListBox::handleEvent( event ); + if( oldValue != focused ) + searchPos = USHRT_MAX; + if (event.what == evBroadcast && + event.message.command == cmListItemSelected && + event.message.infoPtr == list()) + { + /* When the item was selected, reset the search feature */ + searchPos = USHRT_MAX; + clearEvent(event); + return; + } + if( event.what == evKeyDown ) + { + if( event.keyDown.keyCode != kbEnter && + ( event.keyDown.charScan.charCode != 0 || + event.keyDown.keyCode == kbBack ) ) + { + value = focused; + if( value < range ) + getText( curString, value, 255 ); + else + *curString = EOS; + oldPos = searchPos; + if( event.keyDown.keyCode == kbBack ) + { + if( searchPos == USHRT_MAX ) + return; + // SET: 1) Avoid accessing curString[USHRT_MAX], 2) Do in the right order + curString[searchPos--] = EOS; + if( searchPos == USHRT_MAX ) + shiftState = shiftKeys; + } + else if( (event.keyDown.charScan.charCode == '.') ) + { + char *loc = strchr( curString+ + (searchPos==USHRT_MAX ? 0 : searchPos), '.' ); + if( loc ) + { + searchPos = ushort(loc - curString); + if (oldPos == USHRT_MAX) + oldPos = 0; + } + else + { + if (searchPos == USHRT_MAX) + { + searchPos++; + curString[searchPos] = '.'; + curString[searchPos+1] = EOS; + oldPos = 0; + } + } + } + else + { + searchPos++; + if( searchPos == 0 ) + { + shiftState = shiftKeys; + oldPos = 0; + } + curString[searchPos] = event.keyDown.charScan.charCode; + curString[searchPos+1] = EOS; + } + k = getKey(curString); + list()->search( k, value ); + if( value < range ) + { + getText( newString, value, 255 ); + if( TVision_equal( curString, newString, searchPos+1 ) ) + { + if( value != oldValue ) + { + focusItem(value); + setCursor( cursor.x+searchPos, cursor.y ); + } + else + setCursor(cursor.x+(searchPos-oldPos), cursor.y ); + } + else + searchPos = oldPos; + } + else + searchPos = oldPos; + if( searchPos != oldPos || + ucisalpha( event.keyDown.charScan.charCode ) + ) + clearEvent(event); + } + } +} + +void* TSortedListBox::getKey( const char *s ) +{ + return (void *)s; +} + +void TSortedListBox::newList( TSortedCollection *aList ) +{ + TListBox::newList( aList ); + searchPos = USHRT_MAX; +} + +TStreamable *TSortedListBox::build() +{ + return new TSortedListBox( streamableInit ); +} + +void *TSortedListBox::read( ipstream& is ) +{ + TListBox::read(is); + + // Must initialize these or serious memory overwrite + // problems can occur! + searchPos = (ushort)-1; + shiftState = 0; + + return this; +} diff --git a/tvision/classes/tstatict.cc b/tvision/classes/tstatict.cc new file mode 100644 index 0000000..5b78906 --- /dev/null +++ b/tvision/classes/tstatict.cc @@ -0,0 +1,159 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Vadim Beloborodov to be used on WIN32 console +Modified by Salvador E. Tropea: added i18n support. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#include +#define Uses_string +#define Uses_AllocLocal +#define Uses_TStaticText +#define Uses_TDrawBuffer +#define Uses_opstream +#define Uses_ipstream +#define Uses_TPalette +#include + +#define cpStaticText "\x06" + +TStaticText::TStaticText( const TRect& bounds, const char *aText ) : + TView( bounds ), + text( newStr( aText ) ), + intlText( NULL ), + noIntl( 0 ) +{ +} + +TStaticText::TStaticText( const TRect& bounds, const char *aText, + stTVIntl *aIntlText ) : + TView( bounds ), + text( newStr( aText ) ), + intlText( aIntlText ), + noIntl( 0 ) +{ +} + +TStaticText::~TStaticText() +{ + DeleteArray((char *)text); + TVIntl::freeSt( intlText ); +} + +void TStaticText::draw() +{ + uchar color; + Boolean center; + int i, j, l, p, y; + TDrawBuffer b; + int maxLen = size.x*size.y; + AllocLocalStr(s,maxLen+1); + + color = getColor(1); + getText(s, maxLen); + l = strlen(s); + p = 0; + y = 0; + center = False; + while (y < size.y) + { + b.moveChar(0, ' ', color, size.x); + if (p < l) + { + if (s[p] == 3) + { + center = True; + ++p; + } + i = p; + do { + j = p; + while ((p < l) && (s[p] == ' ')) + ++p; + while ((p < l) && (s[p] != ' ') && (s[p] != '\n')) + ++p; + } while ((p < l) && (p < i + size.x) && (s[p] != '\n')); + if (p > i + size.x) + { + if (j > i) + p = j; + else + p = i + size.x; + } + if (center == True) + j = (size.x - p + i) / 2 ; + else + j = 0; + b.moveBuf(j, &s[i], color, (p - i)); + while ((p < l) && (s[p] == ' ')) + p++; + if ((p < l) && (s[p] == '\n')) + { + center = False; + p++; + if ((p < l) && (s[p] == 10)) + p++; + } + } + writeLine(0, y++, size.x, 1, b); + } +} + +TPalette& TStaticText::getPalette() const +{ + static TPalette palette( cpStaticText, sizeof( cpStaticText )-1 ); + return palette; +} + +const char *TStaticText::getText() +{ + return noIntl ? text : TVIntl::getText( text, intlText ); +} + +void TStaticText::getText( char *s, int maxLen ) +{ + if( text == 0 ) + *s = EOS; + else + { + const char *iText = getText(); + strncpy( s, iText, maxLen ); + s[maxLen] = 0; + } +} + +#if !defined( NO_STREAM ) +void TStaticText::write( opstream& os ) +{ + TView::write( os ); + os.writeString( text ); +} + +void *TStaticText::read( ipstream& is ) +{ + TView::read( is ); + text = is.readString(); + intlText = NULL; + return this; +} + +TStreamable *TStaticText::build() +{ + return new TStaticText( streamableInit ); +} + +TStaticText::TStaticText( StreamableInit ) : TView( streamableInit ) +{ +} +#endif // NO_STREAM + + diff --git a/tvision/classes/tstatusd.cc b/tvision/classes/tstatusd.cc new file mode 100644 index 0000000..9377b6e --- /dev/null +++ b/tvision/classes/tstatusd.cc @@ -0,0 +1,43 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#define Uses_TStatusDef +#define Uses_TStatusItem +#include + +CLY_EXPORT TStatusDef& operator + ( TStatusDef& s1, TStatusItem& s2 ) +{ + TStatusDef *def = &s1; + while( def->next != 0 ) + def = def->next; + if( def->items == 0 ) + def->items = &s2; + else + { + TStatusItem *cur = def->items; + while( cur->next != 0 ) + cur = cur->next; + cur->next = &s2; + } + return s1; +} + +CLY_EXPORT TStatusDef& operator + ( TStatusDef& s1, TStatusDef& s2 ) +{ + TStatusDef *cur = &s1; + while( cur->next != 0 ) + cur = cur->next; + cur->next = &s2; + return s1; +} + diff --git a/tvision/classes/tstatusl.cc b/tvision/classes/tstatusl.cc new file mode 100644 index 0000000..9c542fb --- /dev/null +++ b/tvision/classes/tstatusl.cc @@ -0,0 +1,371 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_string + +#define Uses_TStatusLine +#define Uses_TStatusItem +#define Uses_TStatusDef +#define Uses_TDrawBuffer +#define Uses_TEvent +#define Uses_opstream +#define Uses_ipstream +#define Uses_TPalette +#define Uses_TKeys +#include + +#define cpStatusLine "\x02\x03\x04\x05\x06\x07" + +TStatusLine::TStatusLine( const TRect& bounds, TStatusDef& aDefs ) : + TView( bounds ), + defs( &aDefs ) +{ + options |= ofPreProcess; + eventMask |= evBroadcast; + growMode = gfGrowLoY | gfGrowHiX | gfGrowHiY; + findItems(); + computeLength(); +} + +/**[txh]******************************************************************** + + Description: + This routine computes the length of the status line, if that's greater than +the size.x the status line becomes compacted to allow more options.@* + Added by SET. + +***************************************************************************/ + +void TStatusLine::computeLength() +{ + int l = 0; + TStatusItem *p; + + if( items != 0 ) + { + p = items; + while( p != 0 ) + { + if( p->text != 0 ) + l += cstrlen(TVIntl::getText(p->text,p->intlText)) + 2; + p = p->next; + } + } + compactStatus = l > size.x; +} + +/**[txh]******************************************************************** + + Description: + Calls TView::changeBounds, additionally re-computes the length of the +line to select the no/compact mode.@* + Added by SET. + +***************************************************************************/ + +void TStatusLine::changeBounds(const TRect& bounds) +{ + TView::changeBounds(bounds); + int oldCompact=compactStatus; + computeLength(); + if (compactStatus!=oldCompact) + draw(); +} + +void TStatusLine::disposeItems( TStatusItem *item ) +{ + while( item != 0 ) + { + TStatusItem *T = item; + item = item->next; + delete(T); + } +} + +TStatusLine::~TStatusLine(void) +{ + while( defs != 0 ) + { + TStatusDef *T = defs; + defs = defs->next; + disposeItems( T->items ); + delete(T); + } +} + +void TStatusLine::draw() +{ + drawSelect( 0 ); +} + +void TStatusLine::drawSelect( TStatusItem *selected ) +{ + TDrawBuffer b; + ushort color; + char hintBuf[256]; + + ushort cNormal = getColor(0x0301); + ushort cSelect = getColor(0x0604); + ushort cNormDisabled = getColor(0x0202); + ushort cSelDisabled = getColor(0x0505); + b.moveChar( 0, ' ', cNormal, size.x ); + TStatusItem *T = items; + int i = 0, inc = (compactStatus ? 1 : 2); // SET + + while( T != 0 ) + { + if( T->text != 0 ) + { + int l = cstrlen( TVIntl::getText(T->text,T->intlText) ); + if( i + l < size.x ) + { + if( commandEnabled( T->command) ) + if( T == selected ) + color = cSelect; + else + color = cNormal; + else + if( T == selected ) + color = cSelDisabled; + else + color = cNormDisabled; + + b.moveChar( i, ' ', color, 1 ); + b.moveCStr( i+1, TVIntl::getText(T->text,T->intlText), color ); + b.moveChar( i+l+1, ' ', color, 1 ); + } + i += l + inc; + } + T = T->next; + } + if (size.y == 1) + { + if( i < size.x - 2 ) + { + strcpy( hintBuf, hint( helpCtx ) ); + if( *hintBuf != EOS ) + { + b.moveStr( i, hintSeparator, cNormal ); + i += 2; + if( (int32)strlen(hintBuf) + i > size.x ) + hintBuf[size.x-i] = EOS; + b.moveCStr( i, hintBuf, cNormal ); + } + } + writeLine( 0, 0, size.x, 1, b ); + } + else + { + writeLine( 0, 0, size.x, 1, b ); + strcpy( hintBuf, hint( helpCtx ) ); + hintBuf[size.x] = 0; + b.moveChar(0, ' ', cNormal, size.x); + b.moveCStr(0, hintBuf, cNormal); + writeLine( 0, 1, size.x, 1, b ); + } +} + +void TStatusLine::findItems() +{ + TStatusDef *p = defs; + while( p != 0 && ( helpCtx < p->min || helpCtx > p->max ) ) + p = p->next; + items = ( p == 0 ) ? 0 : p->items; +} + +TPalette& TStatusLine::getPalette() const +{ + static TPalette palette( cpStatusLine, sizeof( cpStatusLine )-1 ); + return palette; +} + +TStatusItem *TStatusLine::itemMouseIsIn( TPoint mouse ) +{ + if( mouse.y != 0 ) + return 0; + + int i, inc = (compactStatus ? 1 : 2); // SET + TStatusItem *T; + + for( i = 0, T = items; T != 0; T = T->next) + { + if( T->text != 0 ) + { + int k = i + cstrlen(TVIntl::getText(T->text,T->intlText)) + inc; + if( mouse.x >= i && mouse. x < k ) + return T; + i = k; + } + } + return 0; +} + +void TStatusLine::handleEvent( TEvent& event ) +{ + TView::handleEvent(event); + + switch (event.what) + { + case evMouseDown: + { + TStatusItem *T = 0; + + do { + TPoint mouse = makeLocal( event.mouse.where ); + if( T != itemMouseIsIn(mouse) ) + drawSelect( T = itemMouseIsIn(mouse) ); + } while( mouseEvent( event, evMouseMove ) ); + + if( T != 0 && commandEnabled(T->command) ) + { + event.what = evCommand; + event.message.command = T->command; + event.message.infoPtr = 0; + putEvent(event); + } + clearEvent(event); + drawView(); + break; + } + case evKeyDown: + { + for( TStatusItem *T = items; T != 0; T = T->next ) + { + if( T->keyCode != kbNoKey && + event.keyDown.keyCode == T->keyCode && + commandEnabled(T->command)) + { + event.what = evCommand; + event.message.command = T->command; + event.message.infoPtr = 0; + return; + } + } + break; + } + case evBroadcast: + if( event.message.command == cmCommandSetChanged ) + drawView(); + break; + } +} + +const char* TStatusLine::hint( ushort ) +{ + return ""; +} + +void TStatusLine::update() +{ + TView *p = TopView(); + ushort h = ( p != 0 ) ? p->getHelpCtx() : hcNoContext; + if( helpCtx != h ) + { + helpCtx = h; + findItems(); + drawView(); + } +} + +#if !defined( NO_STREAM ) +void TStatusLine::writeItems( opstream& os, TStatusItem *ts ) +{ + int count = 0; + for( TStatusItem *t = ts; t != 0; t = t->next ) + count++; + os << count; + for( ; ts != 0; ts = ts->next ) + { + os.writeString( ts->text ); + os << ts->keyCode << ts->command; + } +} + +void TStatusLine::writeDefs( opstream& os, TStatusDef *td ) +{ + int count = 0; + for( TStatusDef *t = td; t != 0; t = t->next ) + count++; + os << count; + for( ; td != 0; td = td->next ) + { + os << td->min << td->max; + writeItems( os, td->items ); + } +} + +void TStatusLine::write( opstream& os ) +{ + TView::write( os ); + writeDefs( os, defs ); +} + +TStatusItem *TStatusLine::readItems( ipstream& is ) +{ + TStatusItem *cur = 0; + TStatusItem *first; + TStatusItem **last = &first; + int count; + is >> count; + while( count-- > 0 ) + { + const char *t = is.readString(); + ushort key, cmd; + is >> key >> cmd; + cur = new TStatusItem( t, key, cmd ); + *last = cur; + last = &(cur->next); + } + *last = 0; + return first; +} + +TStatusDef *TStatusLine::readDefs( ipstream& is ) +{ + TStatusDef *cur = 0; + TStatusDef *first; + TStatusDef **last = &first; + int count; + is >> count; + while( count-- > 0 ) + { + ushort min, max; + is >> min >> max; + cur = new TStatusDef( min, max, readItems( is ) ); + *last = cur; + last = &(cur->next); + } + *last = 0; + return first; +} + +void *TStatusLine::read( ipstream& is ) +{ + TView::read( is ); + defs = readDefs( is ); + findItems(); + return this; +} + +TStreamable *TStatusLine::build() +{ + return new TStatusLine( streamableInit ); +} + +TStatusLine::TStatusLine( StreamableInit ) : TView( streamableInit ) +{ +} +#endif // NO_STREAM + + diff --git a/tvision/classes/tstrinde.cc b/tvision/classes/tstrinde.cc new file mode 100644 index 0000000..228da84 --- /dev/null +++ b/tvision/classes/tstrinde.cc @@ -0,0 +1,21 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#define Uses_TStrIndexRec +#include + +TStrIndexRec::TStrIndexRec() : + count(0) +{ +} + diff --git a/tvision/classes/tstringc.cc b/tvision/classes/tstringc.cc new file mode 100644 index 0000000..4feb0a1 --- /dev/null +++ b/tvision/classes/tstringc.cc @@ -0,0 +1,65 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_string + +#define Uses_TStringCollection +#define Uses_opstream +#define Uses_ipstream +#include + +TStringCollection::TStringCollection( ccIndex aLimit, ccIndex aDelta ) : + TSortedCollection(aLimit, aDelta) +{ +} + +int TStringCollection::compare( void *key1, void *key2 ) +{ + return strcmp( (char *)key1, (char *)key2 ); +} + +void TStringCollection::freeItem( void* item ) +{ + delete[] (char *)item; +} + +#if !defined( NO_STREAM ) +TStreamable *TStringCollection::build() +{ + return new TStringCollection( streamableInit ); +} + +void TStringCollection::writeItem( void *obj, opstream& os ) +{ + os.writeString( (const char *)obj ); +} + +void *TStringCollection::readItem( ipstream& is ) +{ + return is.readString(); +} +#endif // NO_STREAM + +TStringCollection & TStringCollection::operator = (const TStringCollection & pl) +{ + int i; + duplicates = pl.duplicates; + freeAll(); + for (i=0;i + +TStringList::~TStringList() +{ + int i; + for (i=indexSize;i>0;i--) delete (index+(i-1)); +/* + delete [indexSize] index; +*/ +} + + +void TStringList::get( char *dest, ushort key ) +{ + if( indexSize == 0 ) + { + *dest = EOS; + return; + } + + TStrIndexRec *cur = index; + while ((cur->key + cur->count - 1 < key) && (cur - index < indexSize)) + cur++; + if ((cur->key + cur->count - 1 < key) || (cur->key > key)) + { + *dest = EOS; + return; + } + + ip->seekg( basePos + cur->offset ); + int count = key - cur->key; + do { + uchar sz = ip->readByte(); + ip->readBytes( dest, sz ); + dest[sz] = EOS; + } while( count-- > 0 ); +} + +#if !defined( NO_STREAM ) +void *TStringList::read( ipstream& is ) +{ + ip = &is; + + ushort strSize; + is >> strSize; + + basePos = is.tellg(); + is.seekg( basePos + strSize ); + is >> indexSize; + index = new TStrIndexRec[indexSize]; + is.readBytes( index, indexSize * sizeof( TStrIndexRec ) ); + return this; +} + +TStringList::TStringList( StreamableInit ) +{ + basePos=0; + indexSize=0; + index=0; +} + +TStreamable *TStringList::build() +{ + return new TStringList( streamableInit ); +} +#endif // NO_STREAM + diff --git a/tvision/classes/tstrlist.cc b/tvision/classes/tstrlist.cc new file mode 100644 index 0000000..97bdb7f --- /dev/null +++ b/tvision/classes/tstrlist.cc @@ -0,0 +1,76 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_string + +#define Uses_TStrIndexRec +#define Uses_TStrListMaker +#define Uses_TStringList +#define Uses_opstream +#include + +TStrListMaker::TStrListMaker( ushort aStrSize, ushort aIndexSize ) +{ + strPos=0; + strSize=0; + strings=new char[aStrSize]; + indexPos=0; + indexSize=aIndexSize; + index=new TStrIndexRec[aIndexSize]; +} + + +TStrListMaker::~TStrListMaker() +{ + delete strings; + delete[] index; +} + + +void TStrListMaker::closeCurrent() +{ + if( cur.count != 0 ) + { + index[indexPos++] = cur; + cur.count = 0; + } +} + +void TStrListMaker::put( ushort key, char *str ) +{ + if( cur.count == MAXKEYS || key != cur.key + cur.count ) + closeCurrent(); + if( cur.count == 0 ) + { + cur.key = key; + cur.offset = strPos; + } + int len = strlen( str ); + strings[strPos] = len; + memmove( strings+strPos+1, str, len ); + strPos += len+1; + cur.count++; +} + +#if !defined( NO_STREAM ) +void TStrListMaker::write( opstream& os ) +{ + closeCurrent(); + os << strPos; + os.writeBytes( strings, strPos ); + os << indexPos; + os.writeBytes( index, indexPos * sizeof( TStrIndexRec ) ); +} +#endif // NO_STREAM + diff --git a/tvision/classes/tstrmcla.cc b/tvision/classes/tstrmcla.cc new file mode 100644 index 0000000..f70e6ef --- /dev/null +++ b/tvision/classes/tstrmcla.cc @@ -0,0 +1,26 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#define Uses_TStreamableClass +#define Uses_pstream +#include + +TStreamableClass::TStreamableClass( const char *n, BUILDER b, int d ) : + name( n ), + build( b ), + delta( d ) +{ + pstream::initTypes(); + pstream::registerType( this ); +} + diff --git a/tvision/classes/tstrmtyp.cc b/tvision/classes/tstrmtyp.cc new file mode 100644 index 0000000..3ec7e38 --- /dev/null +++ b/tvision/classes/tstrmtyp.cc @@ -0,0 +1,62 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_string + +#define Uses_TStreamableClass +#define Uses_TStreamableTypes +#include + +TStreamableTypes::TStreamableTypes() : TNSSortedCollection( 5, 5 ) +{ +} + +// Avoid replacing new by MSS's macro +#include + +void *TStreamableTypes::operator new( size_t, void * arena ) +{ + return arena; +} + +#include + +TStreamableTypes::~TStreamableTypes() +{ +} + +void TStreamableTypes::registerType( const TStreamableClass *d ) +{ + insert( (void *)d ); +} + +const TStreamableClass *TStreamableTypes::lookup( const char *name ) +{ + ccIndex loc; + if( search( (void *)name, loc ) ) + return (TStreamableClass *)at( loc ); + else + return 0; +} + +void *TStreamableTypes::keyOf( void *d ) +{ + return (void *)((TStreamableClass *)d)->name; +} + +int TStreamableTypes::compare( void *d1, void *d2 ) +{ + return strcmp( (char *)d1, (char *)d2 ); +} + diff --git a/tvision/classes/tsubmenu.cc b/tvision/classes/tsubmenu.cc new file mode 100644 index 0000000..8b241fb --- /dev/null +++ b/tvision/classes/tsubmenu.cc @@ -0,0 +1,50 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#define Uses_TSubMenu +#define Uses_TMenuItem +#define Uses_TMenu +#include + +TSubMenu::TSubMenu( const char *nm, ushort key, ushort helpCtx ) : + TMenuItem( nm, 0, key, helpCtx ) +{ +} + +CLY_EXPORT TSubMenu& operator + ( TSubMenu& s, TMenuItem& i ) +{ + TSubMenu *sub = &s; + while( sub->next != 0 ) + sub = (TSubMenu *)(sub->next); + + if( sub->subMenu == 0 ) + sub->subMenu = new TMenu( i ); + else + { + TMenuItem *cur = sub->subMenu->items; + while( cur->next != 0 ) + cur = cur->next; + cur->next = &i; + } + return s; +} + +CLY_EXPORT TSubMenu& operator + ( TSubMenu& s1, TSubMenu& s2 ) +{ + TMenuItem *cur = &s1; + while( cur->next != 0 ) + cur = cur->next; + cur->next = &s2; + return s1; +} + diff --git a/tvision/classes/ttermina.cc b/tvision/classes/ttermina.cc new file mode 100644 index 0000000..ab2f0b6 --- /dev/null +++ b/tvision/classes/ttermina.cc @@ -0,0 +1,242 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified to compile with gcc v3.x by Salvador E. Tropea, with the help of +Andris Pavenis. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#include + +#define Uses_string + +#define Uses_TTextDevice +#define Uses_TTerminal +#define Uses_otstream +#include + +UsingNamespaceStd + +TTerminal::TTerminal( const TRect& bounds, + TScrollBar *aHScrollBar, + TScrollBar *aVScrollBar, + uint32 aBufSize ) : + TTextDevice(bounds, aHScrollBar, aVScrollBar), + queFront( 0 ), + queBack( 0 ) +{ + growMode = gfGrowHiX + gfGrowHiY; + bufSize = aBufSize; + buffer = new char[ bufSize ]; + setLimit( 0, 1 ); + setCursor( 0, 0 ); + showCursor(); +} + + +TTerminal::~TTerminal() +{ + delete buffer; +} + +Boolean TTerminal::canInsert( uint32 amount ) +{ + int32 T = (queFront < queBack) ? + ( queFront + amount ) : + ( int32(queFront) - bufSize + amount); // cast needed so we get + // signed comparison + return Boolean( (int32)queBack > T ); +} + +const int MaxLineLen=256; + +void TTerminal::draw() +{ + short i; + uint32 begLine, endLine; + char s[MaxLineLen]; + int32 bottomLine; + + bottomLine = size.y + delta.y; + if( limit.y > bottomLine ) + { + endLine = prevLines( queFront, limit.y - bottomLine ); + bufDec( endLine ); + } + else + endLine = queFront; + + if( limit.y > size.y ) + i = size.y - 1; + else + { + for( i = limit.y; i <= size.y - 1; i++ ) + writeChar(0, i, ' ', 1, size.x); + i = limit.y - 1; + } + + for( ; i >= 0; i-- ) + { + begLine = prevLines(endLine, 1); + if (endLine >= begLine) + { + int T = int( endLine - begLine ); + if (T>=MaxLineLen) + T=MaxLineLen-1; + memcpy( s, &buffer[begLine], T ); + s[T] = EOS; + } + else + { + int T=int( bufSize - begLine); + if (T>=MaxLineLen) + T=MaxLineLen-1; + memcpy( s, &buffer[begLine], T ); + int T2=endLine; + if (T+T2>=MaxLineLen) + T2=MaxLineLen-T-1; + memcpy( s+T, buffer, T2 ); + s[T+T2] = EOS; + } + if( delta.x >= (int32)strlen(s) ) + *s = EOS; + else + strcpy( s, &s[delta.x] ); + + writeStr( 0, i, s, 1 ); + writeChar( strlen(s), i, ' ', 1, size.x ); + endLine = begLine; + bufDec( endLine ); + } +} + +uint32 TTerminal::nextLine( uint32 pos ) +{ + if( pos != queFront ) + { + while( buffer[pos] != '\n' && pos != queFront ) + bufInc(pos); + if( pos != queFront ) + bufInc( pos ); + } + return pos; +} + +int TTerminal::do_sputn( const char *s, int count ) +{ + ushort screenLines = limit.y; + int32 i; + for( i = 0; i < count; i++ ) + if( s[i] == '\n' ) + screenLines++; + + while( !canInsert( count ) ) + { + queBack = nextLine( queBack ); + screenLines--; + } + + if( queFront + count >= bufSize ) + { + i = bufSize - queFront; + memcpy( &buffer[queFront], s, i ); + memcpy( buffer, &s[i], count - i ); + queFront = count - i; + } + else + { + memcpy( &buffer[queFront], s, count ); + queFront += count; + } + + setLimit( limit.x, screenLines ); + scrollTo( 0, screenLines + 1 ); + i = prevLines( queFront, 1 ); + if( i <= (int32)queFront ) + i = queFront - i; + else + i = bufSize - (i - queFront); + setCursor( i, screenLines - delta.y - 1 ); + drawView(); + return count; +} + +Boolean TTerminal::queEmpty() +{ + return Boolean( queBack == queFront ); +} + +// The SSC code doesn't support as much as needed for it. +#ifndef HAVE_SSC +otstream::otstream( TTerminal *tt ) + #ifdef CLY_ISOCpp98 + // SET: Andris used it. It looks like the new standard doesn't have a + // default constructor + : std::ostream (tt) + #endif +{ + ios::init( tt ); +} +// HAVE_SSC +#endif + +// SET: It was really broken, but as we never used it... +// I rewrote it. I also used bufInc and bufDec and made it inline. (instead +// of the old macros). +uint32 TTerminal::prevLines(uint32 posStart, uint32 Lines) +{ + uint32 pos=posStart; + + // If that's the start just return, we can't go back. Remmember that's a + // circular buffer. + if (!Lines || pos==queBack) + return pos; + + // go back 1 character, is to skip the EOL + bufDec(pos); + + if (pos=queBack); + + return queBack; +} + diff --git a/tvision/classes/ttextdev.cc b/tvision/classes/ttextdev.cc new file mode 100644 index 0000000..1ed4c6c --- /dev/null +++ b/tvision/classes/ttextdev.cc @@ -0,0 +1,35 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#include + +#define Uses_TTextDevice +#include + +TTextDevice::TTextDevice( const TRect& bounds, + TScrollBar *aHScrollBar, + TScrollBar *aVScrollBar) : + TScroller(bounds,aHScrollBar,aVScrollBar) +{ +} + +int TTextDevice::overflow( int c ) +{ + if( c != EOF ) + { + char b = c; + do_sputn( &b, 1 ); + } + return 1; +} + diff --git a/tvision/classes/tvalidat.cc b/tvision/classes/tvalidat.cc new file mode 100644 index 0000000..670a014 --- /dev/null +++ b/tvision/classes/tvalidat.cc @@ -0,0 +1,77 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_string +#include +#include + +#define Uses_ipstream +#define Uses_opstream +#define Uses_TValidator +#include + +TValidator::TValidator() : status(0), options(0) +{ +} + +Boolean TValidator::isValid(const char *) +{ + return True; +} + +Boolean TValidator::isValidInput(char *,Boolean) +{ + return True; +} + +ushort TValidator::transfer(char *,void *,TVTransfer) +{ + return 0; +} + +Boolean TValidator::validate(const char *S) +{ + if (isValid(S)) + return True; + error(); + return False; +} + +// Not in TV 2.0 +void TValidator::format(char *) +{ +} + +void TValidator::error() +{ +} + +#if !defined( NO_STREAM ) +TValidator::TValidator(StreamableInit) +{ +} + +void TValidator::write(opstream & os) +{ + os << status << options; +} + +void * TValidator::read(ipstream & is) +{ + is >> status >> options; + // status=0 TV 2.0 + return this; +} +#endif // NO_STREAM + diff --git a/tvision/classes/tvedit1.cc b/tvision/classes/tvedit1.cc new file mode 100644 index 0000000..b3d1f28 --- /dev/null +++ b/tvision/classes/tvedit1.cc @@ -0,0 +1,180 @@ +/* Modified by Robert Hoehne and Salvador Eduardo Tropea for the gcc port */ +/* Modified by Vadim Beloborodov to be used on WIN32 console */ +/* Modified to compile with gcc v3.x by Salvador E. Tropea, with the help of + Andris Pavenis. */ +/*----------------------------------------------------------*/ +/* */ +/* Turbo Vision 1.0 */ +/* Copyright (c) 1991 by Borland International */ +/* */ +/* Turbo Vision TVEDIT source file */ +/*----------------------------------------------------------*/ + +#define Uses_stdarg +#define Uses_stdlib +#define Uses_string //strcpy() + +#define Uses_TApplication +#define Uses_TEditWindow +#define Uses_TDeskTop +#define Uses_TRect +#define Uses_TEditor +#define Uses_TFileEditor +#define Uses_TFileDialog +#define Uses_TChDirDialog +#define Uses_TEditorApp +#define Uses_TVEdMac +#define Uses_TVEdConstant +#define Uses_TScreen + +#include + +UsingNamespaceStd + +TEditWindow *clipWindow; + +TEditWindow *TEditorApp::openEditor( const char *fileName, Boolean visible ) +{ + TRect r = deskTop->getExtent();//TRect(0,0,80,6); + TView *p = validView( new TEditWindow( r, fileName, wnNoNumber ) ); + if( !visible ) + p->hide(); + deskTop->insert( p ); + return (TEditWindow *)p; +} + +TEditorApp::TEditorApp() : + TProgInit( TEditorApp::initStatusLine, + TEditorApp::initMenuBar, + TEditorApp::initDeskTop + ), + TApplication() +{ + + TCommandSet ts; + ts.enableCmd( cmSave ); + ts.enableCmd( cmSaveAs ); + ts.enableCmd( cmCut ); + ts.enableCmd( cmCopy ); + ts.enableCmd( cmPaste ); + ts.enableCmd( cmClear ); + ts.enableCmd( cmUndo ); + ts.enableCmd( cmFind ); + ts.enableCmd( cmReplace ); + ts.enableCmd( cmSearchAgain ); + disableCommands( ts ); + + TEditor::editorDialog = doEditDialog; + clipWindow = openEditor( 0, False ); + if( clipWindow != 0 ) + { + TEditor::clipboard = clipWindow->editor; + TEditor::clipboard->canUndo = False; + } +} + +void TEditorApp::fileOpen() +{ + char fileName[PATH_MAX]; + strcpy( fileName, "*" ); + + if( execDialog( new TFileDialog( "*", "Open file", + "~N~ame", fdOpenButton, 100 ), fileName) != cmCancel ) + openEditor( fileName, True ); +} + +void TEditorApp::fileNew() +{ + openEditor( 0, True ); +} + +void TEditorApp::changeDir() +{ + execDialog( new TChDirDialog( cdNormal, 0 ), 0 ); +} + +void TEditorApp::dosShell() +{ + if( TScreen::noUserScreen() ) + return; + suspend(); + TScreen::System(CLY_GetShellName()); + resume(); + redraw(); +} + +void TEditorApp::showClip() +{ + clipWindow->select(); + clipWindow->show(); +} + +void TEditorApp::tile() +{ + deskTop->tile( deskTop->getExtent() ); +} + +void TEditorApp::cascade() +{ + deskTop->cascade( deskTop->getExtent() ); +} + + + +void TEditorApp::handleEvent( TEvent& event ) +{ + TApplication::handleEvent( event ); + if( event.what != evCommand ) + return; + else + switch( event.message.command ) + { + case cmOpen: + if( event.message.infoPtr ) // JASC 2006, drag 'n' drop support + openEditor( (char *)event.message.infoPtr, True ); + else + fileOpen(); + break; + + case cmNew: + fileNew(); + break; + + case cmChangeDrct: + changeDir(); + break; + + case cmCallShell: + dosShell(); + break; + + case cmShowClip: + showClip(); + break; + + case cmTile: + tile(); + break; + + case cmCascade: + cascade(); + break; + + default: + return ; + } + clearEvent( event ); +} + +#ifdef TEST +int main(int argc, char *argv[]) +{ + TEditorApp *myApp=new TEditorApp(); + if (myApp) + { + myApp->run(); + delete myApp; + } + return 0; +} +#endif diff --git a/tvision/classes/tvedit2.cc b/tvision/classes/tvedit2.cc new file mode 100644 index 0000000..79cf679 --- /dev/null +++ b/tvision/classes/tvedit2.cc @@ -0,0 +1,111 @@ +/* Modified by Robert Hoehne and Salvador Eduardo Tropea for the gcc port */ +/* Modified to compile with gcc v3.x by Salvador E. Tropea, with the help of + Andris Pavenis. */ +/* Modified for i18n support by Salvador Eduardo Tropea. */ +/*----------------------------------------------------------*/ +/* */ +/* Turbo Vision 1.0 */ +/* Copyright (c) 1991 by Borland International */ +/* */ +/* Turbo Vision TVEDIT source file */ +/*----------------------------------------------------------*/ + +#define Uses_stdlib +#define Uses_stdarg + +#define Uses_TDialog +#define Uses_TDeskTop +#define Uses_TProgram +#define Uses_TApplication +#define Uses_TObject +#define Uses_TInputLine +#define Uses_T1Label +#define Uses_THistory +#define Uses_TRect +#define Uses_TCheckBoxes +#define Uses_TButton +#define Uses_MsgBox +#define Uses_TSItem +#define Uses_TEditor +#define Uses_TEditorApp + +#include + +ushort execDialog( TDialog *d, void *data ) +{ + // SET: set the data before checking if the dialog is valid. + // If we use validators that's very important. + if( d && data ) + d->setData( data ); + TView *p = TProgram::application->validView( d ); + if( p == 0 ) + return cmCancel; + else + { + ushort result = TProgram::deskTop->execView( p ); + if( result != cmCancel && data != 0 ) + p->getData( data ); + TObject::CLY_destroy( p ); + return result; + } +} + +TDialog *createFindDialog() +{ + TDialog *d = new TDialog( TRect( 0, 0, 38, 12 ), __("Find") ); + + d->options |= ofCentered; + + TInputLine *control = new TInputLine( TRect( 3, 3, 32, 4 ), 80 ); + d->insert( control ); + d->insert( + new T1Label( 2, 2, __("~T~ext to find"), control ) ); + d->insert( + new THistory( TRect( 32, 3, 35, 4 ), control, 10 ) ); + + d->insert( new TCheckBoxes( TRect( 3, 5, 35, 7 ), + new TSItem( __("~C~ase sensitive"), + new TSItem( __("~W~hole words only"), 0 )))); + + d->insert( + new TButton( TRect( 14, 9, 24, 11 ), __("O~K~"), cmOK, bfDefault ) ); + d->insert( + new TButton( TRect( 26, 9, 36, 11 ), __("Cancel"), cmCancel, bfNormal ) ); + + d->selectNext( False ); + return d; +} + +TDialog *createReplaceDialog() +{ + TDialog *d = new TDialog( TRect( 0, 0, 40, 16 ), __("Replace") ); + + d->options |= ofCentered; + + TInputLine *control = new TInputLine( TRect( 3, 3, 34, 4 ), 80 ); + d->insert( control ); + d->insert( + new T1Label( 2, 2, __("~T~ext to find"), control ) ); + d->insert( new THistory( TRect( 34, 3, 37, 4 ), control, 10 ) ); + + control = new TInputLine( TRect( 3, 6, 34, 7 ), 80 ); + d->insert( control ); + d->insert( new T1Label( 2, 5, __("~N~ew text"), control ) ); + d->insert( new THistory( TRect( 34, 6, 37, 7 ), control, 11 ) ); + + d->insert( new TCheckBoxes( TRect( 3, 8, 37, 12 ), + new TSItem(__("~C~ase sensitive"), + new TSItem(__("~W~hole words only"), + new TSItem(__("~P~rompt on replace"), + new TSItem(__("~R~eplace all"), 0 )))))); + + d->insert( + new TButton( TRect( 17, 13, 27, 15 ), __("O~K~"), cmOK, bfDefault ) ); + d->insert( new TButton( TRect( 28, 13, 38, 15 ), + __("Cancel"), cmCancel, bfNormal ) ); + + d->selectNext( False ); + + return d; +} + diff --git a/tvision/classes/tvedit3.cc b/tvision/classes/tvedit3.cc new file mode 100644 index 0000000..afe1397 --- /dev/null +++ b/tvision/classes/tvedit3.cc @@ -0,0 +1,208 @@ +/* Modified by Robert Hoehne and Salvador Eduardo Tropea for the gcc port */ +/* Modified by Vadim Beloborodov to be used on WIN32 console */ +/* Modified to compile with gcc v3.x by Salvador E. Tropea, with the help of + Andris Pavenis. */ +/* Modified by Salvador E. Tropea to use messageBox with formating. */ +/*----------------------------------------------------------*/ +/* */ +/* Turbo Vision 1.0 */ +/* Copyright (c) 1991 by Borland International */ +/* */ +/* Turbo Vision TVEDIT source file */ +/*----------------------------------------------------------*/ + +// SET: Internationalized, changed Alt- by Alt+ + +#define Uses_TApplication +#define Uses_TMenuBar +#define Uses_TRect +#define Uses_TSubMenu +#define Uses_TKeys +#define Uses_TMenuItem +#define Uses_TStatusLine +#define Uses_TStatusItem +#define Uses_TStatusDef +#define Uses_TPoint +#define Uses_TEditor +#define Uses_MsgBox +#define Uses_TFileDialog +#define Uses_TDeskTop +#define Uses_TEditorApp +#define Uses_TVEdConstant +#define Uses_stdarg + +#include + +TMenuBar *TEditorApp::initMenuBar( TRect r ) +{ + + TSubMenu& sub1 = *new TSubMenu( __("~F~ile"), kbAltF ) + + *new TMenuItem( __("~O~pen"), cmOpen, kbF3, hcNoContext, "F3" ) + + *new TMenuItem( __("~N~ew"), cmNew, kbNoKey ) + + *new TMenuItem( __("~S~ave"), cmSave, kbF2, hcNoContext, "F2" ) + + *new TMenuItem( __("S~a~ve as..."), cmSaveAs, kbNoKey ) + + newLine() + + *new TMenuItem( __("~C~hange dir..."), cmChangeDrct, kbNoKey ) + + *new TMenuItem( __("S~h~ell"), cmCallShell, kbNoKey ) + + *new TMenuItem( __("E~x~it"), cmQuit, kbAltX, hcNoContext, "Alt+X" ); + + TSubMenu& sub2 = *new TSubMenu( __("~E~dit"), kbAltE ) + + *new TMenuItem( __("~U~ndo"), cmUndo, kbNoKey ) + + newLine() + + *new TMenuItem( __("Cu~t~"), cmCut, kbShiftDel, hcNoContext, "Shift+Del" ) + + *new TMenuItem( __("~C~opy"), cmCopy, kbCtrlIns, hcNoContext, "Ctrl+Ins" ) + + *new TMenuItem( __("~P~aste"), cmPaste, kbShiftIns, hcNoContext, "Shift+Ins" ) + + *new TMenuItem( __("~S~how clipboard"), cmShowClip, kbNoKey ) + + newLine() + + *new TMenuItem( __("~C~lear"), cmClear, kbCtrlDel, hcNoContext, "Ctrl+Del" ); + + TSubMenu& sub3 = *new TSubMenu( __("~S~earch"), kbAltS ) + + *new TMenuItem( __("~F~ind..."), cmFind, kbNoKey ) + + *new TMenuItem( __("~R~eplace..."), cmReplace, kbNoKey ) + + *new TMenuItem( __("~S~earch again"), cmSearchAgain, kbNoKey ); + + TSubMenu& sub4 = *new TSubMenu( __("~W~indows"), kbAltW ) + + *new TMenuItem( __("~S~ize/move"),cmResize, kbCtrlF5, hcNoContext, "Ctrl+F5" ) + + *new TMenuItem( __("~Z~oom"), cmZoom, kbF5, hcNoContext, "F5" ) + + *new TMenuItem( __("~T~ile"), cmTile, kbNoKey ) + + *new TMenuItem( __("C~a~scade"), cmCascade, kbNoKey ) + + *new TMenuItem( __("~N~ext"), cmNext, kbF6, hcNoContext, "F6" ) + + *new TMenuItem( __("~P~revious"), cmPrev, kbShiftF6, hcNoContext, "Shift+F6" ) + + *new TMenuItem( __("~C~lose"), cmClose, kbAltF3, hcNoContext, "Alt+F3" ); + + /*TSubMenu& sub5 = *new TSubMenu( __("~O~ptions"), kbAltO ) + + *new TMenuItem( __("~M~acros"), cmMacros, kbNoKey );*/ + + r.b.y = r.a.y+1; + return new TMenuBar( r, sub1 + sub2 + sub3 + sub4 + //+ sub5 + ); +} + +TStatusLine *TEditorApp::initStatusLine( TRect r ) +{ + r.a.y = r.b.y-1; + return new TStatusLine( r, + *new TStatusDef( 0, 0xFFFF ) + + // SET: F10 before the others so when the library maintains the + // cursor visible this option is pointed and the user have a + // hint about what to do. + *new TStatusItem( __("~F10~ Menu"), kbF10, cmMenu ) + + *new TStatusItem( __("~F2~ Save"), kbF2, cmSave ) + + *new TStatusItem( __("~F3~ Open"), kbF3, cmOpen ) + + *new TStatusItem( __("~Alt+F3~ Close"), kbAltF3, cmClose ) + + *new TStatusItem( __("~F5~ Zoom"), kbF5, cmZoom ) + + *new TStatusItem( __("~F6~ Next"), kbF6, cmNext ) + + *new TStatusItem( 0, kbCtrlF5, cmResize ) + ); + +} + +void TEditorApp::outOfMemory() +{ + messageBox(__("Not enough memory for this operation."), mfError | mfOKButton ); +} + +typedef char *_charPtr; +typedef TPoint *PPoint; + +/**[txh]******************************************************************** + + Description: + This function provides the default dialog actions.@p + SET: I modified it to be easy to overwrite some actions. See the real +function. + +***************************************************************************/ + +ushort doEditDialogDefault( int dialog, va_list arg ) +{ + char *s; + switch( dialog ) + { + case edOutOfMemory: + return messageBox( __("Not enough memory for this operation."), + mfError | mfOKButton ); + case edReadError: + { + s=va_arg( arg, _charPtr ); + va_end(arg); + return messageBox( mfError | mfOKButton, + __("Error reading file %s."), s ); + } + case edWriteError: + { + s=va_arg( arg, _charPtr ); + va_end( arg ); + return messageBox( mfError | mfOKButton, + __("Error writing file %s."), s ); + } + case edCreateError: + { + s=va_arg( arg, _charPtr ); + va_end( arg ); + return messageBox( mfError | mfOKButton, + __("Error creating file %s."), s ); + } + case edSaveModify: + { + s=va_arg( arg, _charPtr ); + va_end( arg ); + return messageBox( mfInformation | mfYesNoCancel, + __("%s has been modified. Save?"), s ); + } + case edSaveUntitled: + return messageBox( __("Save untitled file?"), + mfInformation | mfYesNoCancel ); + case edSaveAs: + { + return execDialog( new TFileDialog( "*", + __("Save file as"), + __("~N~ame"), + fdOKButton, + 101 ), va_arg( arg, _charPtr ) ); + } + + case edFind: + { + return execDialog( createFindDialog(), va_arg( arg, _charPtr ) ); + } + + case edSearchFailed: + return messageBox( __("Search string not found."), + mfError | mfOKButton ); + case edReplace: + { + return execDialog( createReplaceDialog(), va_arg( arg, _charPtr ) ); + } + + case edReplacePrompt: + { + // Avoid placing the dialog on the same line as the cursor + TRect r( 0, 1, 40, 8 ); + r.move( (TProgram::deskTop->size.x-r.b.x)/2, 0 ); + TPoint t = TProgram::deskTop->makeGlobal( r.b ); + t.y++; + TPoint *pt = va_arg( arg, PPoint ); + if( pt->y <= t.y ) + r.move( 0, TProgram::deskTop->size.y - r.b.y - 2 ); + va_end( arg ); + return messageBoxRect( r, __("Replace this occurence?"), + mfYesNoCancel | mfInformation ); + } + default: + return cmCancel; + } +} + +ushort doEditDialog( int dialog, ... ) +{ // Just call the default + va_list arg; + + va_start(arg, dialog); + ushort ret=doEditDialogDefault(dialog,arg); + va_end(arg); + return ret; +} + + diff --git a/tvision/classes/tview.cc b/tvision/classes/tview.cc new file mode 100644 index 0000000..005ab44 --- /dev/null +++ b/tvision/classes/tview.cc @@ -0,0 +1,1249 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified by Vadim Beloborodov to be used on WIN32 console +Modified cursor behavior while desktop locked by Salvador E. Tropea (SET) + Rewrote call50() to support on the fly remapping and avoid using + setCharacter. + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_string +#define Uses_stdio +#define Uses_AllocLocal +#define Uses_TKeys +#define Uses_TKeys_Extended +#define Uses_TView +#define Uses_TCommandSet +#define Uses_TPoint +#define Uses_TGroup +#define Uses_TRect +#define Uses_TEvent +#define Uses_TEventQueue +#define Uses_TScreen +#define Uses_opstream +#define Uses_ipstream +#define Uses_TPalette +#define Uses_TVCodePage + +#include + +#include +#if 0 // def TVCompf_djgpp +#include +#include +#include +#include +#include +#endif + +TPoint shadowSize = {2,1}; +uchar shadowAttr = 0x08; +Boolean TView::showMarkers = False; +uchar TView::errorAttr = 0xCF; +Boolean TView::commandSetChanged = False; + +extern TView *TheTopView; + +static TCommandSet initCommands() +{ + TCommandSet temp; + temp.enableAllCommands(); + temp.disableCmd( cmZoom ); + temp.disableCmd( cmClose ); + temp.disableCmd( cmResize ); + temp.disableCmd( cmNext ); + temp.disableCmd( cmPrev ); + return temp; +} + +TCommandSet TView::curCommandSet = initCommands(); + +TView::TView( const TRect& bounds) : + next( 0 ), + options( 0 ), eventMask( evMouseDown | evKeyDown | evCommand ), + state( sfVisible ), + growMode( 0 ), dragMode( dmLimitLoY ), helpCtx( hcNoContext ), + owner( 0 ) +{ + setBounds( bounds); + cursor.x = cursor.y = 0; +} + +TView::~TView() +{ +} + +void TView::blockCursor() +{ + setState(sfCursorIns, True); +} + +#define grow(i) (( (growMode & gfGrowRel)) ? \ + (i = (i * s + ((s - d) >> 1)) / (s - d)) : (i += d)) + +inline int range( int val, int min, int max ) +{ + if( val < min ) + return min; + else if( val > max ) + return max; + else + return val; +} + +void TView::calcBounds( TRect& bounds, TPoint delta ) +{ + bounds = getBounds(); + + int s = owner->size.x; + int d = delta.x; + + if( (growMode & gfGrowLoX) != 0 ) + grow(bounds.a.x); + + if( (growMode & gfGrowHiX) != 0 ) + grow(bounds.b.x); + + s = owner->size.y; + d = delta.y; + + if( (growMode & gfGrowLoY) != 0 ) + grow(bounds.a.y); + + if( (growMode & gfGrowHiY) != 0 ) + grow(bounds.b.y); + + TPoint minLim, maxLim; + sizeLimits( minLim, maxLim ); + bounds.b.x = bounds.a.x + range( bounds.b.x-bounds.a.x, minLim.x, maxLim.x ); + bounds.b.y = bounds.a.y + range( bounds.b.y-bounds.a.y, minLim.y, maxLim.y ); +} + +void TView::changeBounds( const TRect& bounds ) +{ + setBounds(bounds); + drawView(); +} + +void TView::clearEvent( TEvent& event ) +{ + event.what = evNothing; + event.message.infoPtr = this; +} + +Boolean TView::commandEnabled( ushort command ) +{ + return Boolean(/* (command > 0x3FF) || // is now handled by + // curCommandSet.has(command) */ + curCommandSet.has(command)); +} + +uint32 TView::dataSize() +{ + return 0; +} + +void TView::disableCommands( TCommandSet& commands ) +{ + commandSetChanged = Boolean( commandSetChanged || + !(curCommandSet & commands).isEmpty()); + curCommandSet.disableCmd(commands); +} + +void TView::disableCommand( ushort command ) +{ + commandSetChanged = Boolean( commandSetChanged || + curCommandSet.has(command) ); + curCommandSet.disableCmd(command); +} + +void TView::moveGrow( TPoint p, + TPoint s, + TRect& limits, + TPoint minSize, + TPoint maxSize, + uchar mode + ) +{ + TRect r; + s.x = min(max(s.x, minSize.x), maxSize.x); + s.y = min(max(s.y, minSize.y), maxSize.y); + p.x = min(max(p.x, limits.a.x - s.x+1), limits.b.x-1); + p.y = min(max(p.y, limits.a.y - s.y+1), limits.b.y-1); + + if( (mode & dmLimitLoX) != 0 ) + p.x = max(p.x, limits.a.x); + if( (mode & dmLimitLoY) != 0 ) + p.y = max(p.y, limits.a.y); + if( (mode & dmLimitHiX) != 0 ) + p.x = min(p.x, limits.b.x-s.x); + if( (mode & dmLimitHiY) != 0 ) + p.y = min(p.y, limits.b.y-s.y); + r = TRect(p.x, p.y, p.x + s.x, p.y + s.y); + locate(r); +} + +// No longer needed, now passed as parameter "grow" +//extern unsigned short getshiftstate(void); + +void TView::change( uchar mode, TPoint delta, TPoint& p, TPoint& s, int grow ) +{ + if( (mode & dmDragMove) != 0 && !grow ) + p += delta; + else if( (mode & dmDragGrow) != 0 && grow ) + s += delta; +} + +void TView::dragView( TEvent& event, + uchar mode, + TRect& limits, + TPoint minSize, + TPoint maxSize + ) +{ + TRect saveBounds; + + TPoint p, s; + setState( sfDragging, True ); + + if( event.what == evMouseDown ) + { + if( (mode & dmDragMove) != 0 ) + { + p = origin - event.mouse.where; + do { + event.mouse.where += p; + moveGrow( event.mouse.where, + size, + limits, + minSize, + maxSize, + mode + ); + } while( mouseEvent(event,evMouseMove) ); + } + else + { + p = size - event.mouse.where; + do { + event.mouse.where += p; + moveGrow( origin, + event.mouse.where, + limits, + minSize, + maxSize, + mode + ); + } while( mouseEvent(event,evMouseMove) ); + } + } + else + { + static TPoint + goLeft = {-1, 0}, + goRight = { 1, 0}, + goUp = { 0,-1}, + goDown = { 0, 1}, + goCtrlLeft = {-8, 0}, + goCtrlRight = { 8, 0}; + + saveBounds = getBounds(); + do { + p = origin; + s = size; + keyEvent(event); + switch (event.keyDown.keyCode) + { + case kbLeft: + change(mode,goLeft,p,s); + break; + case kbRight: + change(mode,goRight,p,s); + break; + case kbUp: + change(mode,goUp,p,s); + break; + case kbDown: + change(mode,goDown,p,s); + break; + case kbCtLeft: + change(mode,goCtrlLeft,p,s); + break; + case kbCtRight: + change(mode,goCtrlRight,p,s); + break; + // Shift info goes in the key + case kbShLeft: + change(mode,goLeft,p,s,1); + break; + case kbShRight: + change(mode,goRight,p,s,1); + break; + case kbShUp: + change(mode,goUp,p,s,1); + break; + case kbShDown: + change(mode,goDown,p,s,1); + break; + case kbShCtLeft: + change(mode,goCtrlLeft,p,s,1); + break; + case kbShCtRight: + change(mode,goCtrlRight,p,s,1); + break; + case kbHome: + p.x = limits.a.x; + break; + case kbEnd: + p.x = limits.b.x - s.x; + break; + case kbPgUp: + p.y = limits.a.y; + break; + case kbPgDn: + p.y = limits.b.y - s.y; + break; + } + moveGrow( p, s, limits, minSize, maxSize, mode ); + } while( event.keyDown.keyCode != kbEsc && + event.keyDown.keyCode != kbEnter + ); + if( event.keyDown.keyCode == kbEsc ) + locate(saveBounds); + } + setState(sfDragging, False); +} + +void TView::draw() +{ + TDrawBuffer b; + + b.moveChar( 0, ' ', getColor(1), size.x ); + writeLine( 0, 0, size.x, size.y, b ); +} + +void TView::drawCursor() +{ + // SET: do it only if our owner gives permission + if( (state & sfFocused) != 0 && owner && owner->canShowCursor()) + resetCursor(); +} + +void TView::drawHide( TView* lastView ) +{ + drawCursor(); + drawUnderView(Boolean(state & sfShadow), lastView); +} + +void TView::drawShow( TView* lastView ) +{ + drawView(); + if( (state & sfShadow) != 0 ) + drawUnderView( True, lastView ); +} + +void TView::drawUnderRect( TRect& r, TView* lastView ) +{ + owner->clip.intersect(r); + owner->drawSubViews(nextView(), lastView); + owner->clip = owner->getExtent(); +} + +void TView::drawUnderView( Boolean doShadow, TView* lastView ) +{ + TRect r = getBounds(); + if( doShadow != False ) + r.b += shadowSize; + drawUnderRect( r, lastView ); +} + +void TView::drawView() +{ + if (exposed()) + { + draw(); + drawCursor(); + } +} + +void TView::enableCommands( TCommandSet& commands ) +{ + commandSetChanged = Boolean( commandSetChanged || + ((curCommandSet&commands) != commands) ); + curCommandSet += commands; +} + +void TView::enableCommand( ushort command ) +{ + commandSetChanged = Boolean( commandSetChanged || + !curCommandSet.has( command ) ); + curCommandSet += command; +} + +void TView::endModal( ushort command ) +{ + if( TopView() != 0 ) + TopView()->endModal(command); +} + +Boolean TView::eventAvail() +{ + TEvent event; + getEvent(event); + if( event.what != evNothing ) + putEvent(event); + return Boolean( event.what != evNothing ); +} + +TRect TView::getBounds() +{ + return TRect( origin, origin+size ); +} + +ushort TView::execute() +{ + return cmCancel; +} + +TRect TView::getClipRect() +{ + TRect clip = getBounds(); + if( owner != 0 ) + clip.intersect(owner->clip); + clip.move(-origin.x, -origin.y); + return clip; +} + +ushort TView::getColor( ushort color ) +{ + ushort colorPair = color >> 8; + + if( colorPair != 0 ) + colorPair = mapColor(colorPair) << 8; + + colorPair |= mapColor( uchar(color) ); + + return colorPair; +} + +void TView::getCommands( TCommandSet& commands ) +{ + commands = curCommandSet; +} + +void TView::getData( void * ) +{ +} + +void TView::getEvent( TEvent& event ) +{ + if( owner != 0 ) + owner->getEvent(event); +} + +TRect TView::getExtent() +{ + return TRect( 0, 0, size.x, size.y ); +} + +ushort TView::getHelpCtx() +{ + if( (state & sfDragging) != 0 ) + return hcDragging; + return helpCtx; +} + +TPalette& TView::getPalette() const +{ + static char ch = 0; + static TPalette palette( &ch, 0 ); + return palette; +} + +Boolean TView::getState( ushort aState ) +{ + return Boolean( (state & aState) == aState ); +} + +void TView::growTo( int x, int y ) +{ + TRect r = TRect(origin.x, origin.y, origin.x + x, origin.y + y); + locate(r); +} + +void TView::handleEvent(TEvent& event) +{ + if( event.what == evMouseDown ) + { + if(!(state & (sfSelected | sfDisabled)) && (options & ofSelectable) ) + { + select(); + if( !(state & sfSelected) || // SET: If we failed to get the focus forget + // about this mouse click. + !(options & ofFirstClick) ) + clearEvent(event); + } + } +} + +void TView::hide() +{ + if( (state & sfVisible) != 0 ) + setState( sfVisible, False ); +} + +void TView::hideCursor() +{ + setState( sfCursorVis, False ); +} + +void TView::keyEvent( TEvent& event ) +{ + do { + getEvent(event); + } while( event.what != evKeyDown ); +} + +#define range(Val, Min, Max) (((Val < Min) ? Min : ((Val > Max) ? Max : Val))) + +void TView::locate( TRect& bounds ) +{ + TPoint min, max; + sizeLimits(min, max); + bounds.b.x = bounds.a.x + range(bounds.b.x - bounds.a.x, min.x, max.x); + bounds.b.y = bounds.a.y + range(bounds.b.y - bounds.a.y, min.y, max.y); + TRect r = getBounds(); + if( bounds != r ) + { + changeBounds( bounds ); + if( owner != 0 && (state & sfVisible) != 0 ) + { + if( (state & sfShadow) != 0 ) + { + r.Union(bounds); + r.b += shadowSize; + } + drawUnderRect( r, 0 ); + } + } +} + +void TView::makeFirst() +{ + putInFrontOf(owner->first()); +} + +TPoint TView::makeGlobal( TPoint source ) +{ + TPoint temp = source + origin; + TView *cur = this; + while( cur->owner != 0 ) + { + cur = cur->owner; + temp += cur->origin; + } + return temp; +} + +TPoint TView::makeLocal( TPoint source ) +{ + TPoint temp = source - origin; + TView* cur = this; + while( cur->owner != 0 ) + { + cur = cur->owner; + temp -= cur->origin; + } + return temp; +} + +Boolean TView::mouseEvent(TEvent& event, ushort mask) +{ + do { + getEvent(event); + } while( !(event.what & (mask | evMouseUp)) ); + + return Boolean(event.what != evMouseUp); +} + +Boolean TView::mouseInView(TPoint mouse) +{ + mouse = makeLocal( mouse ); + TRect r = getExtent(); + return r.contains(mouse); +} + +void TView::moveTo( int x, int y ) +{ + TRect r( x, y, x+size.x, y+size.y ); + locate(r); +} + +TView *TView::nextView() +{ + if( this == owner->last ) + return 0; + else + return next; +} + +void TView::normalCursor() +{ + setState(sfCursorIns, False); +} + +TView *TView::prev() +{ + TView* res = this; + while( res->next != this ) + res = res->next; + return res; +} + +TView *TView::prevView() +{ + if( this == owner->first() ) + return 0; + else + return prev(); +} + +void TView::putEvent( TEvent& event ) +{ + if( owner != 0 ) + owner->putEvent(event); +} + +/**[txh]******************************************************************** + + Description: + Helper function to fill a TEvent structure and call putEvent. +@x{::PutEvent}. + +***************************************************************************/ + +void TView::putEvent( ushort what, ushort command, void *infoPtr ) +{ + TEvent event; + + event.what = what; + event.message.command = command; + event.message.infoPtr = infoPtr; + putEvent( event ); +} + +void TView::putInFrontOf( TView *Target ) +{ + TView *p, *lastView; + + if( owner != 0 && Target != this && Target != nextView() && + ( Target == 0 || Target->owner == owner) + ) + { + if( (state & sfVisible) == 0 ) + { + owner->removeView(this); + owner->insertView(this, Target); + } + else + { + lastView = nextView(); + p = Target; + while( p != 0 && p != this ) + p = p->nextView(); + if( p == 0 ) + lastView = Target; + state &= ~sfVisible; + if( lastView == Target ) + drawHide(lastView); + owner->removeView(this); + owner->insertView(this, Target); + state |= sfVisible; + if( lastView != Target ) + drawShow(lastView); + if( (options & ofSelectable) != 0 ) + owner->resetCurrent(); + } + } +} + +void TView::select() +{ + if( (options & ofTopSelect) != 0 ) + makeFirst(); + else if( owner != 0 ) + owner->setCurrent( this, normalSelect ); +} + +void TView::setBounds( const TRect& bounds ) +{ + origin = bounds.a; + size = bounds.b - bounds.a; +} + +void TView::setCommands( TCommandSet& commands ) +{ + commandSetChanged = Boolean( commandSetChanged || + (curCommandSet != commands )); + curCommandSet = commands; +} + +void TView::setCursor( int x, int y ) +{ + cursor.x = x; + cursor.y = y; + drawCursor(); +} + +void TView::setData( void * ) +{ +} + +void TView::setState( ushort aState, Boolean enable ) +{ + if( enable == True ) + state |= aState; + else + state &= ~aState; + + if( owner == 0 ) + return; + + switch( aState ) + { + case sfVisible: + if( (owner->state & sfExposed) != 0 ) + setState( sfExposed, enable ); + if( enable == True ) + drawShow( 0 ); + else + drawHide( 0 ); + if( (options & ofSelectable) != 0 ) + owner->resetCurrent(); + break; + case sfCursorVis: + case sfCursorIns: + drawCursor(); + break; + case sfShadow: + drawUnderView( True, 0 ); + break; + case sfFocused: + if (owner && owner->canShowCursor()) + // SET: do it only if our owner gives permission + resetCursor(); + message( owner, + evBroadcast, + (enable == True) ? cmReceivedFocus : cmReleasedFocus, + this + ); + break; + } +} + +void TView::show() +{ + if( (state & sfVisible) == 0 ) + setState(sfVisible, True); +} + +void TView::showCursor() +{ + setState( sfCursorVis, True ); +} + +void TView::sizeLimits( TPoint& min, TPoint& max ) +{ + min.x = min.y = 0; + if( owner != 0 ) + max = owner->size; + else + max.x = max.y = INT_MAX; +} + +TView* TView::TopView() +{ + if( TheTopView != 0 ) + return TheTopView; + else + { + TView* p = this; + while( p != 0 && !(p->state & sfModal) ) + p = p->owner; + return p; + } +} + +Boolean TView::valid( ushort ) +{ + return True; +} + +Boolean TView::containsMouse( TEvent& event ) +{ + return Boolean( (state & sfVisible) != 0 && + mouseInView( event.mouse.where ) + ); +} + +void TView::shutDown() +{ + hide(); + if( owner != 0 ) + owner->remove( this ); + TObject::shutDown(); +} + +#if !defined( NO_STREAM ) +void TView::write( opstream& os ) +{ + ushort saveState = + state & ~( sfActive | sfSelected | sfFocused | sfExposed ); + + os << origin << size << cursor + << growMode << dragMode << helpCtx + << saveState << options << eventMask; +} + +void *TView::read( ipstream& is ) +{ + is >> origin >> size >> cursor + >> growMode >> dragMode >> helpCtx + >> state >> options >> eventMask; + owner = 0; + next = 0; + return this; +} + +TStreamable *TView::build() +{ + return new TView( streamableInit ); +} + +TView::TView( StreamableInit ) +{ +} +#endif // NO_STREAM + +uchar TView::mapColor( uchar color ) +{ + if( color == 0 ) + return errorAttr; + TView *cur = this; + do { + TPalette& p = cur->getPalette(); + if( p[0] != 0 ) + { + if( color > p[0] ) + return errorAttr; + color = p[color]; + if( color == 0 ) + return errorAttr; + } + cur = cur->owner; + } while( cur != 0 ); + return color; +} + +void TView::resetCursor() +{ + int ax,cx,dx; + TView *self=this,*view; + if ((~state) & (sfVisible /*| sfCursorVis*/ | sfFocused)) goto lab4; + if (TScreen::getDontMoveHiddenCursor() && ((~state) & sfCursorVis)) goto lab4; + ax = cursor.y; + dx = cursor.x; +lab1: + if ( (ax<0) || (ax>=self->size.y) ) goto lab4; + if ( (dx<0) || (dx>=self->size.x) ) goto lab4; + ax += self->origin.y; + dx += self->origin.x; + if (!self->owner) goto lab5; + view = self->owner->last; +lab2: + view = view->next; + if (view == self) + { + self = view->owner; + goto lab1; + } + if (!(view->state & sfVisible)) goto lab2; + if (axorigin.y) goto lab2; + if (ax>=view->origin.y+view->size.y) goto lab2; + if (dxorigin.x) goto lab2; + if (dx>=view->origin.x+view->size.x) goto lab2; +lab4: + // Cursor disabled + TScreen::setCursorType(0); + return; + +lab5: + TScreen::setCursorPos(dx,ax); + if (state & sfCursorVis) + { + cx=TScreen::cursorLines; + if (state & sfCursorIns) + cx=100*256; + TScreen::setCursorType(cx); + } + else + TScreen::setCursorType(0); +} + +#define VIEW ((TGroup *)(view)) + +static TView *target; + +enum call_lab {lab_10,lab_11,lab_20}; +Boolean call(call_lab LAB,TView * &view,int &ax,int &bx,int &cx,int &si); + +Boolean call(call_lab LAB,TView * &view,int &ax,int &bx,int &cx,int &si) +{ + TView *retttarget,*rettview; + int rettax,rettcx,rettsi; + Boolean flag; + switch (LAB) + { + case lab_10 : goto lab10; + case lab_11 : goto lab11; + case lab_20 : goto lab20; + } + return False; +lab10: + view = view->owner; + if (VIEW->buffer) return True; +lab11: + target = view; + ax += view->origin.y; + si = view->origin.x; + bx += si; + cx += si; + view = view->owner; + if (!view) return True; + if (axclip.a.y) return False; + if (ax>=VIEW->clip.b.y) return False; + if (bxclip.a.x) bx = VIEW->clip.a.x; + if (cx>VIEW->clip.b.x) cx = VIEW->clip.b.x; + if (bx>=cx) return False; + view = VIEW->last; +lab20: + view = view->next; + if (view == target) goto lab10; + if (!(view->state & sfVisible)) goto lab20; + si = view->origin.y; + if (axsize.y; + if (ax>=si) goto lab20; + si = view->origin.x; + if (bxsize.x; + if (bx>=si) goto lab20; + bx = si; + if (bxsize.x; + if (cx>si) goto lab23; + cx = view->origin.x; + goto lab20; +lab23: + retttarget = target; + rettview = view; + rettsi = si; + rettcx = cx; + rettax = ax; + cx = view->origin.x; + flag = call(lab_20,view,ax,bx,cx,si); + ax = rettax; + cx = rettcx; + bx = rettsi; + view = rettview; + target = retttarget; + if (!flag) goto lab20; + return True; +} + +Boolean TView::exposed() +{ + int ax,bx,cx,si; + int rettax; + Boolean flag; + TView *view = this; + if (!(state & sfExposed)) return False; + ax = 0; + if (size.xsize.x; + rettax = ax; + flag = call(lab_11,view,ax,bx,cx,si); + ax = rettax; + if (flag) return True; + view = this; + ax++; + if (axsize.y) goto lab1; + return False; +} + +extern TPoint shadowSize; +extern uchar shadowAttr; + +static int offset; +static int y_pos,x_pos_start,x_pos_end,in_shadow; +const void * _Buffer; +TView *_view; + +void _call(int LAB); + +void call30(int x) +{ + TView *retttarget = target; + int rettoffset = offset; + TView *rettview = _view; + int rettdx = in_shadow; + int rettcx = x_pos_end; + int rettax = y_pos; + x_pos_end = x; + _call(20); + y_pos = rettax; + x_pos_end = rettcx; + in_shadow = rettdx; + _view = rettview; + offset = rettoffset; + target = retttarget; + x_pos_start = x; +} + +void call50() +{ + int count = x_pos_end - x_pos_start; + int buf_offset = y_pos * _view->size.x + x_pos_start; + int skip_offset = x_pos_start - offset; + const ushort *toBlit=((const ushort *)_Buffer)+skip_offset; + int isScreen=((TGroup *)(_view))->buffer==TScreen::screenBuffer; + + // Remap characters if needed + AllocLocalStr(aux,count*sizeof(ushort)); + if (isScreen && TVCodePage::OnTheFlyRemapNeeded()) + { + memcpy(aux,toBlit,count*sizeof(ushort)); + int i; + if (in_shadow) + {// Remap and shadow + for (i=0; ibuffer+buf_offset,toBlit,count*sizeof(ushort)); +} + +#ifdef TVCompf_MinGW +// SET: Not sure why Vadim wanted it +#define HideMouse() +#define ShowMouse() +#else +// DOS, Linux and Borland (SAA port) +#define HideMouse() TMouse::hide() +#define ShowMouse() TMouse::show() +#endif + +void _call(int LAB) +{ + int x; + switch (LAB) + { + case 00 : goto lab00; + case 20 : goto lab20; + } + return; +lab00: + offset = x_pos_start; + x_pos_end += x_pos_start; + in_shadow = 0; + if (y_pos < 0 || y_pos >= _view->size.y) return; + x_pos_start = max(x_pos_start,0); + x_pos_end = min(x_pos_end,_view->size.x); + if (x_pos_start >= x_pos_end) return; +lab10: + if ( !( _view->state & sfVisible) ) return; + if (!_view->owner) return; + target = _view; + y_pos += _view->origin.y; + x = _view->origin.x; + x_pos_start += x; + x_pos_end += x; + offset += x; + if (y_pos < _view->owner->clip.a.y) return; + if (y_pos >= _view->owner->clip.b.y) return; + x_pos_start = max(x_pos_start,_view->owner->clip.a.x); + x_pos_end = min(x_pos_end,_view->owner->clip.b.x); + if (x_pos_start >= x_pos_end) return; + _view = _view->owner->last; +lab20: + do + { + _view = _view->next; + if (_view == target) break; + if (!(_view->state & sfVisible)) continue; + { + int y = _view->origin.y; + if (y_pos < y) continue; + y += _view->size.y; + if (y_pos < y) goto lab23; + if (!(_view->state & sfShadow)) continue; + y += shadowSize.y; + if (y_pos >= y) continue; + } + x = _view->origin.x; + x += shadowSize.x; + if (x_pos_start >= x) goto lab22; + if (x_pos_end <= x) continue; + call30(x); + lab22: + x += _view->size.x; + goto lab26; + lab23: + x = _view->origin.x; + if (x_pos_start < x) + { + if (x_pos_end <= x) continue; + call30(x); + } + x += _view->size.x; + if (x_pos_start < x) + { + if (x_pos_end <= x) return; + x_pos_start = x; + } + if (!(_view->state & sfShadow)) continue; + if (y_pos < _view->origin.y+shadowSize.y) continue; + x += shadowSize.x; + lab26: + if (x_pos_start >= x) continue; + in_shadow++; + if (x_pos_end <= x) continue; + call30(x); + in_shadow--; + } while (1); + + _view = _view->owner; + if (!((TGroup *)(_view))->buffer) + { + if (((TGroup *)(_view))->lockFlag) return; + goto lab10; + } + if ((((TGroup *)(_view))->buffer) != TScreen::screenBuffer) + { + call50(); + if (((TGroup *)(_view))->lockFlag) return; + goto lab10; + } + if (y_pos!=TEventQueue::curMouse.where.y || + x_pos_start>TEventQueue::curMouse.where.x || + x_pos_end<=TEventQueue::curMouse.where.x) + // the mouse is not in the draw area + { + TMouse::resetDrawCounter(); + call50(); + if (TMouse::getDrawCounter()==0) + { + // there was no mouse event + if (((TGroup *)(_view))->lockFlag) return; + goto lab10; + } + } + // the mouse is in the draw area or an event has occoured during + // the above drawing + HideMouse(); + call50(); + ShowMouse(); + if (((TGroup *)(_view))->lockFlag) return; + goto lab10; +} + +#define WRITEVIEW(b,a,c,B)\ +do\ +{\ + x_pos_start = b;\ + y_pos = a;\ + x_pos_end = c;\ + _Buffer = B;\ + _view = this;\ + _call(00);\ +} while (0) + +void TView::writeBuf(short x,short y,short w,short h,const void * Buffer) +{ + int i=0; + while (h--) + { + WRITEVIEW(x,y++,w,((ushort *)(Buffer))+w*i); + i++; + } +} + +void TView::writeChar( short x, short y, char c, uchar color, short count ) +{ + ushort colo = (mapColor(color) << 8) | (uchar)c; + int i=0; + if (count<=0) return; + AllocLocalUShort(temp,count*sizeof(ushort)); + for (i=0;i +#ifdef __MSS_USED__ + #define MSS + #undef __MSS_USED__ +#endif +#include +#include +#define Uses_intl_fprintf +#include +#include + +#ifdef HAVE_INTL_SUPPORT + +#define Uses_TVCodePage +class TVPartitionTree556; +#include + +// Prototypes, we know they exists +#ifndef _LIBINTL_H +extern "C" { +char *textdomain(const char *domainname); +char *bindtextdomain(const char *domainname, const char *dirname); +char *gettext(const char *msgid); +char *dgettext(const char *domain, const char *msgid); +char *gettext__(const char *msgid); +char *__gettext(const char *msgid); +} +#endif + +// Small mess to determine which function provides "gettext" +// Must use __DJGPP__ here +#ifndef __DJGPP__ +# if !defined(__GLIBC__) || __GLIBC__<2 + // By default use gettext +# define LibGetTextLow gettext +# else +# if (__GLIBC__==2 && __GLIBC_MINOR__>0) || __GLIBC__>2 +# define LibGetTextLow gettext +# else + // exception: glibc 2.0 needs __gettext +# define LibGetTextLow __gettext +# endif +# endif +#else +# define LibGetTextLow gettext__ +#endif + +char TVIntl::translate=0; +char TVIntl::initialized=0; +char TVIntl::needsRecode=0; +int TVIntl::forcedCatalogEncoding=-1; +int TVIntl::catalogEncoding=885901; +uchar TVIntl::recodeTable[256]; +void *TVIntl::previousCPCallBack=NULL; +char TVIntl::packageName[20]; + +const char *TVIntl::defaultEncodingNames[]= +{ + "de", + "es", + "pl", + "ru" +}; +int TVIntl::defaultEncodings[]= +{ + 885901, // de + 885901, // es + 885902, // pl + 100000 // ru +}; +const int numEncs=3; + + +void TVIntl::initialize() +{ + if (initialized) return; + initialized=1; + const char *lang=getenv("LANG"); + if (lang) + { + translate=1; + int i; + char c0=tolower(lang[0]); + char c1=tolower(lang[1]); + for (i=0; i "Project-Id-Version... + return msgid; + const char *msgstr=LibGetTextLow(msgid); + if (msgid==msgstr) + msgstr=dgettext(packageName,msgstr); + return msgstr; +} + +void TVIntl::recodeStr(char *str, int len) +{ + int i; + uchar *s=(uchar *)str; + for (i=0; i127 ? recodeTable[s[i]] : s[i]; +} + +char *TVIntl::getTextNew(const char *msgid, Boolean onlyIntl) +{ + if (!msgid) return NULL; + const char *source; + if (translate) + source=getText(msgid); + else + source=msgid; + if (onlyIntl && source==msgid) + return NULL; + int len=strlen(source)+1; + char *ret=new char[len]; + memcpy(ret,source,len); + if (needsRecode) + { + //printf("Recodificando %s a ",ret); + recodeStr(ret,len-1); + //printf("%s\n",ret); + } + return ret; +} + +const char *TVIntl::getText(const char *msgid, stTVIntl *&cache) +{ + if (!translate || !msgid) return msgid; + int curCP=TVCodePage::GetAppCodePage(); + if (!cache) + cache=new stTVIntl; + else + { + if (cache->cp==-2) + return msgid; + if (curCP==cache->cp) + return cache->translation ? cache->translation : msgid; + DeleteArray(cache->translation); + } + cache->translation=getTextNew(msgid,True); + cache->cp=curCP; + return cache->translation ? cache->translation : msgid; +} + +void TVIntl::freeSt(stTVIntl *&cache) +{ + if (!cache) return; + DeleteArray(cache->translation); + delete cache; + cache=NULL; +} + +stTVIntl *TVIntl::emptySt() +{ + stTVIntl *p=new stTVIntl[1]; // It will be inserted in a TStringColletion + // where delete[] is used. + p->translation=NULL; + p->cp=-1; + return p; +} + +stTVIntl *TVIntl::dontTranslateSt() +{ + stTVIntl *p=new stTVIntl; + p->translation=NULL; + p->cp=-2; + return p; +} + +int TVIntl::snprintf(char *dest, size_t sz, const char *fmt, ...) +{ + va_list argptr; + char *intlFmt=getTextNew(fmt); + va_start(argptr,fmt); + int l=CLY_vsnprintf(dest,sz,intlFmt,argptr); + va_end(argptr); + DeleteArray(intlFmt); + return l; +} + +int TVIntl::fprintf(FILE *f, const char *fmt, ...) +{ + va_list argptr; + char *intlFmt=getTextNew(fmt); + va_start(argptr,fmt); + int l=vfprintf(f,intlFmt,argptr); + va_end(argptr); + DeleteArray(intlFmt); + return l; +} + +#if defined(TVOS_DOS) || (defined(TVOS_Win32) && !defined(TVCompf_Cygwin)) + #define NoHomeOrientedOS +#endif + +int TVIntl::autoInit(const char *package, const char *localeDir) +{ + char localedir[PATH_MAX]; + setlocale(LC_ALL, ""); + if (!localeDir) + localeDir=getenv("LOCALEDIR"); + + if (!localeDir) + { + #ifdef NoHomeOrientedOS + // if LOCALEDIR doesn't exists use %DJDIR%/share/locale + localeDir=getenv("DJDIR"); + if (localeDir) + { + strcpy(localedir,localeDir); + strcat(localedir,"/share/locale"); + } + else + return 0; + #else + strcpy(localedir,"/usr/share/locale"); + #endif + } + else + strcpy(localedir,localeDir); + + bindTextDomain(package,localedir); + textDomain(package); + return 1; +} + +#else +int TVIntl::snprintf(char *dest, size_t sz, const char *fmt, ...) +{ + va_list argptr; + va_start(argptr,fmt); + int l=CLY_vsnprintf(dest,sz,fmt,argptr); + va_end(argptr); + return l; +} + +int TVIntl::fprintf(FILE *f, const char *fmt, ...) +{ + va_list argptr; + va_start(argptr,fmt); + int l=vfprintf(f,fmt,argptr); + va_end(argptr); + return l; +} +#endif /* HAVE_INTL_SUPPORT */ + diff --git a/tvision/classes/tvtext1.cc b/tvision/classes/tvtext1.cc new file mode 100644 index 0000000..3955ea3 --- /dev/null +++ b/tvision/classes/tvtext1.cc @@ -0,0 +1,142 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. + + * + * + */ + +#define Uses_TScreen +#define Uses_TRadioButtons +#define Uses_TMenuBox +#define Uses_TFrame +#define Uses_TIndicator +#define Uses_THistory +#define Uses_TColorSelector +#define Uses_TMonoSelector +#define Uses_TColorDialog +#define Uses_TInputLine +#define Uses_TStatusLine +#define Uses_TCheckBoxes +#define Uses_TScrollBar +#define Uses_TButton +#define Uses_TDirListBox +#define Uses_TFileEditor +#define Uses_TFileInfoPane +#define Uses_TDeskTop +#define Uses_TListViewer +#include + +// All the strings are arrays ASCIIZ +// All duplicated to restore the original + +uchar TView::specialChars[] = +{ + 175, 174, 26, 27, ' ', ' ', 0 +}; +uchar TView::ospecialChars[] = +{ + 175, 174, 26, 27, ' ', ' ', 0 +}; + +uchar TView::noMoireUnFill=' '; // Just space +uchar TView::noMoireFill=0xDB; // Full block +uchar TView::onoMoireFill=0xDB; // Full block + +char TRadioButtons::button[] = " ( ) "; +char TRadioButtons::obutton[] = " ( ) "; +char TRadioButtons::check = 7; //  +char TRadioButtons::ocheck = 7; + +//" ÚÄ¿ ÀÄÙ ³ ³ ÃÄ´ " 8 +char TMenuBox::frameChars[] = " \332\304\277 \300\304\331 \263 \263 \303\304\264 "; +char TMenuBox::oframeChars[] = " \332\304\277 \300\304\331 \263 \263 \303\304\264 "; +char TMenuBox::rightArrow = 16; //  +char TMenuBox::orightArrow = 16; //  + +const char TFrame::initFrame[19] = + "\x06\x0A\x0C\x05\x00\x05\x03\x0A\x09\x16\x1A\x1C\x15\x00\x15\x13\x1A\x19"; + +char TFrame::frameChars[33] = + " À ³Úà ÙÄÁ¿´ÂÅ È ºÉÇ ¼ÍÏ»¶Ñ "; // for UnitedStates code page +char TFrame::oframeChars[33] = + " À ³Úà ÙÄÁ¿´ÂÅ È ºÉÇ ¼ÍÏ»¶Ñ "; // for UnitedStates code page + +// þ   +char TFrame::closeIcon[] = "[~\xFE~]"; +char TFrame::ocloseIcon[] = "[~\xFE~]"; +char TFrame::zoomIcon[] = "[~\x18~]"; +char TFrame::ozoomIcon[] = "[~\x18~]"; +char TFrame::unZoomIcon[] = "[~\x12~]"; +char TFrame::ounZoomIcon[] = "[~\x12~]"; +// Note: Eddie proposed 0xF (WHITE SUN WITH RAYS) but this reduces to * and +// is the same as 0xFE (BLACK SQUARE) (also reduced to *). +char TFrame::animIcon[] = "[~+~]"; +char TFrame::oanimIcon[] = "[~+~]"; +char TFrame::dragIcon[] = "~ÄÙ~"; +char TFrame::odragIcon[] = "~ÄÙ~"; + +char TIndicator::dragFrame = '\xCD'; // Í +char TIndicator::odragFrame = '\xCD'; // Í +char TIndicator::normalFrame = '\xC4'; // Ä +char TIndicator::onormalFrame = '\xC4'; // Ä +char TIndicator::modifiedStar = 15; //  +char TIndicator::omodifiedStar = 15; //  + +char THistory::icon[] = "\xDE~\x19~\xDD"; // ÞÝ +char THistory::oicon[] = "\xDE~\x19~\xDD"; // ÞÝ + +char TColorSelector::icon = '\xDB'; // Û +char TColorSelector::oicon = '\xDB'; // Û +char TColorSelector::mark = 8; +char TColorSelector::omark = 8; + +char TMonoSelector::button[] = " ( ) "; +char TMonoSelector::obutton[] = " ( ) "; + +char TInputLine::rightArrow = '\x10'; +char TInputLine::orightArrow = '\x10'; +char TInputLine::leftArrow = '\x11'; +char TInputLine::oleftArrow = '\x11'; + +char TStatusLine::hintSeparator[] = "\xB3 "; // ³ +char TStatusLine::ohintSeparator[] = "\xB3 "; // ³ + +char TCheckBoxes::button[] = " [ ] "; +char TCheckBoxes::obutton[] = " [ ] "; + +TScrollChars TScrollBar::vChars = {30, 31, 177, 254, 178}; // ±þ² +TScrollChars TScrollBar::ovChars = {30, 31, 177, 254, 178}; // ±þ² +TScrollChars TScrollBar::hChars = {17, 16, 177, 254, 178}; // ±þ² +TScrollChars TScrollBar::ohChars = {17, 16, 177, 254, 178}; // ±þ² + +char TButton::shadows[] = "\xDC\xDB\xDF"; // ÜÛß +char TButton::oshadows[] = "\xDC\xDB\xDF"; // ÜÛß +char TButton::markers[] = "[]"; +char TButton::omarkers[] = "[]"; + +char TDirListBox::pathDir[] = "ÀÄÂ"; +char TDirListBox::opathDir[] = "ÀÄÂ"; +char TDirListBox::firstDir[] = "ÀÂÄ"; +char TDirListBox::ofirstDir[] = "ÀÂÄ"; +char TDirListBox::middleDir[] = " ÃÄ"; +char TDirListBox::omiddleDir[] = " ÃÄ"; +char TDirListBox::lastDir[] = " ÀÄ"; +char TDirListBox::olastDir[] = " ÀÄ"; +char TDirListBox::graphics[] = "ÀÃÄ"; +char TDirListBox::ographics[] = "ÀÃÄ"; + +const char * TFileInfoPane::pmText = "p"; +const char * TFileInfoPane::amText = "a"; + +char TDeskTop::defaultBkgrnd = '\xB0'; +char TDeskTop::odefaultBkgrnd = '\xB0'; + +uchar TListViewer::columnSeparator = 179; // ³ +uchar TListViewer::ocolumnSeparator = 179; // ³ + diff --git a/tvision/classes/tvtext2.cc b/tvision/classes/tvtext2.cc new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tvision/classes/tvtext2.cc @@ -0,0 +1 @@ + diff --git a/tvision/classes/twindow.cc b/tvision/classes/twindow.cc new file mode 100644 index 0000000..e824363 --- /dev/null +++ b/tvision/classes/twindow.cc @@ -0,0 +1,275 @@ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + +Modified by Robert H”hne to be used for RHIDE. +Modified for i18n support by Salvador Eduardo Tropea. + + * + * + */ +// SET: Moved the standard headers here because according to DJ +// they can inconditionally declare symbols like NULL +#define Uses_string + +#define Uses_TKeys +#define Uses_TWindow +#define Uses_TEvent +#define Uses_TRect +#define Uses_TFrame +#define Uses_TScrollBar +#define Uses_opstream +#define Uses_ipstream +#define Uses_TPalette +#define Uses_TProgram // SET: TProgram::application broadcast +#include + +const TPoint minWinSize = {16, 6}; + +TWindowInit::TWindowInit( TFrame *(*cFrame)( TRect ) ) : + createFrame( cFrame ) +{ +} + +#define cpBlueWindow "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" +#define cpCyanWindow "\x10\x11\x12\x13\x14\x15\x16\x17" +#define cpGrayWindow "\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" + +TWindow::TWindow( const TRect& bounds, + const char *aTitle, + short aNumber + ) : + TWindowInit( &TWindow::initFrame ), + TGroup( bounds ), + flags( wfMove | wfGrow | wfClose | wfZoom ), + zoomRect( getBounds() ), + number( aNumber ), + palette( wpBlueWindow ), + title( newStr( aTitle ) ), + intlTitle( NULL ) +{ + state |= sfShadow; + options |= ofSelectable | ofTopSelect; + growMode = gfGrowAll | gfGrowRel; + eventMask |= evMouseUp; //for TFrame + if( createFrame != 0 && + (frame = createFrame( getExtent() )) != 0 + ) + insert( frame ); +} + +TWindow::~TWindow() +{ + DeleteArray((char *)title); + TVIntl::freeSt(intlTitle); +} + +void TWindow::close() +{ + if( valid( cmClose ) ) + { // SET: tell the application we are closing + message( TProgram::application, evBroadcast, cmClosingWindow, this ); + frame = 0; // so we don't try to use the frame after it's been deleted + CLY_destroy( this ); + } +} + +void TWindow::shutDown() +{ + frame = 0; + TGroup::shutDown(); +} + +TPalette& TWindow::getPalette() const +{ + static TPalette blue( cpBlueWindow, sizeof( cpBlueWindow )-1 ); + static TPalette cyan( cpCyanWindow, sizeof( cpCyanWindow )-1 ); + static TPalette gray( cpGrayWindow, sizeof( cpGrayWindow )-1 ); + static TPalette *palettes[] = + { + &blue, + &cyan, + &gray + }; + return *(palettes[palette]); +} + +const char *TWindow::getTitle( short ) +{ + return TVIntl::getText(title,intlTitle); +} + +void TWindow::handleEvent( TEvent& event ) +{ + TRect limits; + TPoint min, max; + + TGroup::handleEvent(event); + if( event.what== evCommand ) + switch (event.message.command) + { + case cmResize: + if( (flags & (wfMove | wfGrow)) != 0 ) + { + limits = owner->getExtent(); + sizeLimits(min, max); + dragView( event, dragMode | (flags & (wfMove | wfGrow)), + limits, min, max); + clearEvent(event); + } + break; + case cmClose: + if( (flags & wfClose) != 0 && + ( event.message.infoPtr == 0 || event.message.infoPtr == this ) + ) + { + if( (state & sfModal) == 0 ) + close(); + else + { + event.what = evCommand; + event.message.command = cmCancel; + putEvent( event ); + } + clearEvent( event ); + } + break; + case cmZoom: + if( (flags & wfZoom) != 0 && + (event.message.infoPtr == 0 || event.message.infoPtr == this) + ) + { + zoom(); + clearEvent(event); + } + break; + } + else if( event.what == evKeyDown ) + switch (event.keyDown.keyCode) + { + case kbTab: + case kbDown: + case kbRight: + selectNext(False); + clearEvent(event); + break; + case kbShiftTab: + case kbUp: + case kbLeft: + selectNext(True); + clearEvent(event); + break; + } + else if( event.what == evBroadcast && + event.message.command == cmSelectWindowNum && + event.message.infoInt == number && + (options & ofSelectable) != 0 + ) + { + select(); + clearEvent(event); + } +} + +TFrame *TWindow::initFrame( TRect r ) +{ + return new TFrame(r); +} + +void TWindow::setState( ushort aState, Boolean enable ) +{ +#define C(x) if (enable == True) enableCommand(x); else disableCommand(x) + TGroup::setState(aState, enable); + if( (aState & sfSelected) != 0 ) + { + setState(sfActive, enable); + if( frame != 0 ) + frame->setState(sfActive,enable); + C(cmNext); + C(cmPrev); + if( (flags & (wfGrow | wfMove)) != 0 ) + { + C(cmResize); + } + if( (flags & wfClose) != 0 ) + { + C(cmClose); + } + if( (flags & wfZoom) != 0 ) + { + C(cmZoom); + } + } +#undef C +} + +TScrollBar *TWindow::standardScrollBar( ushort aOptions ) +{ + TRect r = getExtent(); + if( (aOptions & sbVertical) != 0 ) + r = TRect( r.b.x-1, r.a.y+1, r.b.x, r.b.y-1 ); + else + r = TRect( r.a.x+2, r.b.y-1, r.b.x-2, r.b.y ); + + TScrollBar *s; + insert( s = new TScrollBar(r) ); + if( (aOptions & sbHandleKeyboard) != 0 ) + s->options |= ofPostProcess; + return s; +} + +void TWindow::sizeLimits( TPoint& min, TPoint& max ) +{ + TView::sizeLimits(min, max); + min = minWinSize; +} + +void TWindow::zoom() +{ + TPoint minSize, maxSize; + sizeLimits( minSize, maxSize ); + if( size != maxSize ) + { + zoomRect = getBounds(); + TRect r( 0, 0, maxSize.x, maxSize.y ); + locate(r); + } + else + locate( zoomRect ); +} + +#if !defined( NO_STREAM ) +void TWindow::write( opstream& os ) +{ + TGroup::write( os ); + os << flags << zoomRect << number << palette; + os << frame; + os.writeString( title ); +} + +void *TWindow::read( ipstream& is ) +{ + TGroup::read( is ); + is >> flags >> zoomRect >> number >> palette; + is >> frame; + title = is.readString(); + intlTitle = NULL; + return this; +} + +TStreamable *TWindow::build() +{ + return new TWindow( streamableInit ); +} + +TWindow::TWindow( StreamableInit ) : + TWindowInit( NULL ), + TGroup( streamableInit ) +{ +} +#endif // NO_STREAM + + diff --git a/tvision/classes/unix/unixdis.cc b/tvision/classes/unix/unixdis.cc new file mode 100644 index 0000000..deec174 --- /dev/null +++ b/tvision/classes/unix/unixdis.cc @@ -0,0 +1,130 @@ +/* Copyright (C) 1996-1998 Robert H”hne, see COPYING.RH for details */ +/* Copyright (C) 1999-2002 Salvador Eduardo Tropea */ +#include + +#define Uses_stdio +#define Uses_stdlib +#define Uses_unistd +#define Uses_TDisplay +#define Uses_TScreen +#define Uses_string +#define Uses_signal +#define Uses_ioctl +#include + +// I delay the check to generate as much dependencies as possible +#if defined(HAVE_NCURSES) && defined(TVOS_UNIX) && !defined(TVOSf_QNXRtP) + +#include +#include + +#include + +int TDisplayUNIX::cur_x=0; +int TDisplayUNIX::cur_y=0; +// SET: Current cursor shape +int TDisplayUNIX::cursorStart=85; // 85 % +int TDisplayUNIX::cursorEnd =100; // 100 % + +// SET: 1 when the size of the window where the program is running changed +volatile sig_atomic_t TDisplayUNIX::windowSizeChanged=0; + +int TDisplayUNIX::tty_fd=-1; // tty descriptor + +TDisplayUNIX::~TDisplayUNIX() {} + +void TDisplayUNIX::Init() +{ + setCursorPos=SetCursorPos; + getCursorPos=GetCursorPos; + getCursorShape=GetCursorShape; + setCursorShape=SetCursorShape; + getRows=GetRows; + getCols=GetCols; + setCrtModeExt=SetCrtModeExt; + checkForWindowSize=CheckForWindowSize; +} + +void TDisplayUNIX::SetCursorPos(unsigned x, unsigned y) +{ + char out[1024], *p = out; + + safeput(p, tparm(cursor_address,y, x)); + write(tty_fd, out, p - out); + cur_x = x; + cur_y = y; +} + +void TDisplayUNIX::GetCursorPos(unsigned &x, unsigned &y) +{ + char s[40]; + + // write/read are better here, because other functions might be buffered + write(tty_fd,"\e[6n",4); // Request cursor position from terminal + read(tty_fd,s,sizeof(s)); // Should never overflow... + + y = atoi(s+2)-1; + x = atoi(strchr(s,';')+1)-1; +} + +void TDisplayUNIX::SetCursorShape(unsigned start, unsigned end) +{ + char out[1024], *p=out; + if (start>=end) // hide + { + safeput(p,tparm(cursor_invisible)); + write(tty_fd,out,p-out); + } + else + { + safeput(p,tparm(cursor_normal)); + write(tty_fd,out,p-out); + } + cursorStart=start; + cursorEnd=end; + //fprintf(stderr,"SetCursorShape: %d,%d start>=end? %d\n",start,end,start>=end); +} + +void TDisplayUNIX::GetCursorShape(unsigned &start, unsigned &end) +{ + // Currently we don't know the real state. + start=cursorStart; + end =cursorEnd; + //fprintf(stderr,"GetCursorShape: %d,%d\n",start,end); +} + +ushort TDisplayUNIX::GetRows() +{ + if (dual_display) return 25; + winsize win; + win.ws_row=0xFFFF; + ioctl(tty_fd,TIOCGWINSZ,&win); + return win.ws_row!=0xFFFF ? win.ws_row : 25; +} + +ushort TDisplayUNIX::GetCols() +{ + if (dual_display) return 80; + winsize win; + win.ws_col=0xFFFF; + ioctl(tty_fd,TIOCGWINSZ,&win); + return win.ws_col!=0xFFFF ? win.ws_col : 80; +} + +void TDisplayUNIX::SetCrtModeExt(char *mode) +{ + system(mode); +} + +int TDisplayUNIX::CheckForWindowSize(void) +{ + int ret=windowSizeChanged!=0; + windowSizeChanged=0; + return ret; +} +#else // TVOS_UNIX && !TVOSf_QNXRtP + +#include + +#endif // else TVOS_UNIX && !TVOSf_QNXRtP + diff --git a/tvision/classes/unix/unixkey.cc b/tvision/classes/unix/unixkey.cc new file mode 100644 index 0000000..960501d --- /dev/null +++ b/tvision/classes/unix/unixkey.cc @@ -0,0 +1,566 @@ +/***************************************************************************** + + Todo: + Volar esto: int use_real_keyboard_bios=0; + + This code is GPL, see copying file for more details. + Keyboard handler for Linux Copyright by Salvador E. Tropea (SET) (1998,1999) + + That's the counterpart of the gkey.cc for DOS that I created some months ago +it uses curses input and tries to detect the shift/control status from the +keycode reported by curses. Additionally the routines detects ALT using the +ESC-keycode sequence (META+key) with a patch in the low level tv_GetRaw. + +RH: I moved that patch to the TGKey::gkey() member + + To make it better in the Linux console I'm mixing the modifiers flags from +the ioctl call with the ones I figured out from the code. + + It fixes a lot of problems that appears when running from telnet, but not +all. Lamentably looks like telnet standard protocols can't simply report all +the keyboard combinations. We lose some important things like Ctrl+Function +key, Shift+(Inset,End,Home,PgUp,PgDn,Delete,Arrows,etc.) and more. + +*****************************************************************************/ +#include + +#define Uses_stdio +#define Uses_unistd +#define Uses_ctype +#define Uses_stdlib +#define Uses_TEvent +#define Uses_TGKey +#define Uses_FullSingleKeySymbols +#define Uses_string +#include + +// I delay the check to generate as much dependencies as possible +#if defined(HAVE_NCURSES) && defined(TVOS_UNIX) && !defined(TVOSf_QNXRtP) + +#include + +// New curses (ncurses) headers +#ifdef TVOSf_FreeBSD + #include +#else + #include +#endif +#include + +#ifdef HAVE_KEYSYMS + // X11R6 keysyms list + #include +#endif + +//#define GKEY +#define TOSTDERR +#ifndef GKEY + #define dbprintf(a...) +#else + #ifdef TOSTDERR + #define dbprintf(a...) fprintf(stderr,a) + #else + #define dbprintf(a...) printf(a) + #endif +#endif + +/* Linux IOCTL values found experimentally */ +const int kblNormal=0,kblShift=1,kblAltR=2,kblCtrl=4,kblAltL=8; +const int MouseB1Down=0x20,MouseB2Down=0x21,MouseB3Down=0x22,MouseUp=0x23; + +#define IN_FD fileno(stdin) +#define META_MASK 0x8000 +#define NCursesGetCh getch +#define NCursesUnGetCh ungetch +// Who knows what's that? +#undef clear + +int use_real_keyboard_bios=0; +// xterm is a crappy terminal and does all in a way too different to the +// standard. +static int XtermMode=0; +static int MouseButtons=0; + +int TGKeyUNIX::Abstract; +char TGKeyUNIX::ascii; +ushort TGKeyUNIX::sFlags; +KeyType TGKeyUNIX::rawCode; + +// - 9 = Tab tiene conflicto con kbI+Control lo cual es natural, por otro +// -lado Ctrl+Tab no lo reporta en forma natural +// - a = Enter tiene conflicto con ^J, como ^J no lo reporta naturalmente sino +// -forzado por el keymap lo mejor es definirlo directamente. +static +unsigned char kbToName1[128] = +{ + 0,kbA,kbB,kbC,kbD,kbE,kbF,kbG, // 00-07 + kbH,kbTab,kbEnter,kbK,kbL,kbM,kbN,kbO, // 08-0F + kbP,kbQ,kbR,kbS,kbT,kbU,kbV,kbW, // 10-17 + kbX,kbY,kbZ,kbEsc,0,kbCloseBrace,kb6,kbMinus, // 18-1F + kbSpace,kbAdmid,kbDobleQuote,kbNumeral,kbDolar,kbPercent,kbAmper,kbQuote,// 20-27 + kbOpenPar,kbClosePar,kbAsterisk,kbPlus,kbComma,kbMinus,kbStop,kbSlash, // 28-2F + kb0,kb1,kb2,kb3,kb4,kb5,kb6,kb7, // 30-37 + kb8,kb9,kbDoubleDot,kbColon,kbLessThan,kbEqual,kbGreaterThan,kbQuestion, // 38-3F + kbA_Roba,kbA,kbB,kbC,kbD,kbE,kbF,kbG, // 40-47 + kbH,kbI,kbJ,kbK,kbL,kbM,kbN,kbO, // 48-4F + kbP,kbQ,kbR,kbS,kbT,kbU,kbV,kbW, // 50-57 + kbX,kbY,kbZ,kbOpenBrace,kbBackSlash,kbCloseBrace,kbCaret,kbUnderLine, // 58-5F + kbGrave,kbA,kbB,kbC,kbD,kbE,kbF,kbG, // 60-67 + kbH,kbI,kbJ,kbK,kbL,kbM,kbN,kbO, // 68-6F + kbP,kbQ,kbR,kbS,kbT,kbU,kbV,kbW, // 70-77 + kbX,kbY,kbZ,kbOpenCurly,kbOr,kbCloseCurly,kbTilde,kbBackSpace // 78-7F +}; + +// 15e = kb5 (del keypad) +static +unsigned char kbToName2[128] = +{ + 0,0,kbDown,kbUp,kbLeft,kbRight,kbHome,kbBackSpace, // 00-07 + 0,kbF1,kbF2,kbF3,kbF4,kbF5,kbF6,kbF7, // 08-0F + kbF8,kbF9,kbF10,kbF1,kbF2,kbF3,kbF4,kbF5, // 10-17 + kbF6,kbF7,kbF8,kbF9,kbF10,0,0,0, // 18-1F + 0,0,0,0,0,0,0,0, // 20-27 + 0,0,0,0,0,0,0,0, // 28-2F + 0,0,0,0,0,0,0,0, // 30-37 + 0,0,0,0,0,kbLeft,kbDown,kbRight, // 38-3F + kbUp,kbEterm,kbHome,kbEnd,kbUp,kbDown,kbRight,kbLeft, // 40-47 + 0,0,kbDelete,kbInsert,0,0,0,0, // 48-4F + 0,0,kbPgDn,kbPgUp,0,0,0,0, // 50-57 + 0,0,0,0,0,0,kb5,0, // 58-5F + 0,0,0,0,0,0,0,0, // 60-67 + kbEnd,0,0,0,0,0,0,0, // 68-6F + 0,0,0,0,0,0,0,0, // 70-77 + 0,0,0,0,0,0,0,kbBackSpace // 78-7F +}; + +const unsigned kbCtrl =kbCtrlCode>>4; +const unsigned kbAlt =kbAltLCode>>4; +const unsigned char kbShift=kbShiftCode>>4; + +static +unsigned char kbExtraFlags1[128] = +{ + 0,kbCtrl,kbCtrl,kbCtrl,kbCtrl,kbCtrl,kbCtrl,kbCtrl, // 00-07 + kbCtrl,0,0,kbCtrl,kbCtrl,kbCtrl,kbCtrl,kbCtrl, // 08-0F + kbCtrl,kbCtrl,kbCtrl,kbCtrl,kbCtrl,kbCtrl,kbCtrl,kbCtrl, // 10-17 + kbCtrl,kbCtrl,kbCtrl,0,0,kbCtrl,kbCtrl,kbCtrl, // 18-1F + 0,kbShift,kbShift,kbShift,kbShift,kbShift,kbShift,0, // 20-27 + kbShift,kbShift,kbShift,kbShift,0,0,0,0, // 28-2F + 0,0,0,0,0,0,0,0, // 30-37 + 0,0,kbShift,0,kbShift,0,kbShift,kbShift, // 38-3F + kbShift,kbShift,kbShift,kbShift,kbShift,kbShift,kbShift,kbShift, // 40-47 + kbShift,kbShift,kbShift,kbShift,kbShift,kbShift,kbShift,kbShift, // 48-4F + kbShift,kbShift,kbShift,kbShift,kbShift,kbShift,kbShift,kbShift, // 50-57 + kbShift,kbShift,kbShift,0,0,0,kbShift,kbShift, // 58-5F + 0,0,0,0,0,0,0,0, // 60-67 + 0,0,0,0,0,0,0,0, // 68-6F + 0,0,0,0,0,0,0,0, // 70-77 + 0,0,0,kbShift,kbShift,kbShift,kbShift,0, // 78-7F +}; + +static +unsigned char kbExtraFlags2[128] = +{ + 0,0,0,0,0,0,0,0, // 00-07 + 0,0,0,0,0,0,0,0, // 08-0F + 0,0,0,kbShift,kbShift,kbShift,kbShift,kbShift, // 10-17 + kbShift,kbShift,kbShift,kbShift,kbShift,0,0,0, // 18-1F + 0,0,0,0,0,0,0,0, // 20-27 + 0,0,0,0,0,0,0,0, // 28-2F + 0,0,0,0,0,0,0,0, // 30-37 + 0,0,0,0,0,0,0,0, // 38-3F + 0,0,0,0,0,0,0,0, // 40-47 + 0,0,0,0,0,0,0,0, // 48-4F + 0,0,0,0,0,0,0,0, // 50-57 + 0,0,0,0,0,0,0,0, // 58-5F + 0,0,0,0,0,0,0,0, // 60-67 + 0,0,0,0,0,0,0,0, // 68-6F + 0,0,0,0,0,0,0,0, // 70-77 + 0,0,0,0,0,0,0,kbAlt // 78-7F +}; + +#ifdef HAVE_KEYSYMS +// This table should be filled at compile time, or I can trust the values +// are standard?! +static +unsigned char kbX11Keys[256]; + +typedef struct +{ + unsigned symbol; + unsigned key; +} keyEquiv; + +keyEquiv XEquiv[] = +{ + /* Cursor control & motion */ + {XK_Home,kbHome}, {XK_Left,kbLeft}, {XK_Up,kbUp}, {XK_Right,kbRight}, + {XK_Down,kbDown}, {XK_Page_Up,kbPgUp}, {XK_Page_Down, kbPgDn}, + {XK_End,kbEnd}, {XK_Begin,kbHome}, + /* Misc Functions */ + {XK_Insert, kbInsert}, {XK_Delete, kbDelete}, + /* TTY Functions */ + {XK_Return, kbEnter}, {XK_BackSpace, kbBackSpace}, {XK_Tab, kbTab}, + {XK_Escape, kbEsc}, + /* Auxilliary Functions */ + {XK_F1, kbF1}, {XK_F2, kbF2}, {XK_F3, kbF3}, {XK_F4, kbF4}, {XK_F5, kbF5}, + {XK_F6, kbF6}, {XK_F7, kbF7}, {XK_F8, kbF8}, {XK_F9, kbF9}, {XK_F10, kbF10}, + {XK_F11, kbF11}, {XK_F12, kbF12}, + /* Keypad Functions */ + {XK_KP_0,kb0}, {XK_KP_1,kb1}, {XK_KP_2,kb2}, {XK_KP_3,kb3}, {XK_KP_4,kb4}, + {XK_KP_5,kb5}, {XK_KP_6,kb6}, {XK_KP_7,kb7}, {XK_KP_8,kb8}, {XK_KP_9,kb9}, + {XK_KP_Enter, kbEnter}, {XK_KP_Home,kbHome}, {XK_KP_Left,kbLeft}, + {XK_KP_Up, kbUp}, {XK_KP_Right,kbRight}, {XK_KP_Down, kbDown}, + {XK_KP_Page_Up, kbPgUp}, {XK_KP_Page_Down,kbPgDn}, {XK_KP_End,kbEnd}, + {XK_KP_Begin, kbHome}, {XK_KP_Insert, kbInsert}, {XK_KP_Delete, kbDelete}, + {XK_KP_Equal, kbEqual}, {XK_KP_Multiply, kbAsterisk}, {XK_KP_Add, kbPlus}, + {XK_KP_Subtract, kbMinus}, {XK_KP_Decimal, kbStop}, {XK_KP_Divide, kbSlash}, + /* End */ + {0,0} +}; +#endif // HAVE_KEYSYMS + +void TGKeyUNIX::SetKbdMapping(int version) +{ + Mode=version; + switch (version) + { + case unixXterm: // It can be combined with others + #ifdef HAVE_DEFINE_KEY + // SET: Here is a temporal workaround for Eterm when the user uses + // the xterm terminfo file (normal in Debian). + define_key("\e[7~",KEY_F(58)); // Home + define_key("\e[8~",KEY_F(59)); // End + define_key("\eOx",KEY_F(56)); // Keypad Up + define_key("\eOv",KEY_F(55)); // Keypad Right + define_key("\eOw",KEY_F(54)); // Keypad Down + define_key("\eOt",KEY_F(53)); // Keypad Left + #endif + #ifdef KEY_MOUSE + // This exists in 1.9.9 but not in 1.8.6 + // 0631 == KEY_MOUSE + kbToName2[KEY_MOUSE & 0x7F]=kbMouse; + kbExtraFlags2[KEY_MOUSE & 0x7F]=0; + #endif + XtermMode=1; + break; + case unixNoXterm: + #ifdef KEY_MOUSE + kbToName2[KEY_MOUSE & 0x7F]=kbF7; + kbExtraFlags2[KEY_MOUSE & 0x7F]=kbShift; + #endif + XtermMode=0; + break; + case unixEterm: + #if defined(HAVE_KEYSYMS) && defined(HAVE_DEFINE_KEY) + // SET: I submited a patch to Eterm maintainers for it: + define_key("\x1B[k",KEY_F(57)); // End + memset(kbX11Keys,0,sizeof(kbX11Keys)); + { + int i; + for (i=0; XEquiv[i].symbol; i++) + kbX11Keys[XEquiv[i].symbol & 0xFF]=XEquiv[i].key; + } + #endif + #ifdef KEY_MOUSE + // 0631 == KEY_MOUSE + kbToName2[KEY_MOUSE & 0x7F]=kbMouse; + kbExtraFlags2[KEY_MOUSE & 0x7F]=0; + #endif + XtermMode=2; + break; + } +} + +int TGKeyUNIX::GetKbdMapping(int version) +{ + switch (version) + { + case unixXterm: + return XtermMode==1; + case unixNoXterm: + return !XtermMode; + break; + case unixEterm: + return XtermMode==2; + } + return 0; +} + +// The intelligence is here +ushort TGKeyUNIX::GKey(void) +{ + Abstract=0; + + GetRaw(); + // Xterm hacks: + if (XtermMode) + { + #ifdef KEY_MOUSE + if (rawCode.full==KEY_MOUSE) + { + dbprintf("TGKey::gkey: Mouse event detected\r\n"); + Abstract=kbMouse; + return rawCode.full; + } + #endif + #ifdef HAVE_KEYSYMS + if (rawCode.full==KEY_F(57)) + { + dbprintf("TGKey::gkey: Special Eterm keysym detected\r\n"); + Abstract=kbEterm; + return rawCode.full;; + } + #endif + if (rawCode.full & 0x80) + { + sFlags|=kblAltL; + rawCode.full &= ~0x80; + dbprintf("Adding left alt because the code contains 0x80 and xterm detected\r\n"); + } + } + if (rawCode.full & META_MASK) + { + sFlags|=kblAltL; + rawCode.full &= ~META_MASK; + dbprintf("Adding left alt because the code contains META key\r\n"); + } + + //---- The following code takes advantage of the flags reported by the ioctl + //---- call. As this mechanism isn't available if we aren't loged in the + //---- console I add more information later. + + // Compose the shift flags: + if (sFlags & kblShift) + Abstract|=kbShiftCode; + if (sFlags & kblCtrl) + Abstract|=kbCtrlCode; + switch (AltSet) + { + case 0: // Normal thing, left is left, right is right + if (sFlags & kblAltL) + Abstract|=kbAltLCode; + else + if (sFlags & kblAltR) + Abstract|=kbAltRCode; + break; + case 1: // Reverse thing + if (sFlags & kblAltL) + Abstract|=kbAltRCode; + else + if (sFlags & kblAltR) + Abstract|=kbAltLCode; + break; + default: // Compatibility + if (sFlags & (kblAltL | kblAltR)) + Abstract|=kbAltLCode; + } + + //--- Translate the rest + unsigned char *name,*flags; + // This values could be 0 or 1 because curses reports upto 512 keys + unsigned isASCIIif; + if (rawCode.b.scan) + { + name=kbToName2; + flags=kbExtraFlags2; + isASCIIif=128; + } + else + { + name=kbToName1; + flags=kbExtraFlags1; + isASCIIif=32; + } + unsigned key=rawCode.full; + if (key & 0x80) + { // Keys over 127 are interpreted as ASCII + ascii=key; + rawCode.b.scan=ascii; + //Abstract|=kbUnknown; + } + else + { // The rest are passed by the tables + key&=0x7F; + ascii=key>=isASCIIif ? key : 0; + if (name[key]==kbTab) ascii='\t'; + rawCode.b.scan=ascii; + Abstract|=name[key] | (flags[key]<<4); + sFlags|=(flags[key]<<4); + } + return rawCode.full; +} + +// All the info. from BIOS in one call +void TGKeyUNIX::GetRaw(void) +{ + int code; + + /* see if there is data available */ + if ((code=NCursesGetCh())!=ERR) + { + if (code==27) + { + if (kbhit()) + { + int code2=NCursesGetCh(); + if (code2!=27) + code=code2 | META_MASK; + } + } + } + else + { + rawCode.full=0; + sFlags=0; + return; + } + rawCode.full=code; + //printf("0x%04X\r\n",code); + sFlags=GetShiftState(); +} + +int TGKeyUNIX::KbHit(void) +{ + int c=NCursesGetCh(); + if (c!=ERR) NCursesUnGetCh(c); + return c!=ERR; +} + +void TGKeyUNIX::Clear(void) +{ + tcflush(IN_FD,TCIFLUSH); +} + +void TGKeyUNIX::FillTEvent(TEvent &e) +{ + GKey(); + if (Abstract==kbMouse) + { // Mouse events are traslated to keyboard sequences: + int event=NCursesGetCh(); + int x=NCursesGetCh()-0x21; // They are 0x20+ and the corner is 1,1 + int y=NCursesGetCh()-0x21; + switch (event) + { + case MouseB1Down: + MouseButtons|=mbLeftButton; + break; + case MouseB2Down: + MouseButtons|=mbMiddleButton; + break; + case MouseB3Down: + MouseButtons|=mbRightButton; + break; + case MouseUp: // fuzzy, if both are pressed ... + if (MouseButtons & mbLeftButton) + MouseButtons&= ~mbLeftButton; + else + MouseButtons&= ~mbRightButton; + break; + } + THWMouse::forceEvent(x,y,MouseButtons); + e.what=evMouseUp; // Acts like a "key" + dbprintf("TGKey::fillTEvent: Reporting mouse instead of key (%d,%d:%d)\r\n",x,y,event); + } + else + #ifdef HAVE_KEYSYMS + if (Abstract==kbEterm) + { // X keysym reported as key sequence yuupi! + int key,c; + unsigned state=0,keysym=0; + c=0; // To avoid hanging + do + { + key=NCursesGetCh(); + if (key!=';') + { + state<<=4; + state+=key>='A' ? key+10-'A' : key-'0'; + } + c++; + } + while (key!=';' && c<3); + c=0; + do + { + key=NCursesGetCh(); + if (key!='~') + { + keysym<<=4; + keysym+=key>='A' ? key+10-'A' : key-'0'; + } + c++; + } + while (key!='~' && c<3); + ushort code=kbX11Keys[keysym & 0xFF]; + dbprintf("TGKey::fillTEvent: Reporting Eterm key (%X,%X code: %X)\r\n",state,keysym,code); + if (code) + { + sFlags=0; + // How can I do it better? + if (state & 1) + sFlags|=kbShiftCode; + if (state & 4) + sFlags|=kbCtrlCode; + if (state & 8) + sFlags|=kbAltLCode; + Abstract=code | sFlags; + e.keyDown.charScan.charCode=code==kbTab ? '\t' : 0; + e.keyDown.charScan.scanCode=0; + e.keyDown.raw_scanCode=0; + e.keyDown.keyCode=Abstract; + e.keyDown.shiftState=sFlags; + e.what=evKeyDown; + } + else + e.what=evNothing; + } + else + #endif + { + e.keyDown.charScan.charCode=sFlags & kblAltL ? 0 : ascii; + e.keyDown.charScan.scanCode=rawCode.b.scan; + e.keyDown.raw_scanCode=rawCode.b.scan; + e.keyDown.keyCode=Abstract; + e.keyDown.shiftState=sFlags; + e.what=evKeyDown; + dbprintf("TGKey::fillTEvent: Reporting key (%X/%X)\r\n",Abstract,sFlags); + } +} + +// I don't know if other UNIX flavors have an equivalent IOCTL +unsigned TGKeyUNIX::GetShiftState() +{ + return 0; +} + +static struct termios saved_attributes; + +void TGKeyUNIX::Resume() +{ + tcgetattr(STDIN_FILENO,&saved_attributes); +} + +void TGKeyUNIX::Suspend() +{ + tcsetattr(STDIN_FILENO,TCSANOW,&saved_attributes); +} + +void TGKeyUNIX::Init() +{ + TGKey::Suspend =TGKeyUNIX::Suspend; + TGKey::Resume =TGKeyUNIX::Resume; + TGKey::kbhit =KbHit; + TGKey::clear =Clear; + TGKey::gkey =GKey; + TGKey::getShiftState=GetShiftState; + TGKey::fillTEvent =FillTEvent; + TGKey::SetKbdMapping=TGKeyUNIX::SetKbdMapping; + TGKey::GetKbdMapping=TGKeyUNIX::GetKbdMapping; +} +#else // TVOS_UNIX && !TVOSf_QNXRtP + +#include + +#endif // else TVOS_UNIX && !TVOSf_QNXRtP + diff --git a/tvision/classes/unix/unixmouse.cc b/tvision/classes/unix/unixmouse.cc new file mode 100644 index 0000000..fafcd36 --- /dev/null +++ b/tvision/classes/unix/unixmouse.cc @@ -0,0 +1,148 @@ +/* Copyright (C) 1996-1998 Robert H”hne, see COPYING.RH for details */ +/* Copyright (C) 1999-2002 Salvador Eduardo Tropea */ +#include + +#define Uses_stdlib +#define Uses_string +#define Uses_stdio +#define Uses_time +#define Uses_TEvent +#define Uses_TEventQueue +#define Uses_TScreen +#define Uses_signal +#include + +// I delay the check to generate as much dependencies as possible +#if (defined(TVOS_UNIX) || defined(TVCompf_Cygwin)) && !defined(TVOSf_QNXRtP) + +#include +#include +#include + +//----------------- Common stuff --------------- + +//#define DEBUG +#ifdef DEBUG + #ifdef TVOSf_Linux + extern char *program_invocation_short_name; + #define LOG(s) do {cerr << program_invocation_short_name << ": " << s << endl; fflush(stderr);} while(0) + #else + #define LOG(s) do {cerr << s << endl; fflush(stderr);} while(0) + #endif +#else + #define LOG(s) do {;} while(0) +#endif + +#ifdef TV_BIG_ENDIAN + #define MouseAttrMask 0x007F; +#else + #define MouseAttrMask 0x7F00; +#endif + +static int last_x=0,last_y=0; +static ushort mouse_char; + +static +void get_mouse_char() +{ + mouse_char=TScreen::getCharacter(last_x+last_y*TScreen::screenWidth); +} + +static +void set_mouse_char() +{ + ushort c=mouse_char ^ MouseAttrMask; + TScreen::setCharacter(last_x+last_y*TScreen::screenWidth,c); +} + +static +void reset_mouse_char() +{ + TScreen::setCharacter(last_x+last_y*TScreen::screenWidth,mouse_char); +} + +static volatile +void show_mouse_char() +{ + if (last_x>TScreen::screenWidth) + last_x=0; + if (last_y>TScreen::screenHeight) + last_y=0; + get_mouse_char(); + set_mouse_char(); +} + +int THWMouseUNIX::DrawMouse(int x, int y) +{ + if (TScreen::suspended) return 0; + if (x!=last_x || y!=last_y) + { + if (visible) reset_mouse_char(); + last_x=x; + last_y=y; + if (visible) show_mouse_char(); + return 1; + } + return 0; +} + +void THWMouseUNIX::Show() +{ + visible=1; + show_mouse_char(); +} + +void THWMouseUNIX::Hide() +{ + reset_mouse_char(); + visible=0; +} + +void THWMouseUNIX::Init() +{ + THWMouse::Show=Show; + THWMouse::Hide=Hide; + THWMouse::drawMouse=DrawMouse; +} + +THWMouseUNIX::~THWMouseUNIX() +{ +} + +#ifdef HAVE_NCURSES +//---------------- XTerm version ----------------- + +void THWMouseXTerm::Resume() +{ + buttonCount=3; // X uses at least 3 buttons + // Save old hilit tracking and enable mouse tracking (GPM_XTERM_ON) + TScreenUNIX::SendToTerminal("\x1B[?1000s\x1B[?1000h"); + LOG("using xterm* mouse"); + show(); +} + +void THWMouseXTerm::Suspend() +{ + // Disable mouse tracking and restore old hilittracking (GPM_XTERM_OFF) + TScreenUNIX::SendToTerminal("\x1B[?1000l\x1B[?1000r"); + LOG("xterm mouse disabled"); +} + +void THWMouseXTerm::Init() +{ + THWMouseUNIX::Init(); + THWMouse::Resume=Resume; + THWMouse::Suspend=Suspend; +} + +THWMouseXTerm::~THWMouseXTerm() +{ +} +#endif // HAVE_NCURSES +#else // TVOS_UNIX && !TVOSf_QNXRtP + +#include +#include + +#endif // else TVOS_UNIX && !TVOSf_QNXRtP + diff --git a/tvision/classes/unix/unixscr.cc b/tvision/classes/unix/unixscr.cc new file mode 100644 index 0000000..b98416d --- /dev/null +++ b/tvision/classes/unix/unixscr.cc @@ -0,0 +1,1117 @@ +/* Copyright (C) 1996-1998 Robert H”hne, see COPYING.RH for details */ +/* Copyright (C) 1998-2002 Salvador Eduardo Tropea */ +/* +TODO: +TurboVision_screenOptions +See ToDo in the mouse initialization. + +TODO: +Alt+X not working on Woody. Solution: start Eterm with --meta-mod 1. + +TODO: +Mouse reporting not disabled at exit!!! + +*/ +#include + +#define Uses_TScreen +#define Uses_TEvent +#define Uses_TDrawBuffer +#define Uses_TGKey +#define Uses_string +#define Uses_ctype +#define Uses_TVCodePage +#define Uses_signal +#define Uses_ioctl +#define Uses_stdio +#define Uses_stdlib +#include + +// I delay the check to generate as much dependencies as possible +#if defined(HAVE_NCURSES) && defined(TVOS_UNIX) && !defined(TVOSf_QNXRtP) + +#include +#include +#include +#include +#include + +// I don't know why it's needed, but it seems to be only known to me way +// to get rhgdb built so it doesn't mess up terminal settings. +// Strange but rhide and setedit doesn't have this problem. +// Andris Pavenis +#define SAVE_TERMIOS +#include +#include +#include +#include + +#ifdef TVOSf_FreeBSD + #include +#else + #include +#endif +#include + +//#define DEBUG +#ifdef DEBUG + #ifdef TVOSf_Linux + extern char *program_invocation_short_name; + #define LOG(s) do {cerr << program_invocation_short_name << ": " << s << endl; fflush(stderr);} while(0) + #else + #define LOG(s) do {cerr << s << endl; fflush(stderr);} while(0) + #endif +#else + #define LOG(s) do {;} while(0) +#endif + +int TScreenUNIX::use_pc_chars=1; +int TScreenUNIX::TerminalType; +FILE *TScreenUNIX::tty_file=0; +int TScreenUNIX::palette; +int TScreenUNIX::force_redraw=0; +cc_t TScreenUNIX::oldKeys[5]; +int TScreenUNIX::old_col=-1; +int TScreenUNIX::old_fore=-1; +int TScreenUNIX::old_back=-1; +ushort *TScreenUNIX::user_buffer=0; +int TScreenUNIX::user_buffer_size; +unsigned TScreenUNIX::user_cursor_x; +unsigned TScreenUNIX::user_cursor_y; +char *TScreenUNIX::terminal=0; +char TScreenUNIX::cursesInitialized=0; +char TScreenUNIX::termAttrsSaved=0; +#ifdef SAVE_TERMIOS +struct termios TScreenUNIX::old_term; +struct termios TScreenUNIX::new_term; +#endif + +TScreen *TV_UNIXDriverCheck() +{ + TScreenUNIX *drv=new TScreenUNIX(); + if (!TScreen::initialized) + { + delete drv; + return 0; + } + return drv; +} + +/**[txh]******************************************************************** + +Moverlo a un flag en la inicialización + + Description: + Finds if this terminal have variable code page of that's fixed. + + Return: + True if the terminal have a variable code page. + +Boolean TScreen::codePageVariable() +{ + return (TerminalType==GENER_TERMINAL || + TerminalType==XTERM_TERMINAL) ? False : True; +} +***************************************************************************/ + + +/**[txh]******************************************************************** + + Description: + Sends the string to the terminal. Is just a replacement for +fputs(tty_file,...) but ensures tty_file was initialized and does a flush to +be sure the characters are flushed to the device. (SET) + +***************************************************************************/ + +void TScreenUNIX::SendToTerminal(const char *value) +{ + if (!tty_file || !value) + return; + + fputs(value,tty_file); + fflush(tty_file); +} + +/* lookup table to translate characters from pc set to standard ascii */ + +static unsigned char pctoascii[] = +{ + " OOooooooooo!!!*><|!!O_|^V><--^V !\"#$%&'()*+,-./0123456789:;<=>?" + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~d" + "cueaaaaceeeiiiaaeafooouuyOUcLYPfaiounN--?--//!<>:%%|{+++++I+'++." + "`++}-+++`.+++=+++++++++++'.|-||-abipeouyooooooEn=+><()-=o..Vn2X " +}; + +static unsigned PC2curses[256]; + +/**[txh]******************************************************************** + + Description: + This function fixes the PC437->ASCII table. This solution is only partial +because the UNIX terminals usually use ISO-1 and never PC437. This will be +finally fixed when I add the codepage stuff in TVision (currently only +available in my editor). Anyways, it makes the windows look much better in +Xterminals, additionally that's what is supposed to do (ask curses). The +only non-clear stuff is that I'm supposing that the frames are in one of the +character sets (G0 or G1) and not made with some trick. That's true in Linux +and any ISO2022 terminal (Xterminals and DEC almost sure). (SET) + +***************************************************************************/ + +void TScreenUNIX::InitPCCharsMapping() +{ + int i; + // By default take the above translation + for (i=0; i<256; i++) + { + PC2curses[i]=pctoascii[i]; + } + if (use_pc_chars==1) + return; + for (i=128; i<256; i++) + PC2curses[i]=i; + // Special characters we can't print + PC2curses[127]='?'; + PC2curses[128+27]='?'; + // Terminals where the alternate charset fails (FreeBSD) + if (use_pc_chars==2) + return; + // Patch the curses available values from terminfo + PC2curses[0xDA]=ACS_ULCORNER; // Ú + PC2curses[0xC9]=ACS_ULCORNER; // É We don't have doubles in curses + PC2curses[0xC0]=ACS_LLCORNER; // À + PC2curses[0xC8]=ACS_LLCORNER; // È + PC2curses[0xBF]=ACS_URCORNER; // ¿ + PC2curses[0xBB]=ACS_URCORNER; // » + PC2curses[0xD9]=ACS_LRCORNER; // Ù + PC2curses[0xBC]=ACS_LRCORNER; // ¼ + + PC2curses[0xC3]=ACS_LTEE; // à + PC2curses[0xCC]=ACS_LTEE; // Ì + PC2curses[0xC6]=ACS_LTEE; // Æ + PC2curses[0xC7]=ACS_LTEE; // Ç + + PC2curses[0xB4]=ACS_RTEE; // ´ + PC2curses[0xB9]=ACS_RTEE; // ¹ + PC2curses[0xB5]=ACS_RTEE; // µ + PC2curses[0xB6]=ACS_RTEE; // ¶ + + PC2curses[0xC1]=ACS_BTEE; // Á + PC2curses[0xCA]=ACS_BTEE; // Ê + PC2curses[0xCF]=ACS_BTEE; // Ï + PC2curses[0xD0]=ACS_BTEE; // Ð + + PC2curses[0xC2]=ACS_TTEE; //  + PC2curses[0xCB]=ACS_TTEE; // Ë + PC2curses[0xD1]=ACS_TTEE; // Ñ + PC2curses[0xD2]=ACS_TTEE; // Ò + + PC2curses[0xC4]=ACS_HLINE; // Ä + PC2curses[0xCD]=ACS_HLINE; // Í + PC2curses[0xB3]=ACS_VLINE; // ³ + PC2curses[0xBA]=ACS_VLINE; // º + PC2curses[0xC5]=ACS_PLUS; + PC2curses[0x04]=ACS_DIAMOND; + PC2curses[0xB1]=ACS_CKBOARD; // 50% + PC2curses[0xB2]=ACS_CKBOARD; // 80% + PC2curses[0xFE]=ACS_BULLET; + PC2curses[0x11]=ACS_LARROW; + PC2curses[0x10]=ACS_RARROW; + PC2curses[0x19]=ACS_DARROW; + PC2curses[0x18]=ACS_UARROW; + // ACS_BOARD is the best choice here but isn't available in Xterms because + // the DEC graphic chars have only one "gray" character (ACS_CKBOARD) + PC2curses[0xB0]=ACS_CKBOARD;//ACS_BOARD; + // The block isn't available in DEC graphics. + //PC2curses[0xDB]=' ';//ACS_BLOCK; + PC2curses[0xDB]=ACS_BLOCK; + PC2curses[0xDC]=' '; + PC2curses[0xDD]=' '; + PC2curses[0xDF]=' '; + // I added the following line even when is supposed to be the default + // because in some way I managed to break it in Eterm while testing so I + // think other users could do the same. Explicitly requesting it for G1 + // is the best. + TScreenUNIX::SendToTerminal("\x1B)0"); // Choose DEC characters for G1 set (ISO2022) +} + +void TScreenUNIX::sigWindowSizeChanged(int sig) +{ + // Set a flag because we don't know if we can do it right now + TScreenUNIX::windowSizeChanged=1; + signal(sig,sigWindowSizeChanged); +} + +void TScreenUNIX::SpecialKeysDisable(int file) +{ + struct termios term; + tcgetattr(file,&term); + oldKeys[0]=term.c_cc[VSUSP]; + oldKeys[1]=term.c_cc[VSTART]; + oldKeys[2]=term.c_cc[VSTOP]; + oldKeys[3]=term.c_cc[VQUIT]; + oldKeys[4]=term.c_cc[VINTR]; + term.c_cc[VSUSP] =0; + term.c_cc[VSTART]=0; + term.c_cc[VSTOP] =0; + term.c_cc[VQUIT] =0; + term.c_cc[VINTR] =0; + tcsetattr(file,TCSANOW,&term); +} + +void TScreenUNIX::SpecialKeysRestore(int file) +{ + struct termios term; + tcgetattr(file,&term); + term.c_cc[VSUSP] =oldKeys[0]; + term.c_cc[VSTART]=oldKeys[1]; + term.c_cc[VSTOP] =oldKeys[2]; + term.c_cc[VQUIT] =oldKeys[3]; + term.c_cc[VINTR] =oldKeys[4]; + tcsetattr(file,TCSANOW,&term); +} + +// This routine was heavily modified, and I think it needs more work (SET) +void TScreenUNIX::startcurses(int &terminalCodePage) +{ + int xterm=0; + + // SET: If we are under xterm* initialize some special stuff: + if (strncmp(terminal,"xterm-eterm-tv",14)==0) + { // Special keyboard treatment + TGKey::SetKbdMapping(TGKey::unixEterm); + xterm=1; + } + else + if (strncmp(terminal,"xterm",5)==0 || strncmp(terminal,"Eterm",5)==0) + { // Special keyboard treatment + TGKey::SetKbdMapping(TGKey::unixXterm); + xterm=1; + } + + /* Configure curses */ + stdscr->_flags |= _ISPAD; + // Make curses interpret the escape sequences + keypad(stdscr,TRUE); + // SET: remove the buffering and pass the values directly to us. The man + // pages recomend using it for interactive applications. Looks like it + // doesn't affect if the delay is 0 but I call it anyways + cbreak(); + noecho(); + /* set getch() in non-blocking mode */ + timeout(0); + + /* Select the palette and characters handling according to the terminal */ + // Unknown terminal, use monochrome + if (!terminal) + { + palette = PAL_MONO; + TScreenUNIX::screenMode = TScreenUNIX::smMono; + use_pc_chars = 0; + TerminalType=GENER_TERMINAL; + } + else if (!strcmp(terminal,"console") || + !strncmp(terminal,"linux",5)) + { // Special case where we know the values or can make a good guess + // Assume linux or linux-c + palette = PAL_HIGH; + TScreenUNIX::screenMode = TScreenUNIX::smCO80; + use_pc_chars = 1; + TerminalType=LINUX_TERMINAL; + LOG("Using high palette"); + if (strstr(terminal,"-m-")!=NULL || !strcmp(terminal+strlen(terminal)-2,"-m")) // linux-m + { // Mono mode, explicitly supress colors even if they are available + palette = PAL_MONO; + TScreen::screenMode = TScreen::smMono; + } + else if (strchr(terminal, '-')!=NULL && // Have a modifier + !(strstr(terminal,"-c-")!=NULL || !strcmp(terminal+strlen(terminal)-2,"-c"))) // It isn't color modifier + { // Not some color variation, so most probably a different charset + use_pc_chars = 0; + TerminalType=GENER_TERMINAL; + } + LOG(palette == PAL_HIGH ? "Using high palette" : "Using mono palette"); + } + else if (xterm && has_colors()) + { // SET: Here we know the escape sequences and as a plus the bold + // attribute can be used for another 8 foreground colors + //palette = PAL_LOW2; Alternative code + palette = PAL_HIGH; + TScreenUNIX::screenMode = TScreenUNIX::smCO80; + use_pc_chars = 0; + TerminalType=XTERM_TERMINAL; + } + else if (has_colors()) + { // Generic color terminal, that's more a guess than a real thing + palette = (max_colors>8) || !strcmp(terminal,"screen") ? PAL_HIGH : PAL_LOW; + TScreenUNIX::screenMode = TScreenUNIX::smCO80; + use_pc_chars = 0; + LOG("Using color palette (" << max_colors << "-8 colors)"); + TerminalType=GENER_TERMINAL; + } + else + { // No colors available + palette = PAL_MONO; + TScreenUNIX::screenMode = TScreenUNIX::smMono; + use_pc_chars = 0; + TerminalType=GENER_TERMINAL; + } + // SET: Not sure about it: FreeBSD terminals doesn't have frames in the "alternate + // characters map" or at leat needs more setup for using them. + if (strncmp(terminal,"cons25",6)==0) + { + use_pc_chars=2; + if (terminal[6]=='r' || terminal[6]=='u') + terminalCodePage=TVCodePage::KOI8r; + } + + switch (TerminalType) + { + case LINUX_TERMINAL: + // SET: Use G1 charset, set G1 to the loaded video fonts, print control chars. + // It means the kernel will send what we write directly to screen, just + // like in the VCSA case. + SendToTerminal("\e)K\xE"); + break; + case XTERM_TERMINAL: + // SET: I still wondering why I keep using ncurses. The f*ck|ng ncurses + // puts the keypad in an "application"(?) mode where numbers are never + // reported. + SendToTerminal("\e>"); + case GENER_TERMINAL: + // Select IBM PC chars? + SendToTerminal(enter_pc_charset_mode); + #ifdef TVOSf_FreeBSD + // Disable autowrapping + SendToTerminal("\e[?7l"); + #endif + break; + } + #ifdef SAVE_TERMIOS + /* Save the terminal attributes so we can restore them later. */ + /* for our screen */ + tcgetattr (tty_fd, &new_term); + #endif + + // SET: Generate a map to convert special chars into curses values + InitPCCharsMapping(); + // SET: Hook the signal generated when the size of the window changes + signal(SIGWINCH,sigWindowSizeChanged); +} + +/* + * Converts colors from the large TV palette (16 foreground colors and + * 16 background colors) to ncurses small palette (8 foreground colors + * and 8 background colors). + */ + +void TScreenUNIX::mapColor(char *&p, int col) +{ + static char map[] = {0, 4, 2, 6, 1, 5, 3, 7}; + int back,fore; + if (col == old_col) + return; + old_col = col; + back = (col >> 4) & 7; + fore = col & 15; +#define SB set_a_background ? set_a_background : set_background +#define SF set_a_foreground ? set_a_foreground : set_foreground + switch (palette) + { + // SET: That's a guess because we don't know how the colors are mapped + // It works for xterm* + case PAL_LOW: + fore&=7; + if (fore==back) + fore=(fore+1) & 7; /* kludge */ + if (back!=old_back) + safeput(p,tparm(SB,map[back])); + if (fore!=old_fore) + safeput(p,tparm(SF,map[fore])); + break; + /* SET: That's an alternative code for PAL_HIGH + case PAL_LOW2: + if (fore!=old_fore || back!=old_back) + { + if (fore>7) + sprintf(p,"\x1B[%d;%d;1m",map[(fore & 7)]+30,map[back]+40); + else // Reset attributes and then do the rest + sprintf(p,"\x1B[0;%d;%dm",map[fore]+30,map[back]+40); + p+=strlen(p); + } + break;*/ + // SET: The value to reset the bold is 22 and not 21 + case PAL_HIGH: + if (fore!=old_fore && back!=old_back) + sprintf(p,"\e[%d;%d;%dm",fore>7 ? 1 : 22, + 30+map[fore & 7],40+map[back]); + else + { + if (fore!=old_fore) + sprintf(p,"\e[%d;%dm",fore>7 ? 1 : 22,30+map[fore & 7]); + else + sprintf(p,"\e[%dm",40+map[back]); + } + p+=strlen(p); + break; + } + old_fore = fore; + old_back = back; +#undef SB +#undef SF +} + + +/* + * Writes a block of text. + */ + +void TScreenUNIX::writeBlock(int dst, int len, ushort *old, ushort *src) +{ + char out[4096], *p = out; + int col=-1; + int altSet=0,needAltSet; + + safeput(p,tparm(cursor_address,dst/TScreenUNIX::screenWidth, + dst%TScreenUNIX::screenWidth)); + while (len-->0) + { + int code =CLY_Low16(*src); + int newcol=CLY_High16(*src); + + *old++=*src++; + if (col!=newcol) /* change color ? */ + { + col = newcol; + if (palette>PAL_MONO) + mapColor(p, col); + else if (palette==PAL_MONO) + { + safeput(p, exit_attribute_mode); + if (col==0x0f) + safeput(p, enter_bold_mode); + else + if (col==0x70) + safeput(p, enter_reverse_mode); + } + } + + switch (TerminalType) + { + case XTERM_TERMINAL: + case GENER_TERMINAL: + code=PC2curses[code]; + needAltSet=code & A_ALTCHARSET; + if (needAltSet && !altSet) + { + altSet=1; + safeput(p,enter_alt_charset_mode); + } + else + if (!needAltSet && altSet) + { + altSet=0; + safeput(p,exit_alt_charset_mode); + } + *p++=code; + break; + case LINUX_TERMINAL: + /* SET: The following uses information I got from Linux kernel. + The file drivers/char/console.c have all the parsing of the + escape sequences. I put more information at the end of this + file. + Some characters are ever interpreted as control codes, here + I use a bitmap for them taked directly from the kernel. + The kernel code also sugest to use UTF-8 to print those + codes. + Note that Unicode 0xF000 | character means that character + must pass unchanged to the screen + */ + #define CTRL_ALWAYS 0x0800f501 /* Cannot be overridden by disp_ctrl */ + #define ENTER_UTF8 "\e%G" + #define EXIT_UTF8 "\e%@" + if (code<32 && ((CTRL_ALWAYS>>code) & 1)) + {/* This character can't be printed, we must use unicode */ + /* Enter UTF-8 and start constructing 0xF000 code */ + safeput(p,ENTER_UTF8 "\xEF\x80"); + /* Set the last 6 bits */ + *p++=code | 0x80; + /* Escape UTF-8 */ + safeput(p,EXIT_UTF8); + } + else if (code==128+27) + {/* A specially evil code: Meta+ESC, it can't be printed */ + /* Just send Unicode 0xF09B to screen */ + safeput(p,ENTER_UTF8 "\xEF\x82\x9B" EXIT_UTF8); + } + else + /* The rest pass directly unchanged */ + *p++=code; + break; + } + if (p>out+4000) + { + write(tty_fd,out,p-out); + p=out; + } + } + if (altSet) + safeput(p,exit_alt_charset_mode); + if (palette==PAL_MONO) + safeput(p,exit_attribute_mode); + safeput(p,tparm(cursor_address,cur_y,cur_x)); + write(tty_fd,out,p-out); +} + +TScreenUNIX::TScreenUNIX() +{ + // ************* First check all the things that can make as fail to work + // Release ^Q and ^S from Xon/Xoff duties + SpecialKeysDisable(fileno(stdin)); + // SET: Original code tried to open a tty at any cost, eg: if stdout was + // redirected it tried to open stdin's tty for writing. I don't see the + // point of such an effort and in fact crashes the library, so here I just + // explain to the user how to run the application in the right way. + if (!isatty(fileno(stdout))) + { + fprintf(stderr,"\r\n"); + fprintf(stderr,_("Error! %s"),_("that's an interactive application, don't redirect stdout. " + "If you want to collect information redirect stderr like this: " + "program 2> file")); + fprintf(stderr,"\r\n"); + return; + } + // SET: open it as a different file because we don't want to mix both + char *tty_name=ttyname(fileno(stdout)); + if (!tty_name) + { + fprintf(stderr,"Failed to get the name of the current terminal used for output!\r\n" + "Please e-mail to salvador@inti.gov.ar giving details about your setup\r\n" + "and the output of the tty command\r\n"); + return; + } + tty_file=fopen(tty_name,"w+b"); + if (!tty_file) + { + fprintf(stderr,"Failed to open the %s terminal!\r\n" + "Please e-mail to salvador@inti.gov.ar giving details about your setup\r\n" + "and the output of the tty command\r\n",tty_name); + tty_file=fopen(tty_name,"wb"); + if (tty_file) + fprintf(stderr,"Also tell me it works only for writing\r\n"); + return; + } + tty_fd=fileno(tty_file); + #ifdef SAVE_TERMIOS + /* Save the terminal attributes so we can restore them later. */ + /* for the user screen */ + tcgetattr(STDOUT_FILENO,&old_term); + termAttrsSaved=1; + #endif + + terminal=getenv("TERM"); + // old buggy code: if (!newterm(terminal,stdin,tty_file)) + // SET: according to man newterm that's the right order! It was a really + // hard bug, and produced all kind of wierd behavior (arrow keys failing, + // endwin not restoring screen, etc. + if (!newterm(terminal,tty_file,stdin)) + { + fprintf(stderr,"Not connected to a terminal (newterm for %s)\n",terminal); + return; + } + cursesInitialized=1; + // ************* If all went ok we can use this driver + + /* Don't need special rights anymore */ + seteuid(getuid()); + setegid(getgid()); + + initialized=1; + if (dCB) dCB(); + + TDisplayUNIX::Init(); + + TScreen::Resume=Resume; + TScreen::Suspend=Suspend; + TScreen::setCrtData=setCrtData; + TScreen::setVideoMode=setVideoMode; + TScreen::setVideoModeExt=setVideoModeExt; + TScreen::getCharacters=getCharacters; + TScreen::getCharacter=getCharacter; + TScreen::setCharacter=setCharacter; + TScreen::setCharacters=setCharacters; + TScreen::System_p=System; + + TGKeyUNIX::Init(); + if (terminal && (strncmp(terminal,"xterm",5)==0 || strncmp(terminal,"Eterm",5)==0)) + THWMouseXTerm::Init(); + #ifdef HAVE_GPM + else + THWMouseGPM::Init(); + #endif + + startupCursor=getCursorType(); + screenMode=startupMode=getCrtMode(); + + /* acquire screen size */ + screenWidth =GetCols(); + screenHeight=GetRows(); + #ifdef TVOSf_FreeBSD + // Kludge: until we find a right way to fix the "last-line" display + // problem, this is a solution. + //screenHeight--; + #endif + LOG("screen size is " << (int)screenWidth << "x" << (int)screenHeight); + + screenBuffer=new ushort[screenWidth * screenHeight]; + + // Fill the screenBuffer with spaces + int i,len = screenWidth*screenHeight; + for (i=0;i_flags &= ~_ISPAD; + // 2) Now reset the attributes, there is no "default color", is an atribute + // I know the name of only some attributes: 0=normal (what we need), + // 1=bold, 4=underline, 5=blink, 7=inverse and I think they are 9: + TScreenUNIX::SendToTerminal(tparm(set_attributes,0,0,0,0,0,0,0,0,0)); + if (!TScreenUNIX::suspended) + { + // 3) Clear the screen + clear(); + refresh(); + // 4) Set usable settings (like new line mode) + resetterm(); + // 5) Enable the echo or the user won't see anything + echo(); + // Now we can finally end + endwin(); + } + cursesInitialized=0; + } + if (tty_file) + { + fclose(tty_file); + tty_file=0; + } + + #ifdef SAVE_TERMIOS + if (termAttrsSaved) + { + termAttrsSaved=0; + tcsetattr(STDOUT_FILENO, TCSANOW, &old_term); + } + #endif + + if (!suspended) + { + RestoreScreen(); + suspended=1; + } + + if (screenBuffer) + { + DeleteArray(screenBuffer); + screenBuffer=0; + } + SpecialKeysRestore(fileno(stdin)); + + LOG("terminated"); +} + +void TScreenUNIX::Suspend() +{ + old_col = old_back = old_fore = -1; + // FIXME: When I know, how to get the cursor state + setCursorType(startupCursor); + if (!dual_display) + { + // SET: According to "man initscr" we must do endwin() to temporally stop + // the ncurses engine, I tried it using tty mode (xterm) and vcs mode and + // seems to work. + endwin(); + #ifdef SAVE_TERMIOS + /* Restore the terminal attributes. */ + /* for the user screen */ + tcsetattr (STDOUT_FILENO, TCSANOW, &old_term); + #endif + + #ifdef TVOSf_FreeBSD + // Enable autowrapping + SendToTerminal("\e[?7h"); + #endif + RestoreScreen(); + } +} + +void TScreenUNIX::setCrtData() +{ + screenMode =getCrtMode(); + screenWidth =getCols(); + screenHeight=getRows(); + hiResScreen =Boolean(screenHeight > 25); + cursorLines =getCursorType(); + setCursorType(0); +} + +void TScreenUNIX::setVideoMode(ushort mode) +{ + int oldWidth=screenWidth; + int oldHeight=screenHeight; + setCrtMode(fixCrtMode(mode)); + setCrtData(); + // allocating a zeroed screenBuffer, because this function + // is called in most cases (in RHIDE) after a SIGWINCH + if (screenWidth!=oldWidth || screenHeight!=oldHeight || !screenBuffer) + { + // Realloc screen buffer only if actually needed (it doesn't exist + // or screen size is changed) + if (screenBuffer) + DeleteArray(screenBuffer); + screenBuffer = new ushort[screenWidth*screenHeight]; + } + memset(screenBuffer,0,screenWidth*screenHeight*sizeof(ushort)); +} + +void TScreenUNIX::setVideoModeExt( char *mode ) +{ + int oldWidth=screenWidth; + int oldHeight=screenHeight; + setCrtModeExt(mode); + setCrtData(); + // allocating a zeroed screenBuffer, because this function + // is called in most cases (in RHIDE) after a SIGWINCH + if (screenWidth!=oldWidth || screenHeight!=oldHeight || !screenBuffer) + { + // Realloc screen buffer only if actually needed (it doesn't exist + // or screen size is changed) + if (screenBuffer) + DeleteArray(screenBuffer); + screenBuffer = new ushort[screenWidth*screenHeight]; + } + memset(screenBuffer,0,screenWidth*screenHeight*sizeof(ushort)); +} + +void TScreenUNIX::getCharacters(unsigned offset, ushort *buf, unsigned count) +{ + memcpy(buf,screenBuffer+offset,count*sizeof(ushort)); +} + +ushort TScreenUNIX::getCharacter(unsigned dst) +{ + ushort src; + getCharacters(dst,&src,1); + return src; +} + +void TScreenUNIX::setCharacter(unsigned offset,ushort value) +{ + setCharacters(offset,&value,1); +} + +/* + * Draws a line of text on the screen. + */ + +void TScreenUNIX::setCharacters(unsigned dst, ushort *src, unsigned len) +{ + ushort *old = screenBuffer + dst; + ushort *old_right = old + len - 1; + ushort *src_right = src + len - 1; + + /* remove unchanged characters from left to right */ + + if (!force_redraw) + { + while (len > 0 && *old == *src) + { + dst++; + len--; + old++; + src++; + } + + /* remove unchanged characters from right to left */ + + while (len > 0 && *old_right == *src_right) + { + len--; + old_right--; + src_right--; + } + } + + /* write only middle changed characters */ + + if (len > 0) writeBlock(dst, len, old, src); +} + +/***************************************************************************** + + Blink stuff. + +*****************************************************************************/ + +//int blink_use_bios = 1; +//int save_text_palette = 0; + +/*void setIntenseState() +{ +} + +void setBlinkState() +{ +} + +int getBlinkState() +{ // SET: 1 means blink enabled and hence only 8 colors (was a bug) + // Report it according to the mode (vcs v.s. tty) + return canWriteVCS() ? 1 : 0; +}*/ + +/***************************************************************************** + + Save/Restore screen + +*****************************************************************************/ + +void TScreenUNIX::RestoreScreen() +{ + char b[256],*p=b; + // Set color to gray over black + mapColor(p,7); *p=0; + SendToTerminal(b); + // Clear the screen to it + SendToTerminal(clear_screen); +} + +// SET: Call to an external program, optionally forking +int TScreenUNIX::System(const char *command, pid_t *pidChild, int in, + int out, int err) +{ + if (!pidChild) + { + // If the caller asks for redirection replace the requested handles + if (in!=-1) + dup2(in,STDIN_FILENO); + if (out!=-1) + dup2(out,STDOUT_FILENO); + if (err!=-1) + dup2(err,STDERR_FILENO); + return system(command); + } + + pid_t cpid=fork(); + if (cpid==0) + {// Ok, we are the child + // I'm not sure about it, but is the best I have right now. + // Doing it we can kill this child and all the subprocesses + // it creates by killing the group. It also have an interesting + // effect that I must evaluate: By doing it this process lose + // the controlling terminal and won't be able to read/write + // to the parents console. I think that's good. + if (setsid()==-1) + _exit(127); + char *argv[4]; + + // If the caller asks for redirection replace the requested handles + if (in!=-1) + dup2(in,STDIN_FILENO); + if (out!=-1) + dup2(out,STDOUT_FILENO); + if (err!=-1) + dup2(err,STDERR_FILENO); + + argv[0]=newStr(getenv("SHELL")); + if (!argv[0]) + argv[0]=newStr("/bin/sh"); + argv[1]=newStr("-c"); + argv[2]=newStr(command); + argv[3]=NULL; + execvp(argv[0],argv); + delete[] argv[0]; + delete[] argv[1]; + delete[] argv[2]; + // We get here only if exec failed + _exit(127); + } + if (cpid==-1) + {// Fork failed do it manually + *pidChild=0; + return system(command); + } + *pidChild=cpid; + return 0; +} + +#else + +#include +#include +#include +#include + +#endif // TVOS_UNIX && !TVOSf_QNXRtP +/***************************************************************************** + + This code was in the constructor and commented, it could help in the + future. + * ESC ] Ps ND string NP + * ND can be any non-digit Character (it's discarded) + * NP can be any non-printing Character (it's discarded) + * string can be any ASCII printable string (max 511 characters) + * Ps = 0 -> use string as a new icon name and title + * Ps = 1 -> use string is a new icon name only + * Ps = 2 -> use string is a new title only + * Ps = 46 -> use string as a new log file name + if (getenv("DISPLAY") != NULL) cout << "\033]2;TurboVision\007"; + +SET: + Here is some information about the Linux console. I got it from the kernel +sources, they says that's VT102: + +\e(n +Sets the G0 character set. The terminal have 2 character sets, that's the +commonly used. The n value can be: +0 Graphics (DEC ISO 2022) +B Latin 1 (ISO 8859-1) +U IBM PC +K User + +\e)n +It sets what character set is used for G1. That's the alternative charset. + +\xF +Select the G0 charset, don't display control characters. After it all printed +values are in G0 charset. + +\xE +Select the G1 charset, display control characters. After it all printed +values are in G1 charset. Usually it selects the graphics chars. + +\e[10m +Selects G0 or G1 (depending of the last selection done by \xF or \xE), don't +display control characters, don't force the bit 7 to 1. + +\e[11m +Selects IBM PC, display control characters, don't force the bit 7 to 1. + +\e[12m +Selects IBM PC, display control characters, force the bit 7 to 1. + +Description of the available charsets for Linux: +1) Graphics (0): + This is latin 1 charset with some changes in the range 32-126. This charset +is called VT100. Here are the codes that differ from ASCII: + 43(+): Right arrow 109(m): simple lower left corner + 44(,): Left arrow 110(n): simple intersection + 45(-): Up arrow 111(o): first line filled + 46(.): Down arrow 112(p): 1/4 of height line filled + 48(0): Filled block 113(q): 1/2 of height line filled + 95(_): Non break space 114(r): 3/4 of height line filled + 96(`): Diamond 115(s): last line filled + 97(a): 50% filled. 116(t): simple vertical with right int. + 98(b): HT 117(u): simple vertical with left int. + 99(c): FF 118(v): simple horiz. with upper int. +100(d): CR 119(w): simple horiz. with lower int. +101(e): LF 120(x): simple vertical +102(f): Degree 121(y): <= +103(g): +/- 122(z): >= +104(h): 25% filled. 123({): pi +105(i): VT 124(|): /= +106(j): simple lower right corner 125(}): pounds +107(k): simple upper right corner 126(~): middle point +108(l): simple upper left corner + +2) Latin 1 (B): + That's pure ISO 8859-1 mapping. It means 128-159 have undefined shapes. + +3) IBM PC (U): + That's PC 437 code page. Some characters are undefined if the currently +loaded fonts doesn't have it. + +4) User defined (K): + That's just "send to screen this code". So it depends on the loaded fonts. + + Note that 0-31 and 127 are considered control characters and will be printed +only if this is enabled. Some characters aren't printed even if that's +enabled, that's because if they are printed you can't use the terminal +(imagine disabling ESC ;-). + Also: 128+27 will never be printed. + + In Eterm only Graphics (VT100) and Latin 1 are supported. + In xterm a simple program have troubles to print anything above 127. + +*****************************************************************************/ diff --git a/tvision/classes/unix/xtermdis.cc b/tvision/classes/unix/xtermdis.cc new file mode 100644 index 0000000..cdf7b06 --- /dev/null +++ b/tvision/classes/unix/xtermdis.cc @@ -0,0 +1,355 @@ +/***************************************************************************** + + XTerm display routines. + Copyright (c) 2002,2003 by Salvador E. Tropea (SET) + Covered by the GPL license. + + ToDo: + * GetWindowTitle can lock until a key is pressed, shouldn't do it. + +*****************************************************************************/ +#include + +#define Uses_stdio +#define Uses_stdlib +#define Uses_unistd +#define Uses_ioctl +#define Uses_string +#define Uses_TDisplay +#define Uses_TScreen +#define Uses_TGKey +#define Uses_signal +#include + +// I delay the check to generate as much dependencies as possible +#if defined(TVOS_UNIX) && !defined(TVOSf_QNXRtP) + +#include + +#include +#include +#include + +// GNU libc pulls it but other libc implementations just have a forward +// declaration for struct timeval. +#include +// That's a workaround for a bug in the glibc 2.3.2 and 2.3.3: +// The TEMP_FAILURE_RETRY macro uses errno, but errno.h isn't included! +#include +// TEMP_FAILURE_RETRY isn't mandatory. +#ifndef TEMP_FAILURE_RETRY + #define TEMP_FAILURE_RETRY(a) (a) +#endif + +int TDisplayXTerm::curX=0; +int TDisplayXTerm::curY=0; +// Current cursor shape +int TDisplayXTerm::cursorStart=86; // 86 % +int TDisplayXTerm::cursorEnd =99; // 99 % +// 1 when the size of the window where the program is running changed +volatile sig_atomic_t TDisplayXTerm::windowSizeChanged=0; +int TDisplayXTerm::hOut=-1; // Handle for the console output +int TDisplayXTerm::selCharset=0; +int TDisplayXTerm::terminalType=TDisplayXTerm::XTerm; +void (*TDisplayXTerm::ResetPaletteColors)()=ResetPaletteColorsXT; +char TDisplayXTerm::cMap[16]={0,4,2,6,1,5,3,7,8,12,10,14,9,13,11,15}; +unsigned TDisplayXTerm::fontW, + TDisplayXTerm::fontH; +char TDisplayXTerm::fontChanged=0; +uchar TDisplayXTerm::startScreenWidth, + TDisplayXTerm::startScreenHeight; +char *TDisplayXTerm::oldFontName=NULL; +// This is the list of fixed fonts included in XFree86 4.1.0 +TScreenResolution TDisplayXTerm::XFonts[]= +{ + { 5, 7 }, + { 5, 8 }, + { 6,10 }, + { 6,12 }, + { 6,13 }, + { 7,13 }, + { 7,14 }, + { 8,13 }, + { 8,16 }, + { 9,15 }, + { 9,18 }, + { 10,20 }, + { 10,24 } +}; + +// All the code is in TScreenLinux, but this is the right moment, by this +// time TScreenLinux is suspended. +TDisplayXTerm::~TDisplayXTerm() +{ + LOG("TDisplayXTerm Destructor"); + TScreenXTerm::DeallocateResources(); +} + +void TDisplayXTerm::Init() +{ + setCursorPos=SetCursorPos; + getCursorPos=GetCursorPos; + getCursorShape=GetCursorShape; + setCursorShape=SetCursorShape; + + // Check if TIOCGWINSZ works + winsize win; + win.ws_col=0xFFFF; + ioctl(hOut,TIOCGWINSZ,&win); + if ((win.ws_col!=0xFFFF)&&(win.ws_col!=0)) + {// Ok! + getRows=GetRowsIOCTL; + getCols=GetColsIOCTL; + } + else + {// Nope, use Window Manipulation escape sequences + getRows=GetRowsSeq; + getCols=GetColsSeq; + } + checkForWindowSize=CheckForWindowSize; + getWindowTitle=GetWindowTitle; + setWindowTitle=SetWindowTitle; +} + +void TDisplayXTerm::SetCursorPos(unsigned x, unsigned y) +{ + fprintf(stdout,"\E[%d;%dH",y+1,x+1); + curX=x; curY=y; +} + +void TDisplayXTerm::GetCursorPos(unsigned &x, unsigned &y) +{ + fflush(TGKeyXTerm::fIn); + fputs("\E[6n",stdout); + // Is it safe? + int nR,nC; + if (fscanf(TGKeyXTerm::fIn,"\E[%d;%dR",&nR,&nC)==2) + { + curX=nC-1; + curY=nR-1; + } + x=curX; y=curY; +} + +void TDisplayXTerm::SetCursorShape(unsigned start, unsigned end) +{ + LOG("Setting cursor shape to " << start << "," << end); + if (start>=end) + { // Hide cursor DECRST DECTCEM + if (!getShowCursorEver()) + fputs("\E[?25l",stdout); + } + else + { // Show cursor DECSET DECTCEM + fputs("\E[?25h",stdout); + } + cursorStart=start; + cursorEnd=end; +} + +void TDisplayXTerm::GetCursorShape(unsigned &start, unsigned &end) +{ + // Currently we don't know the real state. + start=cursorStart; + end =cursorEnd; +} + +ushort TDisplayXTerm::GetRowsIOCTL() +{ + winsize win; + ioctl(hOut,TIOCGWINSZ,&win); + + return win.ws_row; +} + +ushort TDisplayXTerm::GetRowsSeq() +{ + fputs("\E[18t",stdout); + int nR,nC; + if (fscanf(TGKeyXTerm::fIn,"\E[8;%d;%dt",&nR,&nC)==2) + return nR; + return 25; +} + +ushort TDisplayXTerm::GetColsIOCTL() +{ + winsize win; + + ioctl(hOut,TIOCGWINSZ,&win); + LOG("GetColsIOCTL() " << win.ws_col); + return win.ws_col; +} + +ushort TDisplayXTerm::GetColsSeq() +{ + fputs("\E[18t",stdout); + int nR,nC; + if (fscanf(TGKeyXTerm::fIn,"\E[8;%d;%dt",&nR,&nC)==2) + return nC; + return 80; +} + +int TDisplayXTerm::CheckForWindowSize(void) +{ + int ret=windowSizeChanged!=0; + windowSizeChanged=0; + return ret; +} + +const char *TDisplayXTerm::GetWindowTitle(void) +{ + char buffer[256]; // Put a max. + fputs("\E[21t",stdout); + + // Nasty: + // Lamentably Xterm doesn't return it immediately + fd_set set; + struct timeval timeout; + int ret; + + FD_ZERO(&set); + FD_SET(TGKeyXTerm::hIn,&set); + timeout.tv_sec=0; + timeout.tv_usec=300000; + ret=TEMP_FAILURE_RETRY(select(FD_SETSIZE,&set,NULL,NULL,&timeout)); + // Note: As this feature was reported as potentially exploitable now most + // XTerms just ignores this request. So if after 300 ms we didn't get an + // answer we assume the XTerm won't reply and report empty title. + if (!ret) + return newStr(""); + fgets(buffer,255,TGKeyXTerm::fIn); + buffer[255]=0; + // OSC l Name ST (\E]lName\E\\) + if (buffer[0]!=27 || buffer[1]!=']' || buffer[2]!='l') + return NULL; + // Convert it into something the application can use for other things, not + // only for restoring. Read: get rid of the EOS. + char *end=strstr(buffer,"\E\\"); + if (end) *end=0; + return newStr(buffer+3); +} + +int TDisplayXTerm::SetWindowTitle(const char *name) +{ + if (terminalType==Eterm) + fprintf(stdout,"\E]2;%s\x7",name); // BEL is the string terminator + else + fprintf(stdout,"\E]2;%s\E\\",name); // \E\\ is the string terminator + return 1; +} + +/* + Important note about palette: + Only XTerm from X 4.x and Eterm 0.9.x supports the palette manipulation. + As we don't have an easy way to determine the version of the terminal we +are using this escape sequence must be "neutral". + The problem is that both terminals have problems with it. For this reason +I added a Shift In (^O=\xF) to the sequence. When the sequence is +interpreted this SI is executed and that's why I restore the value at the +end (if (selCharset) ...). If the sequence isn't interpreted the SI finishes +the sequence and the rest is discarded. In this way we don't mess the +terminal state. +*/ +// XTerm code +int TDisplayXTerm::SetDisPaletteColorsXT(int from, int number, TScreenColor *colors) +{ + // Assume all will be ok + int ret=number; + fputs("\E]4",stdout); + while (number-- && from<16) + { + fprintf(stdout,";%d;#%2.2X%2.2X%2.2X",cMap[from++],colors->R,colors->G,colors->B); + colors++; + } + fputc(7,stdout); + return ret; +} + +void TDisplayXTerm::ResetPaletteColorsXT() +{// Just setup a default palette + SetDisPaletteColorsXT(0,16,PC_BIOSPalette); +} + +// Eterm code, Linux console style +int TDisplayXTerm::SetDisPaletteColorsEt(int from, int number, TScreenColor *colors) +{ + // Assume all will be ok + int ret=number; + while (number-- && from<16) + { + fprintf(stdout,"\E]P%1.1X%2.2X%2.2X%2.2X\xF",cMap[from++],colors->R,colors->G,colors->B); + colors++; + } + if (selCharset) + fputc(14,stdout); + return ret; +} + +void TDisplayXTerm::ResetPaletteColorsEt() +{ + fputs("\E]R",stdout); +} + +// This is supported only by XTerm +char *TDisplayXTerm::GetCurrentFontName() +{ + if (terminalType==Eterm) return NULL; + char fontNameAux[84]; + fputs("\E]50;?\x7",stdout); + if (fscanf(TGKeyXTerm::fIn,"\E]50;%80[^\x7]\x7",fontNameAux)==1) + return newStr(fontNameAux); + return NULL; +} + +int TDisplayXTerm::SetCrtModeXT(unsigned w, unsigned h, int fW, int fH) +{ + const unsigned XFontsCant=sizeof(XFonts)/sizeof(TScreenResolution); + int fontOK=1, setFont=0; + unsigned whichFont; + if (fW!=-1 || fH!=-1) + {// This is all a guess, I took the GNU/Debian Woody configuration as base. + // That's XFree86 4.1.0 + if (fW==-1) fW=fontW; + if (fH==-1) fH=fontH; + if ((unsigned)fW!=fontW || (unsigned)fH!=fontH) + { + setFont=1; + if (!searchClosestRes(XFonts,fW,fH,XFontsCant,whichFont)) + fontOK=0; + fontW=XFonts[whichFont].x; + fontH=XFonts[whichFont].y; + } + } + + if (TScreen::screenBuffer) + DeleteArray(TScreen::screenBuffer); + TScreen::screenBuffer=new ushort[w*h]; + fprintf(stdout,"\E[8;%d;%dt",h,w); + + if (setFont) + { + if (!fontChanged) + {// Memorize current font + oldFontName=GetCurrentFontName(); + fontChanged=oldFontName!=NULL; + } + fprintf(stdout,"\E]50;%dx%d\x7",fontW,fontH); + } + // Ensure that's done before returning. I get wrong width from the IOCTL + // if I don't flush and ask quickly. + fflush(stdout); + return fontOK ? 1 : 2; +} + +int TDisplayXTerm::SetCrtModeEt(unsigned w, unsigned h, int fW, int fH) +{ + return SetCrtModeXT(w,h+1,fW,fH); +} +#else + +#include +#include +#include + +#endif // TVOS_UNIX && !TVOSf_QNXRtP + diff --git a/tvision/classes/unix/xtermkey.cc b/tvision/classes/unix/xtermkey.cc new file mode 100644 index 0000000..546c11e --- /dev/null +++ b/tvision/classes/unix/xtermkey.cc @@ -0,0 +1,889 @@ +/***************************************************************************** + + XTerm keyboard routines. + Copyright (c) 2002,2003 by Salvador E. Tropea (SET) + Covered by the GPL license. + + Module: XTerm Keyboard + Comments: + This driver is a relatively complex one because:@* + 1) Deals with console mode.@* + 2) Translates keyboard codes.@* + 3) Parses escape sequences.@* + @p + + TODO:@* + * Move the code that overlaps with Linux driver to a base class. Lets say + TGKeyEscapeSequences.@* + * When the list is big (>8?) us bsearch@* + * Allow changing MIN and TIME termios values for slow connections.@* + +*****************************************************************************/ +#include + +#define Uses_stdio +#define Uses_string +#define Uses_stdlib +#define Uses_unistd +#define Uses_ioctl +#define Uses_TEvent +#define Uses_TGKey +#define Uses_FullSingleKeySymbols +#include + +// I delay the check to generate as much dependencies as possible +#if defined(TVOS_UNIX) && !defined(TVOSf_QNXRtP) + +#include +#include + +#include +#include + +int TGKeyXTerm::hIn=-1; +FILE *TGKeyXTerm::fIn=NULL; +int TGKeyXTerm::oldInFlags; +int TGKeyXTerm::newInFlags; +struct termios TGKeyXTerm::inTermiosOrig; +struct termios TGKeyXTerm::inTermiosNew; +const char *TGKeyXTerm::error=NULL; +int TGKeyXTerm::bufferKeys[MaxLenEscapeSequence]; +int TGKeyXTerm::keysInBuffer=0; +int TGKeyXTerm::nextKey=-1; +int TGKeyXTerm::lastKeyCode; +int TGKeyXTerm::lastModifiers; +int TGKeyXTerm::translatedModifiers; +char TGKeyXTerm::ascii; +node *TGKeyXTerm::Keys=NULL; +int TGKeyXTerm::MouseButtons=0; + +/* Linux IOCTL values found experimentally */ +const int kblNormal=0,kblShift=1,kblAltR=2,kblCtrl=4,kblAltL=8; + +/**[txh]******************************************************************** + + Description: + Does initialization tasks performed only once. + + Return: + 0 if success, !=0 if an error ocurred. In the last case the error member +points to a descriptive error. + +***************************************************************************/ + +int TGKeyXTerm::InitOnce() +{ + LOG("TGKeyXTerm::InitOnce"); + hIn=fileno(stdin); + + if (!isatty(hIn)) + { + error=_("that's an interactive application, don't redirect stdin"); + return 1; + } + + char *ttyName=ttyname(hIn); + if (!ttyName) + { + error=_("failed to get the name of the current terminal used for input"); + return 3; + } + fIn=fopen(ttyName,"r+b"); + if (!fIn) + { + error=_("failed to open the input terminal"); + return 4; + } + hIn=fileno(fIn); + + if (tcgetattr(hIn,&inTermiosOrig)) + { + error=_("can't get input terminal attributes"); + return 2; + } + + memcpy(&inTermiosNew,&inTermiosOrig,sizeof(inTermiosNew)); + // Ignore breaks + inTermiosNew.c_iflag|= (IGNBRK | BRKINT); + // Disable Xon/off + inTermiosNew.c_iflag&= ~(IXOFF | IXON); + // Character oriented, no echo, no signals + inTermiosNew.c_lflag&= ~(ICANON | ECHO | ISIG); + + // The following are needed for Solaris. In 2.7 MIN is 4 and TIME 0 + // making things really annoying. In the future they could be driver + // variables to make the use of bandwidth smaller. A value of 4 and 1 looks + // usable. I verified that Solaris 9 (2.9) also uses 4/0. + // + // *BSD systems seems interpret 0/0 value in a different way and they need + // 1/0 in order work properly (otherwise blocks forever). I verified that + // 1/0 works for OpenBSD 3.4, FreeBSD 4.8 and NetBSD 1.6.1. All of them uses + // 1/0 as default, Linux also does it. + inTermiosNew.c_cc[VMIN]=1; + inTermiosNew.c_cc[VTIME]=0; // No timeout, just don't block + if (tcsetattr(hIn,TCSAFLUSH,&inTermiosNew)) + { + error=_("can't set input terminal attributes"); + return 3; + } + // Don't block + oldInFlags=fcntl(hIn,F_GETFL,0); + newInFlags=oldInFlags | O_NONBLOCK; + fcntl(hIn,F_SETFL,newInFlags); + + // We don't need to call Resume + suspended=0; + return 0; +} + +/**[txh]******************************************************************** + + Description: + Restore the original console state. + +***************************************************************************/ + +void TGKeyXTerm::Suspend() +{ + fcntl(hIn,F_SETFL,oldInFlags); + tcsetattr(hIn,TCSAFLUSH,&inTermiosOrig); + LOG("TGKeyXTerm::Suspend"); +} + +/**[txh]******************************************************************** + + Description: + Memorize current console state and setup the one needed for us. + +***************************************************************************/ + +void TGKeyXTerm::Resume() +{// Read current state + tcgetattr(hIn,&inTermiosOrig); + oldInFlags=fcntl(hIn,F_GETFL,0); + // Set our state + tcsetattr(hIn,TCSAFLUSH,&inTermiosNew); + fcntl(hIn,F_SETFL,newInFlags); + LOG("TGKeyXTerm::Resume"); +} + +int TGKeyXTerm::KbHit() +{ + if (keysInBuffer || nextKey!=-1) + return 1; // We have a key waiting for processing + nextKey=fgetc(fIn); + return nextKey!=-1; +} + +void TGKeyXTerm::Clear() +{ + // Discard our buffer + keysInBuffer=0; + // Discard a key waiting + nextKey=-1; + // Flush the input + fflush(fIn); +} + +/***************************************************************************** + + Here starts the keyboard parser and translator. + It uses a static tree/hash to parse the escape sequences, may be this should +be configurable. + +*****************************************************************************/ + +// - 9 = Tab tiene conflicto con kbI+Control lo cual es natural, por otro +// -lado Ctrl+Tab no lo reporta en forma natural +// - a = Enter tiene conflicto con ^J, como ^J no lo reporta naturalmente sino +// -forzado por el keymap lo mejor es definirlo directamente. +unsigned char TGKeyXTerm::kbToName[128] = +{ + 0,kbA,kbB,kbC,kbD,kbE,kbF,kbG, // 00-07 + kbH,kbTab,kbEnter,kbK,kbL,kbM,kbN,kbO, // 08-0F + kbP,kbQ,kbR,kbS,kbT,kbU,kbV,kbW, // 10-17 + kbX,kbY,kbZ,kbEsc,0,kbCloseBrace,kb6,kbMinus, // 18-1F + kbSpace,kbAdmid,kbDobleQuote,kbNumeral,kbDolar,kbPercent,kbAmper,kbQuote,// 20-27 + kbOpenPar,kbClosePar,kbAsterisk,kbPlus,kbComma,kbMinus,kbStop,kbSlash, // 28-2F + kb0,kb1,kb2,kb3,kb4,kb5,kb6,kb7, // 30-37 + kb8,kb9,kbDoubleDot,kbColon,kbLessThan,kbEqual,kbGreaterThan,kbQuestion, // 38-3F + kbA_Roba,kbA,kbB,kbC,kbD,kbE,kbF,kbG, // 40-47 + kbH,kbI,kbJ,kbK,kbL,kbM,kbN,kbO, // 48-4F + kbP,kbQ,kbR,kbS,kbT,kbU,kbV,kbW, // 50-57 + kbX,kbY,kbZ,kbOpenBrace,kbBackSlash,kbCloseBrace,kbCaret,kbUnderLine, // 58-5F + kbGrave,kbA,kbB,kbC,kbD,kbE,kbF,kbG, // 60-67 + kbH,kbI,kbJ,kbK,kbL,kbM,kbN,kbO, // 68-6F + kbP,kbQ,kbR,kbS,kbT,kbU,kbV,kbW, // 70-77 + kbX,kbY,kbZ,kbOpenCurly,kbOr,kbCloseCurly,kbTilde,kbBackSpace // 78-7F +}; + +unsigned char TGKeyXTerm::kbExtraFlags[128] = +{ + 0,kblCtrl,kblCtrl,kblCtrl,kblCtrl,kblCtrl,kblCtrl,kblCtrl, // 00-07 + kblCtrl,0,0,kblCtrl,kblCtrl,kblCtrl,kblCtrl,kblCtrl, // 08-0F + kblCtrl,kblCtrl,kblCtrl,kblCtrl,kblCtrl,kblCtrl,kblCtrl,kblCtrl, // 10-17 + kblCtrl,kblCtrl,kblCtrl,0,0,kblCtrl,kblCtrl,kblCtrl, // 18-1F + 0,kblShift,kblShift,kblShift,kblShift,kblShift,kblShift,0, // 20-27 + kblShift,kblShift,kblShift,kblShift,0,0,0,0, // 28-2F + 0,0,0,0,0,0,0,0, // 30-37 + 0,0,kblShift,0,kblShift,0,kblShift,kblShift, // 38-3F + kblShift,kblShift,kblShift,kblShift,kblShift,kblShift,kblShift,kblShift, // 40-47 + kblShift,kblShift,kblShift,kblShift,kblShift,kblShift,kblShift,kblShift, // 48-4F + kblShift,kblShift,kblShift,kblShift,kblShift,kblShift,kblShift,kblShift, // 50-57 + kblShift,kblShift,kblShift,0,0,0,kblShift,kblShift, // 58-5F + 0,0,0,0,0,0,0,0, // 60-67 + 0,0,0,0,0,0,0,0, // 68-6F + 0,0,0,0,0,0,0,0, // 70-77 + 0,0,0,kblShift,kblShift,kblShift,kblShift,0, // 78-7F +}; + +/************************** Escape sequences tree **************************/ +struct node +{ + union + { + char value; + char keys; + }; + uchar code; + uchar modifiers; + node *next; +}; + +// This is how Xterm usually encodes the modifiers +static +uchar xtMods[7]= +{ + kblShift, // 2 + kblAltL, // 3 + kblShift | kblAltL, // 4 + kblCtrl, // 5 + kblShift | kblCtrl, // 6 + kblCtrl | kblAltL, // 7 + kblShift | kblCtrl | kblAltL // 8 +}; + +const uchar fgEterm=1, fgOnlyEterm=2; +typedef struct +{ + uchar number; + uchar code; +} stCsiKey; + +typedef struct +{ + uchar number; + uchar code; + uchar mods; +} stEtKey; + +// CSI Number ; Modifiers ~ +const int cCsiKeys1=16; +static +stCsiKey csiKeys1[cCsiKeys1]= +{ + { 1, kbHome }, // Putty + { 2, kbInsert }, + { 3, kbDelete }, + { 4, kbEnd }, // Putty + { 5, kbPgUp }, // Prior + { 6, kbPgDn }, // Next + { 7, kbHome }, + { 8, kbEnd }, + { 15, kbF5 }, + { 17, kbF6 }, + { 18, kbF7 }, + { 19, kbF8 }, + { 20, kbF9 }, + { 21, kbF10 }, + { 23, kbF11 }, + { 24, kbF12 } +}; + +static +uchar csiFgKeys1[]= +{ + fgEterm,fgEterm,fgEterm,fgEterm, + fgOnlyEterm|fgEterm,fgOnlyEterm|fgEterm, // Home & End + 0,0,0,0,0,0,0,0 +}; + +// CSI Modifiers Letter +const int cCsiKeys2=9; +static +stCsiKey csiKeys2[cCsiKeys2]= +{ + { 'A', kbUp }, + { 'B', kbDown }, + { 'C', kbRight }, + { 'D', kbLeft }, + { 'E', kb5 }, // Key pad 5 + { 'F', kbEnd }, + { 'H', kbHome }, + { 'K', kbBackSpace }, // SET extension ;-) + { 'T', kbTab } // SET extension ;-) +}; + +// Modifiers O Letter +const int cCsiKeys3=4; +static +stCsiKey csiKeys3[cCsiKeys3]= +{ + { 'P', kbF1 }, + { 'Q', kbF2 }, + { 'R', kbF3 }, + { 'S', kbF4 } +}; + +// Eterm: O Letter and Application mode +const int cCsiKeys4=26; +static +stEtKey csiKeys4[cCsiKeys4]= +{ + { 'a', kbUp, kblCtrl }, + { 'b', kbDown, kblCtrl }, + { 'c', kbRight, kblCtrl }, + { 'd', kbLeft, kblCtrl }, + { 'A', kbUp, 0 }, + { 'B', kbDown, 0 }, + { 'C', kbRight, 0 }, + { 'D', kbLeft, 0 }, + { 'F', kbEnd, 0 }, + { 'H', kbHome, 0 }, + // Keypad + { 'M', kbEnter, 0 }, + { 'j', kbAsterisk, 0 }, + { 'k', kbPlus, 0 }, + { 'm', kbMinus, 0 }, + { 'n', kbDelete, 0 }, + { 'o', kbSlash, 0 }, + { 'p', kbInsert, 0 }, + { 'q', kbEnd, 0 }, + { 'r', kbDown, 0 }, + { 's', kbPgDn, 0 }, + { 't', kbLeft, 0 }, + { 'u', kb5, 0 }, + { 'v', kbRight, 0 }, + { 'w', kbHome, 0 }, + { 'x', kbUp, 0 }, + { 'y', kbPgUp, 0 } +}; + +node *TGKeyXTerm::NewNode() +{ + node *ret=(node *)malloc(sizeof(node)); + ret->keys=0; + return ret; +} + +node *TGKeyXTerm::NewNode(node *p) +{ + node *ret=(node *)malloc(sizeof(node)*2); + ret->keys=1; + ret[1]=*p; + return ret; +} + +node *TGKeyXTerm::SearchInList(node *p, uchar k) +{ + if (p->keys==0) return NULL; // No keys + int i,c=p->keys; + for (i=1; i<=c; i++) + if (p[i].value==k) + return p+i; + return NULL; // Not found +} + +node *TGKeyXTerm::AddKey2List(node *p, uchar k, node **pa) +{ + int i=1,c=p->keys; + while (i<=c && p->valuekeys++; + return p+i; +} + +void TGKeyXTerm::AddKey(const uchar *key, uchar code, uchar modifiers) +{ + if (!Keys) + Keys=NewNode(); + node *p=Keys,*pk,**pa=&Keys; + const uchar *s=key; + + while (*s) + { + pk=SearchInList(p,*s); + if (!pk) + {// Not in the list + pk=AddKey2List(p,*s,pa); + if (*(s+1)) + {// New ramification + p=NewNode(); + pk->next=p; + pa=&(pk->next); + } + else + {// Just new key + pk->next=NULL; + pk->code=code; + pk->modifiers=modifiers; + } + } + else + {// Already in the list + if (*(s+1)) + {// It isn't the end, what is currently there? + if (!pk->next) + {// We have a key, so we must ramify without losing it + pk->next=NewNode(pk); + } + pa=&(pk->next); + p=pk->next; + } + else + { + if (pk->next) + LOG("Error, this key is confusing"); + else + LOG("Warning, this key was already defined [" << key << "]"); + } + } + s++; + } +} + +#ifdef DEBUGTREE +static +int maxKeys=0; + +static +void Indent(int level) +{ + while (level--) + fputc(' ',stderr); +} + +static +void PrintTree(node *p, int level) +{ + int i,c; + + c=p->keys; + Indent(level); + fprintf(stderr,"Keys: %d\n",c); + if (c>maxKeys) + maxKeys=c; + for (i=1; i<=c; i++) + { + Indent(level); + fprintf(stderr,"Key %c ",p[i].value); + if (p[i].next) + { + Indent(level); + fprintf(stderr,"Ramification\n"); + PrintTree(p[i].next,level+1); + } + else + { + Indent(level); + fprintf(stderr,"KeyCode %s\n",TGKey::NumberToKeyName(p[i].code)); + } + } + if (level==0) + fprintf(stderr,"Max keys: %d\n",maxKeys); +} +#else + #define PrintTree(a,b) +#endif + +void TGKeyXTerm::PopulateTree() +{ + int i,j; + char b[MaxLenEscapeSequence]; + + for (i=0; i Alt/Meta + Escape sequence + extraModifiers=0; + if (nextVal=='\e') + { + extraModifiers=kblAltL; + nextVal=fgetc(fIn); + if (nextVal==EOF) // Just Alt+ESC + { + lastModifiers=kblAltL; + return 0; + } + } + + node *p=Keys; + int cant,i; + keysInBuffer=0; + while (nextVal!=EOF) + { + NextNode: + bufferKeys[keysInBuffer++]=nextVal; + cant=p->value; + for (i=1; i<=cant; i++) + { + if (p[i].value==nextVal) + { + if (p[i].next) + { + p=p[i].next; + nextVal=fgetc(fIn); + goto NextNode; + } + lastKeyCode=p[i].code; + lastModifiers=p[i].modifiers | extraModifiers; + bufferKeys[keysInBuffer]=0; + keysInBuffer=0; + return 1; + } + } + return 0; + } + return 0; +} + +int TGKeyXTerm::GetKeyFromBuffer() +{ + int ret=bufferKeys[--keysInBuffer]; + if (keysInBuffer) + memcpy(bufferKeys,bufferKeys+1,keysInBuffer); + return ret; +} + +/**[txh]******************************************************************** + + Description: + Gets a key from the buffer, waiting value or fIn and if needed calls +the escape sequence parser. + +***************************************************************************/ + +int TGKeyXTerm::GetKeyParsed() +{ + lastModifiers=0; + translatedModifiers=-1; + // If we have keys in the buffer take from there. + // They already failed the escape sequence test. + if (keysInBuffer) + return GetKeyFromBuffer(); + + // Use the value we have on hold or get a new one + int nextVal=nextKey; + nextKey=-1; + if (nextVal==-1) + nextVal=fgetc(fIn); + if (nextVal==-1) + return -1; + + // Is that an escape sequence? + if (nextVal=='\e') + { + if (ProcessEscape()) + return -2; + if (!keysInBuffer) + return '\e'; + lastKeyCode=GetKeyFromBuffer(); + lastModifiers=kblAltL; + return -3; + } + + return nextVal; +} + +/**[txh]******************************************************************** + + Description: + Gets the next key, their modifiers and ASCII. Is a postprocessor for +GetKeyParsed. + +***************************************************************************/ + +int TGKeyXTerm::GetRaw() +{ + int result=GetKeyParsed(); + + if (result==-1) + return 0; // No key + if (result==-2) + { + ascii=0; + return 1; // Key already processed + } + if (result==-3) // Forced modifier + result=lastKeyCode; + + ascii=result; + // Translate the key + if (result>=128) + lastKeyCode=kbUnkNown; + else + { + lastModifiers|=kbExtraFlags[result]; + lastKeyCode=kbToName[result]; + } + return 1; +} + +/**[txh]******************************************************************** + + Description: + Gets a key from the input and converts it into the TV format. + +***************************************************************************/ + +ushort TGKeyXTerm::GKey() +{ + if (GetRaw()) + { // Here I add the modifiers to the key code + if (lastModifiers & kblShift) + lastKeyCode|=kbShiftCode; + if (lastModifiers & kblCtrl) + lastKeyCode|=kbCtrlCode; + switch (AltSet) + { + case 1: // Reverse thing + if (lastModifiers & kblAltL) + lastKeyCode|=kbAltRCode; + break; + default: // Compatibility + if (lastModifiers & kblAltL) + lastKeyCode|=kbAltLCode; + } + return lastKeyCode; + } + return kbUnkNown; +} +/***************************************************************************** + End of parser and translator. +*****************************************************************************/ + +/**[txh]******************************************************************** + + Description: + Finds the value of the modifiers in TV format. + +***************************************************************************/ + +unsigned TGKeyXTerm::GetShiftState() +{ + if (!lastModifiers) return 0; + if (translatedModifiers==-1) + { + translatedModifiers=0; + if (lastModifiers & kblShift) + translatedModifiers|=kbLeftShiftDown | kbRightShiftDown; + if (lastModifiers & kblCtrl) + translatedModifiers|=kbLeftCtrlDown | kbRightCtrlDown | kbCtrlDown; + if (lastModifiers & kblAltL) + translatedModifiers|=kbLeftAltDown | kbAltDown; + } + return translatedModifiers; +} + +const int MouseB1Down=0x20,MouseB2Down=0x21,MouseB3Down=0x22,MouseUp=0x23, + MouseB4Down=0x60,MouseB5Down=0x61; + +/**[txh]******************************************************************** + + Description: + Fills the TV event structure for a key. + +***************************************************************************/ + +void TGKeyXTerm::FillTEvent(TEvent &e) +{ + GKey(); + if ((lastKeyCode & kbKeyMask)==kbMouse) + { // Mouse events are traslated to keyboard sequences: + int event=fgetc(fIn); + int x=fgetc(fIn)-0x21; // They are 0x20+ and the corner is 1,1 + int y=fgetc(fIn)-0x21; + // Filter the modifiers: + event&= ~0x1C; + // B4 and B5 behaves in a particular way + MouseButtons&= ~(MouseB4Down | MouseB5Down); + if (event>=0x60) + {// B4 and B5, they seems to report a press and never a release + if (event==MouseB4Down) + MouseButtons|=mbButton4; + else + if (event==MouseB5Down) + MouseButtons|=mbButton5; + } + else + { + if (event>=0x40) event-=0x20; // Translate motion values + switch (event) + { + case MouseB1Down: + MouseButtons|=mbLeftButton; + break; + case MouseB2Down: + MouseButtons|=mbMiddleButton; + break; + case MouseB3Down: + MouseButtons|=mbRightButton; + break; + case MouseUp: // fuzzy, which one? + MouseButtons=0; + break; + } + } + THWMouse::forceEvent(x,y,MouseButtons); + e.what=evMouseUp; // Acts like a "key" + return; + } + + e.keyDown.charScan.charCode=lastModifiers & kblAltL ? 0 : ascii; + e.keyDown.charScan.scanCode=ascii; + e.keyDown.raw_scanCode=ascii; + e.keyDown.keyCode=lastKeyCode; + e.keyDown.shiftState=lastModifiers; + e.what=evKeyDown; +} + +void TGKeyXTerm::Init() +{ + TGKey::Suspend =TGKeyXTerm::Suspend; + TGKey::Resume =TGKeyXTerm::Resume; + TGKey::kbhit =KbHit; + TGKey::clear =Clear; + TGKey::gkey =GKey; + TGKey::getShiftState=GetShiftState; + TGKey::fillTEvent =FillTEvent; + if (Keys==NULL) + PopulateTree(); +} + +#else // TVOS_UNIX && !TVOSf_QNXRtP + +#include +#include + +#endif // else TVOS_UNIX && !TVOSf_QNXRtP diff --git a/tvision/classes/unix/xtermmouse.cc b/tvision/classes/unix/xtermmouse.cc new file mode 100644 index 0000000..d4d2d85 --- /dev/null +++ b/tvision/classes/unix/xtermmouse.cc @@ -0,0 +1,93 @@ +/***************************************************************************** + + XTerm mouse routines. + Copyright (c) 2002 by Salvador E. Tropea (SET) + Covered by the GPL license. + + This driver is a little bit different than THWMouseXTerm because: + 1) Is specifically used with TScreenXTerm. + 2) Uses a finer reporting mechanism. + 3) TScreenXTerm::SendToTerminal doesn't exist. + + TODO: + Why save/restore fails in Eterm? + Bug Eterm people to get 1002 ;-) + +*****************************************************************************/ +#include + +#define Uses_stdio +#define Uses_TEvent +#define Uses_TEventQueue +#define Uses_TScreen +#include + +// I delay the check to generate as much dependencies as possible +#if defined(TVOS_UNIX) && !defined(TVOSf_QNXRtP) + +#include +#include +#include + +int THWMouseXTermFull::mode=modeEterm; + +void THWMouseXTermFull::ResumeFull() +{ + buttonCount=5; // X uses at least 3 buttons, but 5 can be reported + // Save old hilit tracking and enable mouse tracking + // 1002 == Use Cell Motion Mouse Tracking. + fprintf(stdout,"\E[?1002s\E[?1002h"); + show(); + LOG("XTerm mouse enabled (full)"); +} + +void THWMouseXTermFull::SuspendFull() +{ + // Disable mouse tracking and restore old hilittracking + fprintf(stdout,"\E[?1002l\E[?1002r"); + LOG("XTerm mouse disabled (full)"); +} + +void THWMouseXTermFull::ResumeSimple() +{ + buttonCount=5; // X uses at least 3 buttons, but 5 can be reported + //fprintf(stdout,"\E[?1000s\E[?1000h"); + fprintf(stdout,"\E[?1000h"); + show(); + LOG("XTerm mouse enabled (simple)"); +} + +void THWMouseXTermFull::SuspendSimple() +{ + // Disable mouse tracking and restore old hilittracking + //fprintf(stdout,"\E[?1000l\E[?1000r"); Is Eterm broken or is just me? + fprintf(stdout,"\E[?1000l"); + LOG("XTerm mouse disabled (simple)"); +} + +void THWMouseXTermFull::Init(int aMode) +{ + THWMouseUNIX::Init(); + mode=aMode; + if (mode==modeXTerm) + { + THWMouse::Resume=ResumeFull; + THWMouse::Suspend=SuspendFull; + } + else + { + THWMouse::Resume=ResumeSimple; + THWMouse::Suspend=SuspendSimple; + } +} + +THWMouseXTermFull::~THWMouseXTermFull() +{ +} +#else // TVOS_UNIX && !TVOSf_QNXRtP + +#include +#include +#include + +#endif // else TVOS_UNIX && !TVOSf_QNXRtP diff --git a/tvision/classes/unix/xtermscr.cc b/tvision/classes/unix/xtermscr.cc new file mode 100644 index 0000000..9a5dbac --- /dev/null +++ b/tvision/classes/unix/xtermscr.cc @@ -0,0 +1,952 @@ +/***************************************************************************** + + Linux screen routines. + Copyright (c) 2002 by Salvador E. Tropea (SET) + Covered by the GPL license. + + Configuration variables: + ScreenWidth + ScreenHeight + ScreenPalette + FontWidth + FontHeight + AppCP + ScrCP + InpCP + UseShellScreen + +*****************************************************************************/ +#include + +#define Uses_TScreen +#define Uses_TEvent +#define Uses_TDrawBuffer +#define Uses_TGKey +#define Uses_TVCodePage +#define Uses_string +#define Uses_ctype +#define Uses_signal +#define Uses_stdio +#define Uses_stdlib +#include + +// I delay the check to generate as much dependencies as possible +#if defined(TVOS_UNIX) && !defined(TVOSf_QNXRtP) + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +struct termios TScreenXTerm::outTermiosOrig; +struct termios TScreenXTerm::outTermiosNew; +const char *TScreenXTerm::error=NULL; +int TScreenXTerm::palette; +int TScreenXTerm::oldCol=-1, + TScreenXTerm::oldBack=-1, + TScreenXTerm::oldFore=-1; +char TScreenXTerm::useShellScreen=0; + +#define force_redraw 0 + +TScreen *TV_XTermDriverCheck() +{ + TScreenXTerm *drv=new TScreenXTerm(); + if (!TScreen::initialized) + { + delete drv; + return 0; + } + return drv; +} + +void TScreenXTerm::sigWindowSizeChanged(int sig) +{ + // Set a flag because we don't know if we can do it right now + TScreenXTerm::windowSizeChanged=1; + signal(sig,sigWindowSizeChanged); +} + +void TScreenXTerm::Init() +{ + TScreen::Resume=Resume; + TScreen::Suspend=Suspend; + TScreen::setCrtData=defaultSetCrtData; + TScreen::setVideoMode=SetVideoMode; + TScreen::setVideoModeExt=SetVideoModeExt; + TScreen::setCharacter=SetCharacter; + TScreen::System_p=System; + TScreen::setCharacters=SetCharacters; + TDisplay::checkForWindowSize=CheckForWindowSize; +} + + +int TScreenXTerm::InitOnce() +{ + LOG("TScreenXTerm::InitOnce"); + hOut=fileno(stdout); + // SET: Original code tried to open a tty at any cost, eg: if stdout was + // redirected it tried to open stdin's tty for writing. I don't see the + // point of such an effort and in fact crashes the library, so here I just + // explain to the user how to run the application in the right way. + if (!isatty(hOut)) + { + error=_("that's an interactive application, don't redirect stdout. " + "If you want to collect information redirect stderr like this: " + "program 2> file"); + return 1; + } + + if (tcgetattr(hOut,&outTermiosOrig)) + { + error=_("can't get output terminal information"); + return 2; + } + + // Save cursor position, attributes and charset + fputs("\E7",stdout); + memcpy(&outTermiosNew,&outTermiosOrig,sizeof(outTermiosNew)); + outTermiosNew.c_oflag|=OPOST; + if (tcsetattr(hOut,TCSAFLUSH,&outTermiosNew)) + { + error=_("can't configure terminal mode"); + return 3; + } + + // Impossible to know the actual palette, just assume a default + memcpy(OriginalPalette,PC_BIOSPalette,sizeof(OriginalPalette)); + memcpy(ActualPalette,PC_BIOSPalette,sizeof(ActualPalette)); + + // Setup the driver properties. + // We can change the palette (but can't restore it perfectly). + // I assume that's XTerm 4.x or Eterm 0.9.x, this doesn't work + // for older versions. + flags0=CanSetPalette | CanSetVideoSize; + return 0; +} + + +TScreenXTerm::TScreenXTerm() +{ + // Identify the terminal, if that's XTerm or Eterm go on. + char *terminal=getenv("TERM"); + if (!terminal || !(!strncmp(terminal,"xterm",5) || !strncasecmp(terminal,"Eterm",5))) + return; + + if (!strncasecmp(terminal,"Eterm",5)) + terminalType=Eterm; + + // Initialize terminal + if (InitOnce()) + { + fprintf(stderr,_("Error! %s"),error); + fprintf(stderr,"\r\n"); + return; + } + // Initialize keyboard + if (TGKeyXTerm::InitOnce()) + { + tcsetattr(hOut,TCSAFLUSH,&outTermiosOrig); + fprintf(stderr,_("Error! %s"),TGKeyXTerm::error); + fprintf(stderr,"\r\n"); + return; + } + // Ok, if we are here this driver is usable. + initialized=1; + if (dCB) dCB(); + + // Don't need special rights anymore + seteuid(getuid()); + setegid(getgid()); + + // Hook the signal generated when the size of the window changes + signal(SIGWINCH,sigWindowSizeChanged); + + TDisplayXTerm::Init(); + Init(); + + TGKeyXTerm::Init(); + + long aux; + if (optSearch("UseShellScreen",aux)) + useShellScreen=aux; + + // Code page initialization + // Look for user settings + optSearch("AppCP",forcedAppCP); + optSearch("ScrCP",forcedScrCP); + optSearch("InpCP",forcedInpCP); + // User settings have more priority than detected settings + codePage=new TVCodePage(forcedAppCP!=-1 ? forcedAppCP : TVCodePage::ISOLatin1Linux, + forcedScrCP!=-1 ? forcedScrCP : TVCodePage::ISOLatin1Linux, + forcedInpCP!=-1 ? forcedInpCP : TVCodePage::ISOLatin1Linux); + SetDefaultCodePages(TVCodePage::ISOLatin1Linux,TVCodePage::ISOLatin1Linux, + TVCodePage::ISOLatin1Linux); + + if (terminalType==Eterm) + {// Only 8 colors + brightness (8*2+8*2) + palette=PAL_LOW; + THWMouseXTermFull::Init(THWMouseXTermFull::modeEterm); + // Eterm 0.9.x supports palette setting + TDisplay::setDisPaletteColors=SetDisPaletteColorsEt; + ResetPaletteColors=ResetPaletteColorsEt; + setCrtModeRes_p=SetCrtModeEt; + if (parseUserPalette()) + setPaletteColors(0,16,UserStartPalette); + } + else + {// 16+16 colors + palette=PAL_HIGH; + THWMouseXTermFull::Init(THWMouseXTermFull::modeXTerm); + // XTerm from X 4.x supports palette setting + TDisplay::setDisPaletteColors=SetDisPaletteColorsXT; + ResetPaletteColors=ResetPaletteColorsXT; + // XTerm colors are ugly, change them. + if (parseUserPalette()) + setPaletteColors(0,16,UserStartPalette); + else + SetDisPaletteColorsXT(0,16,ActualPalette); + setCrtModeRes_p=SetCrtModeXT; + } + // This is what GNU/Debian Woody uses by default + fontW=6; fontH=13; + TScreenXTerm::screenMode=TScreenXTerm::smCO80; + LOG((palette==PAL_HIGH ? "Using high palette" : "Using low palette")); + + // G0=ASCII (+LAT1?) G1=Dec. SI + // How do I restore the original state? + fputs("\E(B\E)0\xF",stdout); + + startupCursor=getCursorType(); + startupMode =getCrtMode(); + startScreenWidth =getCols(); + startScreenHeight=getRows(); + + // Look for defaults + unsigned maxX=startScreenWidth, maxY=startScreenHeight; + unsigned fW=fontW, fH=fontH; + if (optSearch("ScreenWidth",aux)) + maxX=aux; + if (optSearch("ScreenHeight",aux)) + maxY=aux; + if (optSearch("FontWidth",aux)) + fW=aux; + if (optSearch("FontHeight",aux)) + fH=aux; + if (maxX!=startScreenWidth || maxY!=startScreenHeight) + setCrtModeRes(maxX,maxY,fW,fH); + + cursorLines=getCursorType(); + screenMode =getCrtMode(); + screenWidth =getCols(); + screenHeight=getRows(); + LOG("Screen size: " << (int)screenWidth << "," << (int)screenHeight); + screenBuffer=new ushort[screenWidth * screenHeight]; + SaveScreen(); + + // This is our state, save it + tcgetattr(hOut,&outTermiosNew); + suspended=0; + setCursorType(0); +} + +void TScreenXTerm::Suspend() +{// Invalidate the knowledge about the current color of the terminal + oldCol=oldBack=oldFore=-1; + // Restore old font + if (fontChanged && oldFontName) + fprintf(stdout,"\E]50;%s\x7",oldFontName); + // Restore original window size + signal(SIGWINCH,SIG_DFL); + if (startScreenWidth!=screenWidth || startScreenHeight!=screenHeight) + fprintf(stdout,"\E[8;%d;%dt",startScreenHeight+(terminalType==Eterm ? 1 : 0), + startScreenWidth); + // Restore screen contents + RestoreScreen(); + // Restore the palette, must be before restoring the charset + if (paletteModified) + ResetPaletteColors(); + // Restore the cursor shape + setCursorType(startupCursor); + // That's the default, we don't know the original values + fputs("\E(B\E)0\xF",stdout); + // Restore cursor position, attributes and charset + fputs("\E8",stdout); + // Ensure all is processed before leaving + fflush(stdout); + // Restore console mode, I think drain is better here, but the previous flush + // is needed anyways. + tcsetattr(hOut,TCSADRAIN,&outTermiosOrig); + LOG("TScreenXTerm Suspend"); +} + +TScreenXTerm::~TScreenXTerm() +{ + // At this point we are not suspended + LOG("TScreenXTerm Destructor"); +} + +void TScreenXTerm::DeallocateResources() +{ + LOG("TScreenXTerm DeallocateResources"); + if (oldFontName) + { + DeleteArray(oldFontName); + oldFontName=NULL; + } +} + +void TScreenXTerm::Resume() +{ + // Save console mode + tcgetattr(hOut,&outTermiosOrig); + // Set our console mode + tcsetattr(hOut,TCSAFLUSH,&outTermiosNew); + // That's the default + fputs("\E(B\E)0\xF",stdout); + selCharset=0; + // Save cursor position, attributes and charset + fputs("\E7",stdout); + SaveScreen(); + // Setup our palette + if (paletteModified) + SetDisPaletteColorsXT(0,16,ActualPalette); + // Check the window size + startScreenWidth =getCols(); + startScreenHeight=getRows(); + if (startScreenWidth!=screenWidth || startScreenHeight!=screenHeight) + fprintf(stdout,"\E[8;%d;%dt",screenHeight+(terminalType==Eterm ? 1 : 0), + screenWidth); + // Restore our font + if (fontChanged) + { + DeleteArray(oldFontName); + oldFontName=GetCurrentFontName(); + fprintf(stdout,"\E]50;%dx%d\x7",fontW,fontH); + } + signal(SIGWINCH,sigWindowSizeChanged); + // When we set the video mode the cursor is hidded + ushort oldCursorLines=cursorLines; + // Check for video size change and save some state + //setVideoMode(screenMode); + // Set our cursor shape + setCursorType(oldCursorLines); + LOG("TScreenXTerm Resume"); +} + +/***************************************************************************** + Save/Restore screen +*****************************************************************************/ + +void TScreenXTerm::SaveScreen() +{ + if (!useShellScreen) + // Just switch to the alternative buffer + printf("\E[?47h"); +} + +void TScreenXTerm::RestoreScreen() +{ + if (useShellScreen) + // Clear the screen + printf("\E[2J"); + else + // Just go back to the normal buffer + printf("\E[?47l"); +} + +void TScreenXTerm::SaveScreenReleaseMemory(void) +{ +} + + +void TScreenXTerm::CheckSizeBuffer(int oldWidth, int oldHeight) +{ + // allocating a zeroed screenBuffer, because this function + // is called in most cases (in RHIDE) after a SIGWINCH + if (screenWidth!=oldWidth || screenHeight!=oldHeight || !screenBuffer) + { + // Realloc screen buffer only if actually needed (it doesn't exist + // or screen size is changed) + if (screenBuffer) + DeleteArray(screenBuffer); + screenBuffer=new ushort[screenWidth*screenHeight]; + } + memset(screenBuffer,0,screenWidth*screenHeight*sizeof(ushort)); +} + +void TScreenXTerm::SetVideoMode(ushort mode) +{ + int oldWidth=screenWidth; + int oldHeight=screenHeight; + + setCrtMode(mode); + defaultSetCrtData(); + CheckSizeBuffer(oldWidth,oldHeight); +} + +void TScreenXTerm::SetVideoModeExt(char *mode) +{ + int oldWidth=screenWidth; + int oldHeight=screenHeight; + + setCrtModeExt(mode); + defaultSetCrtData(); + CheckSizeBuffer(oldWidth,oldHeight); +} + +void TScreenXTerm::SetCharacter(unsigned offset,ushort value) +{ + setCharacters(offset,&value,1); +} + +void TScreenXTerm::SetCharacters(unsigned dst, ushort *src, unsigned len) +{ + ushort *old=screenBuffer+dst; + ushort *old_right=old+len-1; + ushort *src_right=src+len-1; + + /* remove unchanged characters from left to right */ + if (!force_redraw) + { + while (len>0 && *old==*src) + { + dst++; + len--; + old++; + src++; + } + + /* remove unchanged characters from right to left */ + while (len>0 && *old_right==*src_right) + { + len--; + old_right--; + src_right--; + } + } + + /* write only middle changed characters */ + if (len>0) + writeBlock(dst,len,old,src); +} + + +/* + The following tables creates a layout quite similar to what linux calls +ISO lat 1 fonts. Lamentably looks like Xterm doesn't implement all the +DEC graphics. + Additionally I don't know what happends if X is configured for another +encoding, does Xterm use it for values between 160 and 254? or it ever +uses ISO-88590-1? + +Which is OK? is just that Xterm have poor fonts? Is Linux extending DEC charset? +Linux have full block (DEC 48), but Xterm no. +Linux have all arrows, but Xterm no. +*/ + +const uchar TScreenXTerm::Code[256]= +{ + '?','=','?','?',96,98,99,100,101,97/*104?*/,97,' '/**/,' '/**/,115/**/,111/**/,' '/**/, + ' '/**/,104/*'n'*/,105,121,122,124,'<','>','^','v','>','<','*','*','?',123, + 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, + 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, + 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, + 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, + 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,'Y'/**/, + 113,120/**/,113/**/,109,120/**/,120,108,116,113/**/,106,113,118,107,117,119,110, + 114,120,113,109,120,120,108,116,113,106,113,118,107,117,119,110, // Most aprox. + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 +}; + +const uchar TScreenXTerm::Modifier[256]= +{ + 0,0,0,0,1,1,1,1,1,1,1,0,0,1,1,0, // 0- 15 + 0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,1, // 16- 31 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 32- 47 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 48- 63 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 64- 79 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 80- 95 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 96-111 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 112-127 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 128-143 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 144-159 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 160-175 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 176-191 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 192-207 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 208-223 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 224-239 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // 240-255 +}; + +/* + * Writes a block of text. + */ + +void TScreenXTerm::writeBlock(int dst, int len, ushort *old, ushort *src) +{ + int col=-1; + uchar val,mod; + + fprintf(stdout,"\E[%d;%dH",dst/TScreenXTerm::screenWidth+1,dst%TScreenXTerm::screenWidth+1); + + while (len-->0) + { + int code =CLY_Low16(*src); + int newcol=CLY_High16(*src); + + *old++=*src++; + if (col!=newcol) /* change color ? */ + { + col=newcol; + if (palette==PAL_MONO) + { + if (col==0x0f) + fputs("\E[0;1m",stdout); // Bold + else + if (col==0x70) + fputs("\E[0;7m",stdout); // Reverse + else + fputs("\E[0m",stdout); // Normal + } + else + mapColor(col); + } + // Convert the value to something in the ISO-Latin-1 range. + // Use the DEC graphics for some values in the control range. + if (code==12 || code==14) + { + fputs("\E[7m \E[27m",stdout); // Reversed space + } + else + { + val=Code[code]; + mod=Modifier[code]; + if (mod!=selCharset) + { + selCharset=mod; + fputc(15-selCharset,stdout); + } + fputc(val,stdout); + } + } + if (palette==PAL_MONO) + fputs("\E[0m",stdout); // Normal + + fprintf(stdout,"\E[%d;%dH",curY+1,curX+1); +} + +/* + * Converts colors from the large TV palette (16 foreground colors and + * 16 background colors) to ncurses small palette (8 foreground colors + * and 8 background colors). + */ + +void TScreenXTerm::mapColor(int col) +{ + static char map[] = {0, 4, 2, 6, 1, 5, 3, 7, 0, 4, 2, 6, 1, 5, 3, 7}; + int back,fore; + + if (col==oldCol) + return; + oldCol=col; + back=(col >> 4) & 15; + fore=col & 15; + + if (palette==PAL_LOW) + {// Just 8 colors, but use bold and blink getting 16+16 + if (fore!=oldFore && back!=oldBack) + fprintf(stdout,"\E[%d;%d;%d;%dm", + fore>7 ? 1 : 22,30+map[fore], + back>7 ? 5 : 25,40+map[back]); + else + { + if (fore!=oldFore) + fprintf(stdout,"\E[%d;%dm",fore>7 ? 1 : 22,30+map[fore]); + else + fprintf(stdout,"\E[%d;%dm",back>7 ? 5 : 25,40+map[back]); + } + } + else + { // 16 fore and 16 background colors, yuuuhuuu! ;-) + if (fore!=oldFore && back!=oldBack) + fprintf(stdout,"\E[%d;%dm",map[fore]+(fore>7 ? 90 : 30), + map[back]+(back>7 ? 100 : 40)); + else + { + if (fore!=oldFore) + fprintf(stdout,"\E[%dm",map[fore]+(fore>7 ? 90 : 30)); + else + fprintf(stdout,"\E[%dm",map[back]+(back>7 ? 100 : 40)); + } + } + + oldFore = fore; + oldBack = back; +} + +// SET: Call to an external program, optionally forking +int TScreenXTerm::System(const char *command, pid_t *pidChild, int in, + int out, int err) +{ + if (!pidChild) + { + // If the caller asks for redirection replace the requested handles + if (in!=-1) + dup2(in,STDIN_FILENO); + if (out!=-1) + dup2(out,STDOUT_FILENO); + if (err!=-1) + dup2(err,STDERR_FILENO); + return system(command); + } + + pid_t cpid=fork(); + if (cpid==0) + {// Ok, we are the child + // I'm not sure about it, but is the best I have right now. + // Doing it we can kill this child and all the subprocesses + // it creates by killing the group. It also have an interesting + // effect that I must evaluate: By doing it this process lose + // the controlling terminal and won't be able to read/write + // to the parents console. I think that's good. + if (setsid()==-1) + _exit(127); + char *argv[4]; + + // If the caller asks for redirection replace the requested handles + if (in!=-1) + dup2(in,STDIN_FILENO); + if (out!=-1) + dup2(out,STDOUT_FILENO); + if (err!=-1) + dup2(err,STDERR_FILENO); + + argv[0]=newStr(getenv("SHELL")); + if (!argv[0]) + argv[0]=newStr("/bin/sh"); + argv[1]=newStr("-c"); + argv[2]=newStr(command); + argv[3]=NULL; + execvp(argv[0],argv); + delete[] argv[0]; + delete[] argv[1]; + delete[] argv[2]; + // We get here only if exec failed + _exit(127); + } + if (cpid==-1) + {// Fork failed do it manually + *pidChild=0; + return system(command); + } + *pidChild=cpid; + return 0; +} + +#else + +#include +#include +#include +#include +#include + +#endif // TVOS_UNIX && !TVOSf_QNXRtP +/***************************************************************************** + +ESC ( C Designate G0 Character Set (ISO 2022) + C = 0 -> DEC Special Character and Line Drawing Set + C = A -> United Kingdom (UK) + C = B -> United States (USASCII) +ESC ) C Designate G1 Character Set (ISO 2022) + C = 0 -> DEC Special Character and Line Drawing Set + C = A -> United Kingdom (UK) + C = B -> United States (USASCII) +ESC 7 Save Cursor (DECSC) +ESC 8 Restore Cursor (DECRC) +ESC > Normal Keypad (DECPNM) +SO Shift Out (Ctrl-N) -> Switch to Alternate Character Set: + invokes the G1 character set. +SI Shift In (Ctrl-O) -> Switch to Standard Character Set: + invokes the G0 character set (the default). +ESC [ Ps ; Ps H Cursor Position [row;column] (default = [1,1]) (CUP) +ESC [ Ps J Erase in Display (ED) + Ps = 0 -> Clear Below (default) + Ps = 1 -> Clear Above + Ps = 2 -> Clear All +ESC [ Ps n Device Status Report (DSR) + Ps = 5 -> Status Report ESC [ 0 n (``OK'') + Ps = 6 -> Report Cursor Position (CPR) [row;column] as ESC + [ r ; c R +ESC [ ? Pm h DEC Private Mode Set (DECSET) + ******* Lo siguiente restaura la pantalla al salir!!! ******* + Ps = 4 7 -> Use Alternate Screen Buffer (unless disabled + by the titeInhibit resource) + Ps = 1 0 0 0 -> Send Mouse X & Y on button press and + release. See the section Mouse Tracking. + Ps = 1 0 0 2 -> Use Cell Motion Mouse Tracking. + ****** Esto lo soporta la del X 3 y reporta el movimiento del mouse!!!! *** + Ps = 1 0 0 3 -> Use All Motion Mouse Tracking. + ****** Probar esto, ¿hará que reporte un modificador para Alt? + Ps = 1 0 3 5 -> Enable special modifiers for Alt and + NumLock keys. + ****** Suena interesante, el de X 3 parece que no lo tiene + Ps = 1 0 3 6 -> Send ESC when Meta modifies a key + (enables the metaSendsEscape resource). + ****** Este es aún mejor que el 47, pero no sirve en Eterm + Ps = 1 0 4 9 -> Save cursor as in DECSC and use Alter­ + nate Screen Buffer, clearing it first (unless disabled by + the titeInhibit resource) + ****** Alguno podrían ayudar + Ps = 1 0 5 1 -> Set Sun function-key mode. + Ps = 1 0 5 2 -> Set HP function-key mode. + Ps = 1 0 6 0 -> Set legacy keyboard emulation (X11R6). + Ps = 1 0 6 1 -> Set Sun/PC keyboard emulation of VT220 + keyboard. +ESC [ ? Pm l DEC Private Mode Reset (DECRST) + Ps = 4 7 -> Use Normal Screen Buffer + Ps = 1 0 0 0 -> Don't Send Mouse X & Y on button press and + release +ESC [ ? Pm r Restore DEC Private Mode Values. The value of Ps previously + saved is restored. Ps values are the same as for DECSET. +ESC [ ? Pm s Save DEC Private Mode Values. Ps values are the same as for + DECSET. +ESC ] Ps ; Pt BEL + Set Text Parameters + Ps = 0 -> Change Icon Name and Window Title to Pt + Ps = 1 -> Change Icon Name to Pt + Ps = 2 -> Change Window Title to Pt + Ps = 4 6 -> Change Log File to Pt (normally disabled by a + compile-time option) + Ps = 5 0 -> Set Font to Pt +****** La Xterm que probé soporta 16 fondos y 16 p.planos. Para restaurar los colores +al salir hay que elegir con 39;49, ojo, Eterm 0.8 soporta sólo 8+8 +CSI Pm m Character Attributes (SGR) + Ps = 0 -> Normal (default) + Ps = 1 -> Bold + Ps = 4 -> Underlined + Ps = 5 -> Blink (appears as Bold) + Ps = 7 -> Inverse + Ps = 8 -> Invisible (hidden) + Ps = 2 2 -> Normal (neither bold nor faint) + Ps = 2 4 -> Not underlined + Ps = 2 5 -> Steady (not blinking) + Ps = 2 7 -> Positive (not inverse) + Ps = 2 8 -> Visible (not hidden) + Ps = 3 0 -> Set foreground color to Black + Ps = 3 1 -> Set foreground color to Red + Ps = 3 2 -> Set foreground color to Green + Ps = 3 3 -> Set foreground color to Yellow + Ps = 3 4 -> Set foreground color to Blue + Ps = 3 5 -> Set foreground color to Magenta + Ps = 3 6 -> Set foreground color to Cyan + Ps = 3 7 -> Set foreground color to White + + Ps = 3 9 -> Set foreground color to default (original) + + Ps = 4 0 -> Set background color to Black + Ps = 4 1 -> Set background color to Red + Ps = 4 2 -> Set background color to Green + Ps = 4 3 -> Set background color to Yellow + Ps = 4 4 -> Set background color to Blue + Ps = 4 5 -> Set background color to Magenta + Ps = 4 6 -> Set background color to Cyan + Ps = 4 7 -> Set background color to White + + Ps = 4 9 -> Set background color to default (original). + + If 16-color support is compiled, the following apply. + Assume that xterm's resources are set so that the ISO + color codes are the first 8 of a set of 16. Then the + aixterm colors are the bright versions of the ISO colors: + Ps = 9 0 -> Set foreground color to Black + Ps = 9 1 -> Set foreground color to Red + Ps = 9 2 -> Set foreground color to Green + Ps = 9 3 -> Set foreground color to Yellow + Ps = 9 4 -> Set foreground color to Blue + Ps = 9 5 -> Set foreground color to Magenta + Ps = 9 6 -> Set foreground color to Cyan + Ps = 9 7 -> Set foreground color to White + + Ps = 1 0 0 -> Set background color to Black + Ps = 1 0 1 -> Set background color to Red + Ps = 1 0 2 -> Set background color to Green + Ps = 1 0 3 -> Set background color to Yellow + Ps = 1 0 4 -> Set background color to Blue + Ps = 1 0 5 -> Set background color to Magenta + Ps = 1 0 6 -> Set background color to Cyan + Ps = 1 0 7 -> Set background color to White + + If xterm is compiled with the 16-color support disabled, + it supports the following, from rxvt: + Ps = 1 0 0 -> Set foreground and background color to + default + + If 88- or 256-color support is compiled, the following + apply. + Ps = 3 8 ; 5 ; Ps -> Set foreground color to the second Ps + Ps = 4 8 ; 5 ; Ps -> Set background color to the second Ps + +**** ¿Será necesario? +CSI Ps ; Ps " p + Set conformance level (DECSCL) Valid values for the first + parameter: + Ps = 6 1 -> VT100 + Ps = 6 2 -> VT200 + Ps = 6 3 -> VT300 + Valid values for the second parameter: + Ps = 0 -> 8-bit controls + Ps = 1 -> 7-bit controls (always set for VT100) + Ps = 2 -> 8-bit controls + +CSI Ps ; Ps ; Ps t + Window manipulation (from dtterm, as well as extensions). + Valid values for the first (and any additional parame­ + ters) are: + **** Estas dos son mortales: + Ps = 1 -> De-iconify window. + Ps = 2 -> Iconify window. + Ps = 3 ; x ; y -> Move window to [x, y]. + Ps = 4 ; height ; width -> Resize the xterm window to height and width in pixels. + Ps = 5 -> Raise the xterm window to the front of the stacking order. + Ps = 6 -> Lower the xterm window to the bottom of the stacking order. + Ps = 7 -> Refresh the xterm window. + **** Esta permitiría cosas muy buenas!!! + Ps = 8 ; height ; width -> Resize the text area to [height;width] in characters. + Ps = 9 ; 0 -> Restore maximized window. + Ps = 9 ; 1 -> Maximize window (i.e., resize to screen size). + Ps = 1 1 -> Report xterm window state. If the xterm + window is open (non-iconified), it returns CSI 1 t . If + the xterm window is iconified, it returns CSI 2 t . + Ps = 1 3 -> Report xterm window position as CSI 3 ; x; yt + Ps = 1 4 -> Report xterm window in pixels as CSI 4 ; height ; width t + ***** Esta es una alternativa para el tamaño de la ventana + Ps = 1 8 -> Report the size of the text area in characters as CSI 8 ; height ; width t + Ps = 1 9 -> Report the size of the screen in characters as CSI 9 ; height ; width t + Ps = 2 0 -> Report xterm window's icon label as OSC L label ST + ***** Esto implementa el getWindowTitle + Ps = 2 1 -> Report xterm window's title as OSC l title ST + Ps >= 2 4 -> Resize to Ps lines (DECSLPP) + +**** Este parece interesante, pero no lo pude hacer andar +CSI Ps ; Pu ´ z + Enable Locator Reporting (DECELR) + Valid values for the first parameter: + Ps = 0 -> Locator disabled (default) + Ps = 1 -> Locator enabled + Ps = 2 -> Locator enabled for one report, then dis­ + abled + The second parameter specifies the coordinate unit for + locator reports. + Valid values for the second parameter: + Pu = 0 or omitted -> default to character cells + Pu = 1 -> device physical pixels + Pu = 2 -> character cells +CSI Pm ´ { Select Locator Events (DECSLE) + Valid values for the first (and any additional parame­ + ters) are: + Ps = 0 -> only respond to explicit host requests + (DECRQLP) + (default) also cancels any filter rectangle + Ps = 1 -> report button down transitions + Ps = 2 -> do not report button down transitions + Ps = 3 -> report button up transitions + Ps = 4 -> do not report button up transitions +CSI Ps ´ | Request Locator Position (DECRQLP) + Valid values for the parameter are: + Ps = 0 , 1 or omitted -> transmit a single DECLRP loca­ + tor report + + If Locator Reporting has been enabled by a DECELR, xterm + will respond with a DECLRP Locator Report. This report + is also generated on button up and down events if they + have been enabled with a DECSLE, or when the locator is + detected outside of a filter rectangle, if filter rectan­ + gles have been enabled with a DECEFR. + + -> CSI Pe ; Pb ; Pr ; Pc ; Pp & w + + Parameters are [event;button;row;column;page]. + Valid values for the event: + Pe = 0 -> locator unavailable - no other parameters + sent + Pe = 1 -> request - xterm received a DECRQLP + Pe = 2 -> left button down + Pe = 3 -> left button up + Pe = 4 -> middle button down + Pe = 5 -> middle button up + Pe = 6 -> right button down + Pe = 7 -> right button up + Pe = 8 -> M4 button down + Pe = 9 -> M4 button up + Pe = 1 0 -> locator outside filter rectangle + ``button'' parameter is a bitmask indicating which but­ + tons are pressed: + Pb = 0 -> no buttons down + Pb & 1 -> right button down + Pb & 2 -> middle button down + Pb & 4 -> left button down + Pb & 8 -> M4 button down + ``row'' and ``column'' parameters are the coordinates of + the locator position in the xterm window, encoded as + ASCII decimal. + The ``page'' parameter is not used by xterm, and will be + omitted. + + +**** Esto lo estoy usando para la paleta +OSC Ps ; Pt BEL + Set Text Parameters. For colors and font, if Pt is a + "?", the control sequence elicits a response which con­ + sists of the control sequence which would set the corre­ + sponding value. The dtterm control sequences allow you + to determine the icon name and window title. + Ps = 0 -> Change Icon Name and Window Title to Pt + Ps = 1 -> Change Icon Name to Pt + Ps = 2 -> Change Window Title to Pt + Ps = 3 -> Set X property on top-level window. Pt + should be in the form "prop=value", or just "prop" to + delete the property + Ps = 4 ; c ; name -> Change Color #c to cname. Any + number of c name pairs may be given. + Ps = 1 0 -> Change color names starting with text + foreground to Pt (a list of one or more color names or + RGB specifications, separated by semicolon, up to eight, + as per XParseColor). + Ps = 1 1 -> Change colors starting with text back­ + ground to Pt + Ps = 1 2 -> Change colors starting with text cursor to + Pt + Ps = 1 3 -> Change colors starting with mouse fore­ + ground to Pt + Ps = 1 4 -> Change colors starting with mouse back­ + ground to Pt + Ps = 1 5 -> Change colors starting with Tek foreground + to Pt + Ps = 1 6 -> Change colors starting with Tek background + to Pt + Ps = 1 7 -> Change colors starting with highlight to + Pt + Ps = 4 6 -> Change Log File to Pt (normally disabled + by a compile-time option) + Ps = 5 0 -> Set Font to Pt If Pt begins with a "#", + index in the font menu, relative (if the next character + is a plus or minus sign) or absolute. A number is + expected but not required after the sign (the default is + the current entry for relative, zero for absolute index­ + ing). + +*****************************************************************************/ diff --git a/tvision/classes/win32/win32clip.cc b/tvision/classes/win32/win32clip.cc new file mode 100644 index 0000000..0ceb52c --- /dev/null +++ b/tvision/classes/win32/win32clip.cc @@ -0,0 +1,144 @@ +/**[txh]******************************************************************** + + Copyright (c) 2002 by Salvador E. Tropea (SET) + Based on code contributed by Anatoli Soltan. + + Description: + Win32 Clipboard routines. + +***************************************************************************/ + +#include + +#define Uses_string +#define Uses_TVOSClipboard +#include +#include + +// I delay the check to generate as much dependencies as possible +#ifdef TVOS_Win32 + +#define WIN32_LEAN_AND_MEAN +#include + +// Strings for the errors +const char *TVWin32Clipboard::win32NameError[]= +{ + NULL, + NULL +}; + +void TVWin32Clipboard::Init() +{ + TVOSClipboard::copy=copy; + TVOSClipboard::paste=paste; + TVOSClipboard::destroy=destroy; + TVOSClipboard::available=1; // We have 1 clipboard + TVOSClipboard::name="Windows"; + // We get the error from windows, so we just change the pointer + TVOSClipboard::errors=1; + TVOSClipboard::nameErrors=win32NameError; +} + +void TVWin32Clipboard::getErrorString() +{ + if (win32NameError[1]) + LocalFree((LPVOID)win32NameError[1]); + + LPVOID lpMsgBuf; + + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL,GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR)&lpMsgBuf,0,NULL); + win32NameError[1]=(const char *)lpMsgBuf; + TVOSClipboard::error=1; +} + +void TVWin32Clipboard::destroy() +{ + if (win32NameError[1]) + LocalFree((LPVOID)win32NameError[1]); +} + +char *TVWin32Clipboard::paste(int id, unsigned &len) +{ + if (id!=0) return NULL; + + char* p=NULL; + HGLOBAL hMem; + + if (OpenClipboard(NULL)) + { + hMem=GetClipboardData(CF_TEXT); + if (hMem) + { + char *d=(char*)GlobalLock(hMem); + if (d) + { + len=GlobalSize(hMem)-1; + p=new char[len+1]; + memcpy(p,d,len); + p[len]=0; + // The returned length doesn't have to be the exact length of the string. + // Reported by Warren H. Holt + len=strlen(p); + GlobalUnlock(hMem); + } + else + getErrorString(); + } + else + getErrorString(); + CloseClipboard(); + } + else + getErrorString(); + + return p; +} + +int TVWin32Clipboard::copy(int id, const char *buffer, unsigned len) +{ + if (id!=0) return 0; + if (!len || !buffer) return 1; + + HGLOBAL hMem=GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,len+1); + if (!hMem) + { + getErrorString(); + return 0; + } + + char *d=(char *)GlobalLock(hMem); + if (!d) + { + getErrorString(); + GlobalFree(hMem); + return 0; + } + memcpy(d,buffer,len); + d[len]=0; + GlobalUnlock(hMem); + + if (OpenClipboard(NULL)) + { + EmptyClipboard(); + if (SetClipboardData(CF_TEXT,hMem)) + { + CloseClipboard(); + // Windows now owns the memory, we doesn't have to release it. + return 1; + } + getErrorString(); + CloseClipboard(); + } + else + getErrorString(); + GlobalFree(hMem); + + return 0; +} + +#endif // TVOS_Win32 + diff --git a/tvision/classes/win32/win32dis.cc b/tvision/classes/win32/win32dis.cc new file mode 100644 index 0000000..f0cb2cd --- /dev/null +++ b/tvision/classes/win32/win32dis.cc @@ -0,0 +1,226 @@ +/**[txh]******************************************************************** + + Copyright (c) 2002 by Salvador E. Tropea (SET) + Based on code contributed by Vadim Beloborodov. + + Description: + Win32 Display routines. + The original implementation was done by Vadim, I removed some code, added +some routines and adapted it to the new architecture. + One important detail is that Vadim implemented it with threads. The +thread that monitors the window size is different, that's why a lock is +needed. + +***************************************************************************/ + +#include + +#define Uses_stdio +#define Uses_TDisplay +#define Uses_TScreen +#include + +// I delay the check to generate as much dependencies as possible +#ifdef TVOS_Win32 + +#define WIN32_LEAN_AND_MEAN +#include + +#include + +const int mxTitleSize=256; + +HANDLE TDisplayWin32::hOut=INVALID_HANDLE_VALUE; +HANDLE TDisplayWin32::hIn =INVALID_HANDLE_VALUE; +HANDLE TDisplayWin32::hStdOut=INVALID_HANDLE_VALUE; +CONSOLE_SCREEN_BUFFER_INFO TDisplayWin32::ConsoleInfo; +CONSOLE_CURSOR_INFO TDisplayWin32::ConsoleCursorInfo; +CRITICAL_SECTION TDisplayWin32::lockWindowSizeChanged; +int TDisplayWin32::WindowSizeChanged=0; + +void TDisplayWin32::SetCursorPos(unsigned x, unsigned y) +{ + COORD pos; + pos.X=x; + pos.Y=y; + SetConsoleCursorPosition(hOut,pos); +} + +void TDisplayWin32::GetCursorPos(unsigned &x, unsigned &y) +{ + GetConsoleScreenBufferInfo(hOut,&ConsoleInfo); + x=ConsoleInfo.dwCursorPosition.X; + y=ConsoleInfo.dwCursorPosition.Y; +} + +// by SET +void TDisplayWin32::GetCursorShape(unsigned &start, unsigned &end) +{ + GetConsoleCursorInfo(hOut,&ConsoleCursorInfo); + if (ConsoleCursorInfo.bVisible) + {// Visible + // Win32API returns a "percent filled" value. + start=100-ConsoleCursorInfo.dwSize; + // Ever upto the end + end =100; + return; + } + // Invisible cursor + start=end=0; +} + +// by SET +void TDisplayWin32::SetCursorShape(unsigned start, unsigned end) +{ + if (start>=end && getShowCursorEver()) + return; + + GetConsoleCursorInfo(hOut,&ConsoleCursorInfo); + if (start>=end) + ConsoleCursorInfo.bVisible=FALSE; + else + { + ConsoleCursorInfo.bVisible=TRUE; + ConsoleCursorInfo.dwSize=end-start; + if (ConsoleCursorInfo.dwSize>=100) + ConsoleCursorInfo.dwSize=99; + } + SetConsoleCursorInfo(hOut,&ConsoleCursorInfo); +} + +ushort TDisplayWin32::GetRows() +{ +#if 0 + ushort Rows=ConsoleInfo.srWindow.Bottom-ConsoleInfo.srWindow.Top+1; + if (Rows>ConsoleInfo.dwMaximumWindowSize.Y) + Rows=ConsoleInfo.dwMaximumWindowSize.Y; + return Rows; +#else + return ConsoleInfo.dwSize.Y; +#endif +} + +ushort TDisplayWin32::GetCols() +{ +#if 0 + ushort Cols=ConsoleInfo.srWindow.Right-ConsoleInfo.srWindow.Left+1; + if (Cols>ConsoleInfo.dwMaximumWindowSize.X) + Cols=ConsoleInfo.dwMaximumWindowSize.X; + return Cols; +#else + return ConsoleInfo.dwSize.X; +#endif +} + +int TDisplayWin32::CheckForWindowSize(void) +{ + int SizeChanged=WindowSizeChanged; + EnterCriticalSection(&lockWindowSizeChanged); + WindowSizeChanged=0; + LeaveCriticalSection(&lockWindowSizeChanged); + if (SizeChanged) + GetConsoleScreenBufferInfo(hOut,&ConsoleInfo); + + return SizeChanged; +} + +void TDisplayWin32::SetCrtMode(ushort) +{ + SetCursorShape(0x58,0x64); +} + +void TDisplayWin32::SetCrtModeExt(char *) +{ + SetCursorShape(0x58,0x64); +} + +/**[txh]******************************************************************** + + Description: + Finds the main window title. + + Return: + A pointer to a newly allocated string (new[]). Or 0 if fail. by SET. + +***************************************************************************/ + +const char *TDisplayWin32::GetWindowTitle(void) +{ + char buf[mxTitleSize]; + DWORD ret=GetConsoleTitle(buf,mxTitleSize); + if (ret) + { + char *s=new char[ret+1]; + memcpy(s,buf,ret); + s[ret]=0; + return s; + } + return 0; +} + +/**[txh]******************************************************************** + + Description: + Sets the main window title. + + Return: + non-zero successful. by SET. + +***************************************************************************/ + +int TDisplayWin32::SetWindowTitle(const char *name) +{ + return SetConsoleTitle(name); +} + +void TDisplayWin32::Beep() +{ + MessageBeep(0xFFFFFFFF); +} + +TDisplayWin32::~TDisplayWin32() {} + +void TDisplayWin32::Init() +{ + setCursorPos=SetCursorPos; + getCursorPos=GetCursorPos; + getCursorShape=GetCursorShape; + setCursorShape=SetCursorShape; + getRows=GetRows; + getCols=GetCols; + checkForWindowSize=CheckForWindowSize; + setWindowTitle=SetWindowTitle; + getWindowTitle=GetWindowTitle; + setCrtMode=SetCrtMode; + setCrtModeExt=SetCrtModeExt; + beep=Beep; +} + +/* Not implemented +void TDisplay::setCrtMode(ushort ) +{ + GetConsoleScreenBufferInfo(hOut, &ConsoleInfo); + EnterCriticalSection( &lockWindowSizeChanged ); + LeaveCriticalSection( &lockWindowSizeChanged ); +} + +void TDisplay::setCrtMode(char * ) +{ + GetConsoleScreenBufferInfo(hOut, &ConsoleInfo); + EnterCriticalSection( &lockWindowSizeChanged ); + LeaveCriticalSection( &lockWindowSizeChanged ); +} + +ushort TDisplay::getCrtMode() +{ + GetConsoleScreenBufferInfo(hOut, &ConsoleInfo); + return smCO80; +} +*/ + +#else // TVOS_Win32 + +#include + +#endif // else TVOS_Win32 + diff --git a/tvision/classes/win32/win32key.cc b/tvision/classes/win32/win32key.cc new file mode 100644 index 0000000..f467d70 --- /dev/null +++ b/tvision/classes/win32/win32key.cc @@ -0,0 +1,464 @@ +/**[txh]******************************************************************** + + Copyright (c) 2002 by Salvador E. Tropea (SET) + It said: + Keyboard handler for Win32 by Vadim Beloborodov + Based on code by Salvador E. Tropea (SET) (c) (1998) + + Description: + Win32 Keyboard routines. + The original implementation was done by Vadim, I removed some code, added +some routines and adapted it to the new architecture. + One important detail is that Vadim implemented it with threads. So we have +here an events handler with a queue. + +***************************************************************************/ + +#include + +#define Uses_string +#define Uses_TEvent +#define Uses_TGKey +#define Uses_TKeys +#define Uses_TKeys_Extended +#define Uses_ctype +#define Uses_TDisplay +#define Uses_TScreen +#include + +// I delay the check to generate as much dependencies as possible +#ifdef TVOS_Win32 + +#define WIN32_LEAN_AND_MEAN +#include + +#include +#include + +KeyDownEvent *TGKeyWin32::evKeyboardIn; +KeyDownEvent *TGKeyWin32::evKeyboardOut; +KeyDownEvent TGKeyWin32::evKeyboardQueue[eventKeyboardQSize]; +unsigned TGKeyWin32::evKeyboardLength; +CRITICAL_SECTION TGKeyWin32::lockKeyboard; +ushort TGKeyWin32::LastControlKeyState=0; + +void TGKeyWin32::Init() +{ + TGKey::kbhit=KbHit; + TGKey::getShiftState=GetShiftState; + TGKey::fillTEvent=FillTEvent; + + InitializeCriticalSection(&lockKeyboard); + evKeyboardLength=0; + evKeyboardIn=evKeyboardOut=&evKeyboardQueue[0]; +} + +void TGKeyWin32::DeInit() +{ + DeleteCriticalSection(&lockKeyboard); +} + +int TGKeyWin32::KbHit(void) +{ + return evKeyboardLength>0; +} + +void TGKeyWin32::FillTEvent(TEvent &e) +{ + getConsoleKeyboardEvent(e.keyDown); + e.what=evKeyDown; +} + +ushort TGKeyWin32::transShiftState(DWORD state) +{ + ushort tvstate=0; + if (state & (RIGHT_ALT_PRESSED |LEFT_ALT_PRESSED) ) tvstate|=kbAltShift; + if (state & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)) tvstate|=kbCtrlShift; + if (state & SHIFT_PRESSED) tvstate|=kbLeftShift; + if (state & NUMLOCK_ON ) tvstate|=kbNumState; + if (state & SCROLLLOCK_ON) tvstate|=kbScrollState; + if (state & CAPSLOCK_ON ) tvstate|=kbCapsState; + + return tvstate; +} + +/* + Translate keyboard events to Salvador E. Tropea's key codes + by Vadim Beloborodov + Originally in trans.cc +*/ + +const char TGKeyWin32::KeyTo[256]= +{ + /* 00 */ 0, + /* 01 VK_LBUTTON */ 0, + /* 02 VK_RBUTTON */ 0, + /* 03 VK_CANCEL */ 0, + /* 04 VK_MBUTTON */ 0, + /* 05 unassigned */ 0, + /* 06 unassigned */ 0, + /* 07 unassigned */ 0, + /* 08 VK_BACK */ kbBackSpace, + /* 09 VK_TAB */ kbTab, + /* 0A unassigned */ 0, + /* 0B unassigned */ 0, + /* 0C VK_CLEAR ?? */ 0, + /* 0D VK_RETURN */ kbEnter, + /* 0E unassigned */ 0, + /* 0F unassigned */ 0, + /* 10 VK_SHIFT */ 0, + /* 11 VK_CONTROL */ 0, + /* 12 VK_MENU */ 0, + /* 13 VK_PAUSE */ 0, + /* 14 VK_CAPITAL */ 0, + /* 15 Kanji systems*/ 0, + /* 16 Kanji systems*/ 0, + /* 17 Kanji systems*/ 0, + /* 18 Kanji systems*/ 0, + /* 19 Kanji systems*/ 0, + /* 1A unassigned */ 0, + /* 1B VK_ESCAPE */ kbEsc, + /* 1C Kanji systems*/ 0, + /* 1D Kanji systems*/ 0, + /* 1E Kanji systems*/ 0, + /* 1F Kanji systems*/ 0, + /* 20 VK_SPACE */ kbSpace, + /* 21 VK_PRIOR */ kbPgUp, + /* 22 VK_NEXT */ kbPgDn, + /* 23 VK_END */ kbEnd, + /* 24 VK_HOME */ kbHome, + /* 25 VK_LEFT */ kbLeft, + /* 26 VK_UP */ kbUp, + /* 27 VK_RIGHT */ kbRight, + /* 28 VK_DOWN */ kbDown, + /* 29 VK_SELECT */ 0, + /* 2A OEM specific */ 0, + /* 2B VK_EXECUTE */ 0, + /* 2C VK_SNAPSHOT */ 0, + /* 2D VK_INSERT */ kbInsert, + /* 2E VK_DELETE */ kbDelete, + /* 2F VK_HELP */ 0, + /* 30 VK_0 '0' */ kb0, + /* 31 VK_1 '1' */ kb1, + /* 32 VK_2 '2' */ kb2, + /* 33 VK_3 '3' */ kb3, + /* 34 VK_4 '4' */ kb4, + /* 35 VK_5 '5' */ kb5, + /* 36 VK_6 '6' */ kb6, + /* 37 VK_7 '7' */ kb7, + /* 38 VK_8 '8' */ kb8, + /* 39 VK_9 '9' */ kb9, + /* 3A unassigned */ 0, + /* 3B unassigned */ 0, + /* 3C unassigned */ 0, + /* 3D unassigned */ 0, + /* 3E unassigned */ 0, + /* 3F unassigned */ 0, + /* 40 unassigned */ 0, + /* 41 VK_A 'A' */ kbA, + /* 42 VK_B 'B' */ kbB, + /* 43 VK_C 'C' */ kbC, + /* 44 VK_D 'D' */ kbD, + /* 45 VK_E 'E' */ kbE, + /* 46 VK_F 'F' */ kbF, + /* 47 VK_G 'G' */ kbG, + /* 48 VK_H 'H' */ kbH, + /* 49 VK_I 'I' */ kbI, + /* 4A VK_J 'J' */ kbJ, + /* 4B VK_K 'K' */ kbK, + /* 4C VK_L 'L' */ kbL, + /* 4D VK_M 'M' */ kbM, + /* 4E VK_N 'N' */ kbN, + /* 4F VK_O 'O' */ kbO, + /* 50 VK_P 'P' */ kbP, + /* 51 VK_Q 'Q' */ kbQ, + /* 52 VK_R 'R' */ kbR, + /* 53 VK_S 'S' */ kbS, + /* 54 VK_T 'T' */ kbT, + /* 55 VK_U 'U' */ kbU, + /* 56 VK_V 'V' */ kbV, + /* 57 VK_W 'W' */ kbW, + /* 58 VK_X 'X' */ kbX, + /* 59 VK_Y 'Y' */ kbY, + /* 5A VK_Z 'Z' */ kbZ, + /* 5B unassigned */ 0, + /* 5C unassigned */ 0, + /* 5D unassigned */ 0, + /* 5E unassigned */ 0, + /* 5F unassigned */ 0, + /* 60 VK_NUMPAD0 NumKeyPad '0' */ kb0, + /* 61 VK_NUMPAD1 NumKeyPad '1' */ kb1, + /* 62 VK_NUMPAD2 NumKeyPad '2' */ kb2, + /* 63 VK_NUMPAD3 NumKeyPad '3' */ kb3, + /* 64 VK_NUMPAD4 NumKeyPad '4' */ kb4, + /* 65 VK_NUMPAD5 NumKeyPad '5' */ kb5, + /* 66 VK_NUMPAD6 NumKeyPad '6' */ kb6, + /* 67 VK_NUMPAD7 NumKeyPad '7' */ kb7, + /* 68 VK_NUMPAD8 NumKeyPad '8' */ kb8, + /* 69 VK_NUMPAD9 NumKeyPad '9' */ kb9, + /* 6A VK_MULTIPLY */ kbAsterisk, + /* 6B VK_ADD */ kbPlus, + /* 6C VK_SEPARATOR */ kbBackSlash, + /* 6D VK_SUBSTRACT */ kbMinus, + /* 6E VK_DECIMAL */ kbGrave, + /* 6F VK_DIVIDE */ kbSlash, + /* 70 VK_F1 'F1' */ kbF1, + /* 71 VK_F2 'F2' */ kbF2, + /* 72 VK_F3 'F3' */ kbF3, + /* 73 VK_F4 'F4' */ kbF4, + /* 74 VK_F5 'F5' */ kbF5, + /* 75 VK_F6 'F6' */ kbF6, + /* 76 VK_F7 'F7' */ kbF7, + /* 77 VK_F8 'F8' */ kbF8, + /* 78 VK_F9 'F9' */ kbF9, + /* 79 VK_F10 'F10' */ kbF10, + /* 7A VK_F11 'F11' */ kbF11, + /* 7B VK_F12 'F12' */ kbF12, + /* 7C VK_F13 */ 0, + /* 7D VK_F14 */ 0, + /* 7E VK_F15 */ 0, + /* 7F VK_F16 */ 0, + /* 80 VK_F17 */ 0, + /* 81 VK_F18 */ 0, + /* 82 VK_F19 */ 0, + /* 83 VK_F20 */ 0, + /* 84 VK_F21 */ 0, + /* 85 VK_F22 */ 0, + /* 86 VK_F23 */ 0, + /* 87 VK_F24 */ 0, + /* 88 unassigned */ 0, + /* 89 VK_NUMLOCK */ 0, + /* 8A VK_SCROLL */ 0, + /* 8B unassigned */ 0, + /* 8C unassigned */ 0, + /* 8D unassigned */ 0, + /* 8E unassigned */ 0, + /* 8F unassigned */ 0, + /* 90 unassigned */ 0, + /* 91 unassigned */ 0, + /* 92 unassigned */ 0, + /* 93 unassigned */ 0, + /* 94 unassigned */ 0, + /* 95 unassigned */ 0, + /* 96 unassigned */ 0, + /* 97 unassigned */ 0, + /* 98 unassigned */ 0, + /* 99 unassigned */ 0, + /* 9A unassigned */ 0, + /* 9B unassigned */ 0, + /* 9C unassigned */ 0, + /* 9D unassigned */ 0, + /* 9E unassigned */ 0, + /* 9F unassigned */ 0, + /* A0 unassigned */ 0, + /* A1 unassigned */ 0, + /* A2 unassigned */ 0, + /* A3 unassigned */ 0, + /* A4 unassigned */ 0, + /* A5 unassigned */ 0, + /* A6 unassigned */ 0, + /* A7 unassigned */ 0, + /* A8 unassigned */ 0, + /* A9 unassigned */ 0, + /* AA unassigned */ 0, + /* AB unassigned */ 0, + /* AC unassigned */ 0, + /* AD unassigned */ 0, + /* AE unassigned */ 0, + /* AF unassigned */ 0, + /* B0 unassigned */ 0, + /* B1 unassigned */ 0, + /* B2 unassigned */ 0, + /* B3 unassigned */ 0, + /* B4 unassigned */ 0, + /* B5 unassigned */ 0, + /* B6 unassigned */ 0, + /* B7 unassigned */ 0, + /* B8 unassigned */ 0, + /* B9 unassigned */ 0, + /* BA OEM specific */ 0, + /* BB OEM specific */ 0, + /* BC OEM specific */ 0, + /* BD OEM specific */ 0, + /* BE OEM specific */ 0, + /* BF OEM specific */ 0, + /* C0 OEM specific */ 0, + /* C1 unassigned */ 0, + /* C2 unassigned */ 0, + /* C3 unassigned */ 0, + /* C4 unassigned */ 0, + /* C5 unassigned */ 0, + /* C6 unassigned */ 0, + /* C7 unassigned */ 0, + /* C8 unassigned */ 0, + /* C9 unassigned */ 0, + /* CA unassigned */ 0, + /* CB unassigned */ 0, + /* CC unassigned */ 0, + /* CD unassigned */ 0, + /* CE unassigned */ 0, + /* CF unassigned */ 0, + /* D0 unassigned */ 0, + /* D1 unassigned */ 0, + /* D2 unassigned */ 0, + /* D3 unassigned */ 0, + /* D4 unassigned */ 0, + /* D5 unassigned */ 0, + /* D6 unassigned */ 0, + /* D7 unassigned */ 0, + /* D8 unassigned */ 0, + /* D9 unassigned */ 0, + /* DA unassigned */ 0, + /* DB OEM specific */ 0, + /* DC OEM specific */ 0, + /* DD OEM specific */ 0, + /* DE OEM specific */ 0, + /* DF OEM specific */ 0, + /* E0 OEM specific */ 0, + /* E1 OEM specific */ 0, + /* E2 OEM specific */ 0, + /* E3 OEM specific */ 0, + /* E4 OEM specific */ 0, + /* E5 unassigned */ 0, + /* E6 OEM specific */ 0, + /* E7 unassigned */ 0, + /* E8 unassigned */ 0, + /* E9 OEM specific */ 0, + /* EA OEM specific */ 0, + /* EB OEM specific */ 0, + /* EC OEM specific */ 0, + /* ED OEM specific */ 0, + /* EE OEM specific */ 0, + /* EF OEM specific */ 0, + /* F0 OEM specific */ 0, + /* F1 OEM specific */ 0, + /* F2 OEM specific */ 0, + /* F3 OEM specific */ 0, + /* F4 OEM specific */ 0, + /* F5 OEM specific */ 0, + /* F6 unassigned */ 0, + /* F7 unassigned */ 0, + /* F8 unassigned */ 0, + /* F9 unassigned */ 0, + /* FA unassigned */ 0, + /* FB unassigned */ 0, + /* FC unassigned */ 0, + /* FD unassigned */ 0, + /* FE unassigned */ 0, + /* FF unassigned */ 0 +}; + +int TGKeyWin32::transKeyEvent(KeyDownEvent& dst, KEY_EVENT_RECORD& src) +{ + if (src.wVirtualKeyCode!=VK_MENU && + src.wVirtualKeyCode!=VK_CONTROL && + src.wVirtualKeyCode!=VK_SHIFT) + { + dst.keyCode=KeyTo[src.wVirtualKeyCode]; + dst.charScan.charCode=src.uChar.AsciiChar; + dst.charScan.scanCode=(uchar)src.wVirtualScanCode; + dst.raw_scanCode=(uchar)src.wVirtualScanCode; + dst.shiftState=transShiftState(src.dwControlKeyState); + if (dst.shiftState&kbAltShift) dst.keyCode|=kbAltLCode; + if (dst.shiftState&kbCtrlShift) dst.keyCode|=kbCtrlCode; + if (dst.shiftState&kbShift) dst.keyCode|=kbShiftCode; + return 1; + } + return 0; +} + +/* + Win32 console events handlers + by Vadim Beloborodov + Originally in console.cc +*/ + +const char TGKeyWin32::testChars[]= +"`1234567890-=" +"~!@#$%^&*()_+" +"qwertyuiop[]" +"QWERTYUIOP{}" +"asdfghjkl;'\\" +"ASDFGHJKL:\"|" +"zxcvbnm,./" +"ZXCVBNM<>?"; + +unsigned TGKeyWin32::GetShiftState() +{ + return LastControlKeyState; +} + +void TGKeyWin32::putConsoleKeyboardEvent(KeyDownEvent &key) +{ + EnterCriticalSection(&lockKeyboard); + if (evKeyboardLength=&evKeyboardQueue[eventKeyboardQSize]) + evKeyboardIn=&evKeyboardQueue[0]; + } + LeaveCriticalSection(&lockKeyboard); +} + +int TGKeyWin32::getConsoleKeyboardEvent(KeyDownEvent &key) +{ + EnterCriticalSection(&lockKeyboard); + int haskeyevent=evKeyboardLength>0; + if (haskeyevent) + { + evKeyboardLength--; + key=*evKeyboardOut; + if (++evKeyboardOut>=&evKeyboardQueue[eventKeyboardQSize]) + evKeyboardOut=&evKeyboardQueue[0]; + } + LeaveCriticalSection(&lockKeyboard); + return haskeyevent; +} + +void TGKeyWin32::HandleKeyEvent() +{ + INPUT_RECORD ir; + DWORD dwRead; + PeekConsoleInput(TScreenWin32::hIn,&ir,1,&dwRead); + if ((dwRead==1) && (ir.EventType==KEY_EVENT)) + { + if (ir.Event.KeyEvent.bKeyDown) + { + //support for non US keyboard layout on Windows95 + if (((ir.Event.KeyEvent.dwControlKeyState & (RIGHT_ALT_PRESSED|LEFT_ALT_PRESSED|RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED))==0) && + (ir.Event.KeyEvent.uChar.AsciiChar) && + strchr(testChars,ir.Event.KeyEvent.uChar.AsciiChar)) + { + uchar chr; + ReadConsole(TScreenWin32::hIn,&chr,1,&dwRead,NULL); + ir.Event.KeyEvent.uChar.AsciiChar=chr; + dwRead=0; + } + else + { + ReadConsoleInput(TScreenWin32::hIn,&ir,1,&dwRead); + dwRead = 0; + } + //translate event + KeyDownEvent key; + if (transKeyEvent(key,ir.Event.KeyEvent)) + putConsoleKeyboardEvent(key); + } + ProcessControlKeyState(&ir); + } + if (dwRead==1) + ReadConsoleInput(TScreenWin32::hIn,&ir,1,&dwRead); +} + +void TGKeyWin32::ProcessControlKeyState(INPUT_RECORD *ir) +{ + LastControlKeyState=transShiftState(ir->Event.KeyEvent.dwControlKeyState); +} +#else + +#include +#include + +#endif // TVOS_Win32 + diff --git a/tvision/classes/win32/win32mouse.cc b/tvision/classes/win32/win32mouse.cc new file mode 100644 index 0000000..8255430 --- /dev/null +++ b/tvision/classes/win32/win32mouse.cc @@ -0,0 +1,126 @@ +/**[txh]******************************************************************** + + Copyright (c) 2002 by Salvador E. Tropea (SET) + Based on code contributed by Vadim Beloborodov. + + Description: + Win32 Mouse routines. + The original implementation was done by Vadim, I removed some code and +adapted it to the new architecture. + One important detail is that Vadim implemented it with threads. So we have +here an events handler with a queue. + +***************************************************************************/ + +#include + +#define Uses_stdlib +#define Uses_TEvent +#define Uses_TEventQueue +#define Uses_TGKey +#define Uses_TScreen +#include + +// I delay the check to generate as much dependencies as possible +#ifdef TVOS_Win32 + +#define WIN32_LEAN_AND_MEAN +#include + +#include +#include +#include + +MouseEventType *THWMouseWin32::evMouseIn; +MouseEventType *THWMouseWin32::evLastMouseIn=NULL; +MouseEventType *THWMouseWin32::evMouseOut; +MouseEventType THWMouseWin32::evMouseQueue[eventMouseQSize]; +unsigned THWMouseWin32::evMouseLength; +CRITICAL_SECTION THWMouseWin32::lockMouse; + +void THWMouseWin32::Init() +{ + THWMouse::GetEvent=THWMouseWin32::GetEvent; + THWMouse::Resume=THWMouseWin32::Resume; + InitializeCriticalSection(&lockMouse); + evMouseLength=0; + evMouseIn=evMouseOut=&evMouseQueue[0]; + Resume(); +} + +void THWMouseWin32::Resume() +{ + // SET: This is supposed to report if mouse is present and how many buttons + // have. I put a detailed comment in winnt driver. + buttonCount=GetSystemMetrics(SM_CMOUSEBUTTONS); +} + +void THWMouseWin32::DeInit() +{ + DeleteCriticalSection(&lockMouse); +} + +void THWMouseWin32::putConsoleMouseEvent(MouseEventType& mouse) +{ + EnterCriticalSection(&lockMouse); + if (evMouseLengthbuttons==mouse.buttons)) + *evLastMouseIn=mouse; + else + { + evMouseLength++; + *evMouseIn=mouse; + evLastMouseIn=evMouseIn; + if (++evMouseIn>=&evMouseQueue[eventMouseQSize]) + evMouseIn=&evMouseQueue[0]; + } + } + LeaveCriticalSection(&lockMouse); +} + +void THWMouseWin32::GetEvent(MouseEventType &me) +{ + EnterCriticalSection(&lockMouse); + int hasmouseevent=evMouseLength>0; + if (hasmouseevent) + { + evMouseLength--; + me=*evMouseOut; + if (++evMouseOut>=&evMouseQueue[eventMouseQSize]) + evMouseOut=&evMouseQueue[0]; + } + else + // If no event is available use the last values so TV reports no changes + me=TEventQueue::curMouse; + LeaveCriticalSection(&lockMouse); +} + +void THWMouseWin32::HandleMouseEvent() +{ + INPUT_RECORD ir; + DWORD dwRead; + ReadConsoleInput(TScreenWin32::hIn,&ir,1,&dwRead); + if ((dwRead==1) && (ir.EventType==MOUSE_EVENT)) + { + MouseEventType mouse; + mouse.where.x=ir.Event.MouseEvent.dwMousePosition.X; + mouse.where.y=ir.Event.MouseEvent.dwMousePosition.Y; + mouse.buttons=0; + mouse.doubleClick=False; + if (ir.Event.MouseEvent.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) + mouse.buttons|=mbLeftButton; + if (ir.Event.MouseEvent.dwButtonState & RIGHTMOST_BUTTON_PRESSED) + mouse.buttons|=mbRightButton; + putConsoleMouseEvent(mouse); + TGKeyWin32::ProcessControlKeyState(&ir); + } +} +#else + +#include +#include +#include + +#endif // TVOS_Win32 + diff --git a/tvision/classes/win32/win32scr.cc b/tvision/classes/win32/win32scr.cc new file mode 100644 index 0000000..a1655d0 --- /dev/null +++ b/tvision/classes/win32/win32scr.cc @@ -0,0 +1,564 @@ +/**[txh]******************************************************************** + + Copyright (c) 2002 by Salvador E. Tropea (SET) + Based on code contributed by Vadim Beloborodov. + + Description: + Win32 Screen routines. + The original implementation was done by Vadim, I removed some code, added +some routines and adapted it to the new architecture. + One important detail is that Vadim implemented it with threads. The +thread that monitors the window size is different, that's why a lock is +needed. + ToDo: Set UseScreenSaver when we are in full screen. + + Configuration variables: + ScreenWidth + ScreenHeight + AppCP + ScrCP + InpCP + + Notes: +1) I changed all the code related to the save/restore state using a new +screen buffer. I comment more in the "WinNT" driver. One really strange +thing is that this driver behaves better with the cursor. Don't know why. +I also added the resize window stuff. + +***************************************************************************/ + +#include + +#define Uses_string +#define Uses_stdlib +#define Uses_unistd +#define Uses_TScreen +#define Uses_TEvent +#define Uses_TGKey +#define Uses_TVCodePage +#include +#include + +// I delay the check to generate as much dependencies as possible +#ifdef TVOS_Win32 + +#define WIN32_LEAN_AND_MEAN +#include + +#include +#include +#include + +//#define DEBUG +#ifdef DEBUG + #define DBPr1(a) fputs(a,stderr) + #define DBPr2(a,b) fprintf(stderr,a,b) + #define DBPr3(a,b,c) fprintf(stderr,a,b,c) +#else + #define DBPr1(a) + #define DBPr2(a,b) + #define DBPr3(a,b,c) +#endif + +CONSOLE_SCREEN_BUFFER_INFO TScreenWin32::info; +int TScreenWin32::ExitEventThread=0; +HANDLE TScreenWin32::EventThreadHandle=NULL; +DWORD TScreenWin32::oldConsoleMode, + TScreenWin32::newConsoleMode; +unsigned TScreenWin32::xCurStart, + TScreenWin32::yCurStart; +unsigned TScreenWin32::saveScreenWidth, + TScreenWin32::saveScreenHeight; + +TScreenWin32::TScreenWin32() +{ + if (!InitConsole()) return; + flags0=CodePageVar | CursorShapes | CanSetVideoSize; + startupMode=getCrtMode(); + startupCursor=getCursorType(); + saveScreenWidth =GetCols(); + saveScreenHeight=GetRows(); + + unsigned maxX=saveScreenWidth, maxY=saveScreenHeight; + long aux; + if (optSearch("ScreenWidth",aux)) + maxX=aux; + if (optSearch("ScreenHeight",aux)) + maxY=aux; + if (maxX!=saveScreenWidth || maxY!=saveScreenHeight) + { + setCrtModeRes(maxX,maxY); + // Update cached values + GetConsoleScreenBufferInfo(hOut,&ConsoleInfo); + } + + cursorLines=getCursorType(); + screenWidth =GetCols(); + screenHeight=GetRows(); + + screenBuffer=new ushort[screenHeight*screenWidth]; + ZeroMemory(screenBuffer,screenHeight*screenWidth*sizeof(ushort)); + + GetCursorPos(xCurStart,yCurStart); + suspended=0; + setCrtData(); +} + +int TScreenWin32::InitConsole() +{ + DWORD flags; + // Check if we are running in a console + if (!GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE),&flags)) + return 0; + // Get handles to access Standard Input and Output + hIn =GetStdHandle(STD_INPUT_HANDLE); + hStdOut=GetStdHandle(STD_OUTPUT_HANDLE); + // Create a new buffer, it have their own content and cursor + hOut=CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, + 0,NULL,CONSOLE_TEXTMODE_BUFFER,NULL); + if (hStdOut==INVALID_HANDLE_VALUE || hOut==INVALID_HANDLE_VALUE) + return 0; // Something went wrong + // Make the new one the active + if (!SetConsoleActiveScreenBuffer(hOut)) + return 0; + + // If we are here this driver will be used + initialized=1; + if (dCB) dCB(); + + // Enable mouse input + GetConsoleMode(hIn,&oldConsoleMode); + newConsoleMode=oldConsoleMode | ENABLE_MOUSE_INPUT|ENABLE_WINDOW_INPUT; + newConsoleMode&=~(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT); + SetConsoleMode(hIn,newConsoleMode); + SetConsoleCtrlHandler(ConsoleEventHandler,TRUE); + + GetConsoleScreenBufferInfo(hOut,&ConsoleInfo); + + InitializeCriticalSection(&lockWindowSizeChanged); + + TDisplayWin32::Init(); + + TScreen::clearScreen=clearScreen; + TScreen::setCharacter=setCharacter; + TScreen::setCharacters=setCharacters; + TScreen::System_p=System; + TScreen::Resume=Resume; + TScreen::Suspend=Suspend; + TScreen::setCrtModeRes_p=SetCrtModeRes; + TScreen::setVideoModeRes_p=SetVideoModeRes; + TScreen::setVideoMode=SetVideoMode; + TScreen::setVideoModeExt=SetVideoModeExt; + + TVWin32Clipboard::Init(); + TGKeyWin32::Init(); + THWMouseWin32::Init(); + + DWORD EventThreadID; + EventThreadHandle=CreateThread(NULL,0,HandleEvents,NULL,0,&EventThreadID); + + UINT outCP=GetConsoleOutputCP(); + UINT inCP=GetConsoleCP(); + // Look for user settings + optSearch("AppCP",forcedAppCP); + optSearch("ScrCP",forcedScrCP); + optSearch("InpCP",forcedInpCP); + // User settings have more priority than detected settings + codePage=new TVCodePage(forcedAppCP!=-1 ? forcedAppCP : outCP, + forcedScrCP!=-1 ? forcedScrCP : outCP, + forcedInpCP!=-1 ? forcedInpCP : inCP); + SetDefaultCodePages(outCP,outCP,inCP); + + return 1; +} + +void TScreenWin32::DoneConsole() +{ + INPUT_RECORD ir; + DWORD written; + + // Stop the events thread + ZeroMemory(&ir,sizeof(ir)); + ExitEventThread=1; + ir.EventType=KEY_EVENT; + WriteConsoleInput(hIn,&ir,1,&written); + WaitForSingleObject(EventThreadHandle,INFINITE); + CloseHandle(EventThreadHandle); + + DeleteCriticalSection(&lockWindowSizeChanged); + THWMouseWin32::DeInit(); + TGKeyWin32::DeInit(); +} + +DWORD WINAPI TScreenWin32::HandleEvents(void *) +{ + INPUT_RECORD ir; + DWORD dwRead; + + while (!ExitEventThread) + { + WaitForSingleObject(hIn,INFINITE); + if (!ExitEventThread) + { + if (PeekConsoleInput(hIn,&ir,1,&dwRead) && dwRead>0) + { + switch (ir.EventType) + { + case MOUSE_EVENT: + THWMouseWin32::HandleMouseEvent(); + break; + + case KEY_EVENT: + TGKeyWin32::HandleKeyEvent(); + break; + + // Vadim wrote it, I never could make Windows resize. + // Not even providing a larger screen buffer. + case WINDOW_BUFFER_SIZE_EVENT: + EnterCriticalSection(&lockWindowSizeChanged); + WindowSizeChanged=1; + LeaveCriticalSection(&lockWindowSizeChanged); + + default: + ReadConsoleInput(hIn,&ir,1,&dwRead); + } + } + } + else + ReadConsoleInput(hIn,&ir,1,&dwRead); + } + return 0; +} + + +void TScreenWin32::Resume() +{ + DBPr1("TScreenWin32::Resume\n"); + // First switch to our handle + SetConsoleActiveScreenBuffer(hOut); + // Now we can save the current window size + GetConsoleScreenBufferInfo(hOut,&ConsoleInfo); + saveScreenWidth =ConsoleInfo.dwSize.X; + saveScreenHeight=ConsoleInfo.dwSize.Y; + // Restore our window size + SetCrtModeRes(screenWidth,screenHeight); + GetConsoleScreenBufferInfo(hOut,&ConsoleInfo); + setCrtData(); + // Invalidate the cache to force a redraw + ZeroMemory(screenBuffer,screenHeight*screenWidth*sizeof(ushort)); + + GetConsoleMode(hIn,&oldConsoleMode); + SetConsoleMode(hIn,newConsoleMode); + SetConsoleCtrlHandler(ConsoleEventHandler,TRUE); +} + +void TScreenWin32::Suspend() +{ + // Restore window size (using our handle!) + SetCrtModeRes(saveScreenWidth,saveScreenHeight); + // Switch to the original handle + SetConsoleActiveScreenBuffer(hStdOut); + SetConsoleMode(hIn,oldConsoleMode); + SetConsoleCtrlHandler(ConsoleEventHandler,FALSE); +} + +TScreenWin32::~TScreenWin32() +{ + Suspend(); + suspended=1; + setCursorType(startupCursor); + DoneConsole(); + if (screenBuffer) + { + delete screenBuffer; + screenBuffer=0; + } +} + +void TScreenWin32::clearScreen() +{ + COORD coord ={0,0}; + DWORD read; + unsigned size=GetRows()*GetCols(); + FillConsoleOutputAttribute(hOut,0x07,size,coord,&read); + FillConsoleOutputCharacterA(hOut,' ',size,coord,&read); +} + +void TScreenWin32::setCharacter(unsigned offset, ushort value) +{ + setCharacters(offset,&value,1); +} + +void TScreenWin32::setCharacters(unsigned dst, ushort *src, unsigned len) +{ + ushort *old=((ushort*)screenBuffer)+dst; + ushort *old_right=old+len-1; + ushort *src_right=src+len-1; + + while (len>0 && *old==*src) + { + dst++; + len--; + old++; + src++; + } + + /* remove unchanged characters from right to left */ + while (len>0 && *old_right==*src_right) + { + len--; + old_right--; + src_right--; + } + + /* write only middle changed characters */ + if (len>0) + { + CHAR_INFO ch[maxViewWidth]; + int i=0; + + while (len-->0) + { + *old++=*src; + ch[i].Attributes=HIBYTE(*src); + ch[i].Char.AsciiChar=LOBYTE(*src); + i++; + src++; + } + + ushort x=dst%screenWidth, y=dst/screenWidth; + + SMALL_RECT to={x,y,x+i-1,y}; + COORD bsize={i,1}; + static COORD from={0,0}; + WriteConsoleOutput(hOut,ch,bsize,from,&to); + } +} + +#ifndef TVCompf_Cygwin +int TScreenWin32::System(const char *command, pid_t *pidChild, int in, + int out, int err) +{ + // fork mechanism not implemented, indicate the child finished + if (pidChild) + *pidChild=0; + // If the caller asks for redirection replace the requested handles + if (in!=-1) + dup2(in,STDIN_FILENO); + if (out!=-1) + dup2(out,STDOUT_FILENO); + if (err!=-1) + dup2(err,STDERR_FILENO); + return system(command); +} +#else +// fork mechanism is implemented in Cygwin, so linux code should work -- OH + +// SET: Call to an external program, optionally forking +int TScreenWin32::System(const char *command, pid_t *pidChild, int in, + int out, int err) +{ + if (!pidChild) + { + // If the caller asks for redirection replace the requested handles + if (in!=-1) + dup2(in,STDIN_FILENO); + if (out!=-1) + dup2(out,STDOUT_FILENO); + if (err!=-1) + dup2(err,STDERR_FILENO); + return system(command); + } + + pid_t cpid=fork(); + if (cpid==0) + {// Ok, we are the child + // I'm not sure about it, but is the best I have right now. + // Doing it we can kill this child and all the subprocesses + // it creates by killing the group. It also have an interesting + // effect that I must evaluate: By doing it this process lose + // the controlling terminal and won't be able to read/write + // to the parents console. I think that's good. + if (setsid()==-1) + _exit(127); + char *argv[4]; + + // If the caller asks for redirection replace the requested handles + if (in!=-1) + dup2(in,STDIN_FILENO); + if (out!=-1) + dup2(out,STDOUT_FILENO); + if (err!=-1) + dup2(err,STDERR_FILENO); + + argv[0]=getenv("SHELL"); + if (!argv[0]) + argv[0]="/bin/sh"; + argv[1]="-c"; + argv[2]=(char *)command; + argv[3]=0; + execvp(argv[0],argv); + // We get here only if exec failed + _exit(127); + } + if (cpid==-1) + {// Fork failed do it manually + *pidChild=0; + return system(command); + } + *pidChild=cpid; + return 0; +} +#endif + +TScreen *TV_Win32DriverCheck() +{ + TScreenWin32 *drv=new TScreenWin32(); + if (!TScreen::initialized) + { + delete drv; + return 0; + } + return drv; +} + +/**[txh]******************************************************************** + + Description: + Change the window size to the desired value. The font size is ignored +because it can't be controlled by the application, the Win32 API reference +I have says: "A screen buffer can be any size, limited only by available +memory. The dimensions of a screen buffer's window cannot exceed the +corresponding dimensions of either the screen buffer or the maximum window +that can fit on the screen based on the current font size (controlled +exclusively by the user).".@* + It only works if we are windowed and this will prevent from going full +screen unless Windows knows an equivalent text mode. + + Return: 0 no change, 1 full change, 2 approx. change. by SET + +***************************************************************************/ + +int TScreenWin32::SetCrtModeRes(unsigned w, unsigned h, int fW, int fH) +{ + CONSOLE_SCREEN_BUFFER_INFO info; + DBPr3("TScreenWin32::SetCrtModeRes(%d,%d)\n",w,h); + // Find current size + if (!GetConsoleScreenBufferInfo(hOut,&info)) + { + DBPr1("GetConsoleScreenBufferInfo failed\n"); + return 0; + } + // Is the same used? + if (info.dwSize.X==(int)w && info.dwSize.Y==(int)h) + { + DBPr3("Already using %d,%d size\n",w,h); + return 0; + } + // Find the max. size, depends on the font and screen size. + COORD max=GetLargestConsoleWindowSize(hOut); + COORD newSize={w,h}; + if (newSize.X>max.X) newSize.X=max.X; + if (newSize.Y>max.Y) newSize.Y=max.Y; + // The buffer must be large enough to hold both modes (current and new) + COORD newBufSize=newSize; + if (info.dwMaximumWindowSize.X>newBufSize.X) + newBufSize.X=info.dwMaximumWindowSize.X; + if (info.dwMaximumWindowSize.Y>newBufSize.Y) + newBufSize.Y=info.dwMaximumWindowSize.Y; + DBPr3("Enlarging buffer from %d,%d to",info.dwMaximumWindowSize.X, + info.dwMaximumWindowSize.Y); + DBPr3(" %d,%d\n",newBufSize.X,newBufSize.Y); + // Enlarge the buffer size. It fails if not windowed. + if (!SetConsoleScreenBufferSize(hOut,newBufSize)) + { + DBPr1("SetConsoleScreenBufferSize failed!\n"); + return 0; + } + // Resize the window. + SMALL_RECT r={0,0,newSize.X-1,newSize.Y-1}; + DBPr3("Resizing window to %d,%d\n",newSize.X,newSize.Y); + if (!SetConsoleWindowInfo(hOut,TRUE,&r)) + {// Revert buffer size + DBPr1("SetConsoleWindowInfo failed!\n"); + newSize.X=info.dwMaximumWindowSize.X; + newSize.Y=info.dwMaximumWindowSize.Y; + SetConsoleScreenBufferSize(hOut,newSize); + return 0; + } + // Now we can shrink the buffer to the needed size + SetConsoleScreenBufferSize(hOut,newSize); + // Ok! we did it. + return fW!=-1 || fH!=-1 || newSize.X!=(int)w || newSize.Y!=(int)h ? 2 : 1; +} + +void TScreenWin32::CheckSizeBuffer(int oldWidth, int oldHeight) +{ + // allocating a zeroed screenBuffer, because this function + // is called in most cases (in RHIDE) after a SIGWINCH + if (screenWidth!=oldWidth || screenHeight!=oldHeight || !screenBuffer) + { + // Realloc screen buffer only if actually needed (it doesn't exist + // or screen size is changed) + if (screenBuffer) + DeleteArray(screenBuffer); + screenBuffer=new ushort[screenWidth*screenHeight]; + } + memset(screenBuffer,0,screenWidth*screenHeight*sizeof(ushort)); +} + +void TScreenWin32::SetVideoMode(ushort mode) +{ + int oldWidth=screenWidth; + int oldHeight=screenHeight; + + defaultSetVideoMode(mode); + CheckSizeBuffer(oldWidth,oldHeight); +} + +void TScreenWin32::SetVideoModeExt(char *mode) +{ + int oldWidth=screenWidth; + int oldHeight=screenHeight; + + defaultSetVideoModeExt(mode); + CheckSizeBuffer(oldWidth,oldHeight); +} + +int TScreenWin32::SetVideoModeRes(unsigned w, unsigned h, int fW, int fH) +{// Set the screen mode + int ret=setCrtModeRes(w,h,fW,fH); + if (ret) + {// Memorize new values: + // Cache the values for TDisplay + GetConsoleScreenBufferInfo(hOut,&ConsoleInfo); + screenWidth =ConsoleInfo.dwSize.X; + screenHeight=ConsoleInfo.dwSize.Y; + DeleteArray(screenBuffer); + screenBuffer=new ushort[screenHeight*screenWidth]; + ZeroMemory(screenBuffer,screenHeight*screenWidth*sizeof(ushort)); + // This is something silly TV code spects: after a video mode change the + // cursor should go to the "default" state. + setCursorType(cursorLines); + // Cache the data about it and initialize related stuff + setCrtData(); + } + return ret; +} + +// Anatoli's idea +BOOL WINAPI TScreenWin32::ConsoleEventHandler(DWORD dwCtrlType) +{ + if (dwCtrlType==CTRL_C_EVENT || dwCtrlType==CTRL_BREAK_EVENT) + return TRUE; + return FALSE; +} + +#else + +#include +#include +#include + +#endif // TVOS_Win32 + diff --git a/tvision/classes/wingr/wingrdis.cc b/tvision/classes/wingr/wingrdis.cc new file mode 100644 index 0000000..b5a08c3 --- /dev/null +++ b/tvision/classes/wingr/wingrdis.cc @@ -0,0 +1,1623 @@ +/**[txh]******************************************************************** + + Copyright (c) 2002 José Angel Sánchez Caso (JASC) + + skeletons by Salvador E. Tropea (SET) + + Description: + Windows GUI Display routines. + +***************************************************************************/ + +#include + +#define Uses_stdio +#define Uses_stdlib +#define Uses_TDisplay +#define Uses_TScreen +#define Uses_TEvent +#define Uses_TEditor +#define Uses_TGKey +#define Uses_TMouse +#define Uses_TGroup +#define Uses_TVCodePage +#define Uses_TProgram +#define Uses_TRect +#define Uses_TEvent +#define Uses_alloca +#include + +#if defined(TVOS_Win32) && !defined(TV_Disable_WinGr_Driver) + +#define WIN32_LEAN_AND_MEAN +#include +#include + + +#include +#include +#include + +const int maxTitleSize= 256; + +char * TDisplayWinGr::className= "TVISION for windows"; /* Make the classname into a global variable */ +HINSTANCE TDisplayWinGr::TvWinInstance; + +char TDisplayWinGr::cShapeFr; +char TDisplayWinGr::cShapeTo; + +unsigned TDisplayWinGr::xPos= UINT_MAX; /* X axis of the cursor */ +unsigned TDisplayWinGr::yPos= UINT_MAX; /* Y axis of the cursor */ +unsigned TDisplayWinGr::zPos; /* Z axis of the cursor (means size )*/ +int TDisplayWinGr::sizeChanged= 0; /* Resizinf counter */ +int TDisplayWinGr::forceRedraw= 0; + +TEvent TDisplayWinGr::storedEvent; /* Correctly processes message queue */ +HWND TDisplayWinGr::hwnd= NULL; /* Main window handler */ +HDC TDisplayWinGr::hdc; /* A device context used for drawing */ +COLORREF TDisplayWinGr::colorMap[ 16 ]; + +HCURSOR TDisplayWinGr::normCursor; +HCURSOR TDisplayWinGr::sizeCursor; +HCURSOR TDisplayWinGr::handCursor; + +bitmapFontRec TDisplayWinGr::primary = { 0,0,0,0,0 }; +bitmapFontRec TDisplayWinGr::secondary= { 0,0,0,0,0 }; + + RECT TDisplayWinGr::wGeo= { 0, 0, 0, 0 }; + +/* + * JASC, marz 2006 + * + * drag 'n' drop support + */ + +char TDisplayWinGr::dragDropName[ PATH_MAX ]; +int TDisplayWinGr::dragDropIdx= 0; +void * TDisplayWinGr::dragDropHnd= NULL; + + +/* + * At least font limits have the hardcoded fonts + */ + +int TDisplayWinGr::foWmin= 8; +int TDisplayWinGr::foHmin= 16; +int TDisplayWinGr::foWmax= 10; +int TDisplayWinGr::foHmax= 20; + +unsigned TDisplayWinGr::dmPelsWidth ; +unsigned TDisplayWinGr::dmPelsHeight; + + + + +uchar TDisplayWinGr::shapeFont10x20[]= +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x4C,0x80,0x4C,0x80,0x7C,0x80,0x79,0x80,0x73,0x80,0x73,0x80,0x73,0x80,0x7F,0x80,0x73,0x80,0x73,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x80,0x6D,0x80,0x67,0x00,0x00,0x00,0x39,0x80,0x6D,0x80,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x36,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x67,0x80,0x66,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x36,0x00,0x1F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x6D,0x80,0x6D,0x80,0x6F,0x80,0x6C,0x00,0x6C,0x00,0x6D,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x3F,0x00,0x7F,0x80,0x7F,0x80,0x3F,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x7E,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x00,0x00,0x1F,0x80,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x7C,0x00,0x60,0x00,0x60,0x00,0x78,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x0F,0x80,0x0C,0x00,0x0C,0x00,0x0F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x3C,0x00,0x66,0x00,0x60,0x00,0x60,0x00,0x66,0x00,0x3C,0x00,0x00,0x00,0x1F,0x00,0x19,0x80,0x19,0x80,0x1F,0x00,0x1E,0x00,0x1B,0x00,0x19,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x3E,0x00,0x00,0x00,0x0F,0x80,0x0C,0x00,0x0C,0x00,0x0F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x55,0x40,0x00,0x00,0xAA,0x80,0x00,0x00,0x55,0x40,0x00,0x00,0xAA,0x80,0x00,0x00,0x55,0x40,0x00,0x00,0xAA,0x80,0x00,0x00,0x55,0x40,0x00,0x00,0xAA,0x80,0x00,0x00,0x55,0x40,0x00,0x00,0xAA,0x80,0x00,0x00 +, 0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80 +, 0x55,0x40,0xFF,0xC0,0xAA,0x80,0xFF,0xC0,0x55,0x40,0xFF,0xC0,0xAA,0x80,0xFF,0xC0,0x55,0x40,0xFF,0xC0,0xAA,0x80,0xFF,0xC0,0x55,0x40,0xFF,0xC0,0xAA,0x80,0xFF,0xC0,0x55,0x40,0xFF,0xC0,0xAA,0x80,0xFF,0xC0 +, 0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0 +, 0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00 +, 0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0 +, 0x00,0x00,0x00,0x00,0x66,0x00,0x76,0x00,0x7E,0x00,0x7E,0x00,0x6E,0x00,0x66,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x3C,0x00,0x3C,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x1F,0x80,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x38,0x00,0x0E,0x00,0x03,0x80,0x0E,0x00,0x38,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,0x0E,0x00,0x38,0x00,0xE0,0x00,0x38,0x00,0x0E,0x00,0x03,0x80,0x00,0x00,0x00,0x00,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x18,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x07,0x80,0x1F,0x80,0x7F,0x80,0x7F,0x80,0x1F,0x80,0x07,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x78,0x00,0x7E,0x00,0x7F,0x80,0x7F,0x80,0x7E,0x00,0x78,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x3F,0x00,0x6D,0x80,0x4C,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x4C,0x80,0x6D,0x80,0x3F,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x06,0x00,0x03,0x00,0xFF,0x80,0xFF,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0xFF,0x80,0xFF,0x80,0x60,0x00,0x30,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x3F,0x00,0x6D,0x80,0x4C,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x4C,0x80,0x6D,0x80,0x3F,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0x33,0x00,0x61,0x80,0xFF,0xC0,0xFF,0xC0,0x61,0x80,0x33,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x19,0x80,0x31,0x80,0x7F,0x80,0x7F,0x80,0x30,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x33,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x3F,0xC0,0x1B,0x00,0x1B,0x00,0x1B,0x00,0x7F,0x80,0x36,0x00,0x36,0x00,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x3F,0x00,0x6D,0x80,0x6C,0x00,0x6C,0x00,0x6C,0x00,0x3F,0x00,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x6D,0x80,0x3F,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x80,0x6D,0x80,0x6F,0x00,0x3B,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x1B,0x80,0x1E,0xC0,0x36,0xC0,0x33,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x3C,0x00,0x18,0x00,0x38,0x00,0x6C,0x00,0x66,0xC0,0x63,0x80,0x63,0x00,0x77,0x80,0x3C,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x7F,0x80,0x1E,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1C,0x00,0x3C,0x00,0x6C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x01,0x80,0x01,0x80,0x03,0x00,0x0E,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x01,0x80,0x03,0x00,0x0E,0x00,0x03,0x00,0x01,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x07,0x00,0x0F,0x00,0x1B,0x00,0x33,0x00,0x63,0x00,0x63,0x00,0x7F,0x80,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0x80,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x01,0x80,0x21,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x00,0x01,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x67,0x80,0x6F,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6F,0x00,0x66,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x66,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x66,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x67,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x63,0x00,0x63,0x00,0x66,0x00,0x66,0x00,0x7C,0x00,0x66,0x00,0x66,0x00,0x63,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x73,0x80,0x73,0x80,0x7F,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x71,0x80,0x71,0x80,0x79,0x80,0x79,0x80,0x6D,0x80,0x6D,0x80,0x67,0x80,0x67,0x80,0x63,0x80,0x63,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x6D,0x80,0x67,0x80,0x33,0x00,0x1F,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x66,0x00,0x63,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x60,0x00,0x60,0x00,0x30,0x00,0x1E,0x00,0x03,0x00,0x01,0x80,0x01,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x73,0x80,0x73,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x1E,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0x80,0x01,0x80,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x06,0x00,0x03,0x00,0x03,0x00,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x73,0x00,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x1D,0x80,0x33,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x7F,0x80,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x19,0x80,0x19,0x80,0x18,0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x80,0x63,0x80,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x60,0x00,0x3F,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x3F,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x00,0x00,0x07,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x31,0x80,0x31,0x80,0x31,0x80,0x1F,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x63,0x00,0x66,0x00,0x6C,0x00,0x78,0x00,0x7C,0x00,0x66,0x00,0x63,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5B,0x00,0x7F,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x73,0x00,0x6E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1D,0x80,0x33,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0x00,0x39,0x80,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x60,0x00,0x3F,0x00,0x01,0x80,0x01,0x80,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x19,0x80,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x7F,0x80,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x33,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x61,0x80,0x33,0x00,0x1E,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x01,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x3F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x78,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x07,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x07,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x80,0x6D,0x80,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00 +, 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00 +, 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x0F,0xC0,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00 +, 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0xF8,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00 +, 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0xFF,0xC0,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x04,0x00,0x07,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x13,0xC0,0x10,0x00,0x1F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00 +, 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xC0,0x10,0x00,0x13,0xC0,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00 +, 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x13,0xC0,0x10,0x00,0x13,0xC0,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x08,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0xF2,0x00,0x02,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0xF3,0xC0,0x00,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x02,0x00,0xF2,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00 +, 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0xF2,0x00,0x02,0x00,0xF2,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00,0xF3,0xC0,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00 +, 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0xF3,0xC0,0x00,0x00,0xF3,0xC0,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x00,0x60,0x00,0x60,0x00,0x61,0x00,0x33,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x19,0x80,0x19,0x80,0x18,0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x7C,0x00,0x56,0xC0,0x73,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x3F,0x00,0x6D,0x80,0x6C,0x00,0x6C,0x00,0x6C,0x00,0x3F,0x00,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x6D,0x80,0x3F,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x3F,0x00,0x0C,0x00,0x3F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x63,0x00,0x30,0x00,0x3C,0x00,0x66,0x00,0x33,0x00,0x19,0x80,0x0F,0x00,0x03,0x00,0x31,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x5E,0x80,0x52,0x80,0x50,0x80,0x52,0x80,0x5E,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x21,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x80,0x0D,0x80,0x1B,0x00,0x36,0x00,0x6C,0x00,0xD8,0x00,0x6C,0x00,0x36,0x00,0x1B,0x00,0x0D,0x80,0x04,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x7F,0x80,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x5E,0x80,0x52,0x80,0x5E,0x80,0x54,0x80,0x56,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x00,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x36,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x36,0x00,0x06,0x00,0x0C,0x00,0x06,0x00,0x36,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x77,0x00,0x7D,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x7F,0x80,0x7D,0x80,0x7D,0x80,0x7D,0x80,0x3D,0x80,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x06,0x00,0x36,0x00,0x1C,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x38,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x36,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x1C,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x6C,0x00,0x36,0x00,0x1B,0x00,0x0D,0x80,0x06,0xC0,0x0D,0x80,0x1B,0x00,0x36,0x00,0x6C,0x00,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x60,0x00,0x20,0x80,0x21,0x00,0x72,0x00,0x04,0x00,0x09,0x00,0x13,0x00,0x25,0x00,0x4F,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x60,0x00,0x20,0x80,0x21,0x00,0x72,0x00,0x04,0x00,0x0B,0x00,0x14,0x80,0x20,0x80,0x41,0x00,0x02,0x00,0x07,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x08,0x00,0x30,0x80,0x09,0x00,0x72,0x00,0x04,0x00,0x09,0x00,0x13,0x00,0x25,0x00,0x4F,0x80,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x19,0x00,0x3F,0x00,0x26,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x1E,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x1E,0x00,0x36,0x00,0x36,0x00,0x66,0x00,0x66,0x00,0x7F,0x80,0x66,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x67,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x61,0x80,0x33,0x00,0x1E,0x00,0x0C,0x00,0x06,0x00,0x36,0x00,0x1C,0x00 +, 0x00,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x00,0x00,0x3F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x3F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x3F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x3F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0xF9,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x19,0x00,0x3F,0x00,0x26,0x00,0x00,0x00,0x61,0x80,0x71,0x80,0x79,0x80,0x79,0x80,0x6D,0x80,0x6D,0x80,0x67,0x80,0x67,0x80,0x63,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x19,0x00,0x3F,0x00,0x26,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x63,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x36,0x00,0x63,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x80,0x1F,0x00,0x33,0x00,0x63,0x80,0x63,0x80,0x65,0x80,0x65,0x80,0x65,0x80,0x69,0x80,0x69,0x80,0x69,0x80,0x71,0x80,0x33,0x00,0x3E,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x3F,0x00,0x31,0x80,0x31,0x80,0x31,0x80,0x31,0x80,0x31,0x80,0x3F,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x1B,0x00,0x31,0x80,0x31,0x80,0x33,0x00,0x76,0x00,0x36,0x00,0x33,0x00,0x31,0x80,0x31,0x80,0x31,0x80,0x33,0x00,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x00,0x3F,0x00,0x26,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3B,0x00,0x4D,0x80,0x0D,0x80,0x0F,0x00,0x3C,0x00,0x6C,0x00,0x6C,0x80,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x0C,0x00,0x06,0x00,0x36,0x00,0x1C,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x7F,0x80,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x7F,0x80,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x7F,0x80,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x7F,0x80,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x00,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x07,0xC0,0x01,0x80,0x1D,0x80,0x33,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x00,0x3F,0x00,0x26,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x00,0x3F,0x00,0x26,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x7F,0x80,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x1F,0x00,0x33,0x00,0x65,0x80,0x65,0x80,0x69,0x80,0x69,0x80,0x33,0x00,0x3E,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x61,0x80,0x33,0x00,0x1E,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x3E,0x00,0x33,0x00,0x31,0x80,0x31,0x80,0x31,0x80,0x33,0x00,0x3E,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00 +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x61,0x80,0x33,0x00,0x1E,0x00 +}; + +uchar TDisplayWinGr::shapeFont8x16[]= +{ 0x00,0x00,0x7E,0xC3,0x99,0x99,0xF3,0xE7,0xE7,0xFF,0xE7,0xE7,0x7E,0x00,0x00,0x00 // 0 +, 0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00 //  +, 0x00,0x00,0x6E,0xF8,0xD8,0xD8,0xDC,0xD8,0xD8,0xD8,0xF8,0x6E,0x00,0x00,0x00,0x00 //  +, 0x00,0x00,0x00,0x00,0x00,0x6E,0xDB,0xDB,0xDF,0xD8,0xDB,0x6E,0x00,0x00,0x00,0x00 //  +, 0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00 //  +, 0x00,0x88,0x88,0xF8,0x88,0x88,0x00,0x3E,0x08,0x08,0x08,0x08,0x00,0x00,0x00,0x00 //  +, 0x00,0xF8,0x80,0xE0,0x80,0x80,0x00,0x3E,0x20,0x38,0x20,0x20,0x00,0x00,0x00,0x00 //  +, 0x00,0x70,0x88,0x80,0x88,0x70,0x00,0x3C,0x22,0x3C,0x24,0x22,0x00,0x00,0x00,0x00 //  +, 0x00,0x80,0x80,0x80,0x80,0xF8,0x00,0x3E,0x20,0x38,0x20,0x20,0x00,0x00,0x00,0x00 //  +, 0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44 // \t +, 0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA // \n +, 0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77 // +, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF // +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF // \r +, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 //  +, 0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0 //  +, 0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F //  +, 0x00,0x88,0xC8,0xA8,0x98,0x88,0x00,0x20,0x20,0x20,0x20,0x3E,0x00,0x00,0x00,0x00 //  +, 0x00,0x88,0x88,0x50,0x50,0x20,0x00,0x3E,0x08,0x08,0x08,0x08,0x00,0x00,0x00,0x00 //  +, 0x00,0x00,0x00,0x00,0x0E,0x38,0xE0,0x38,0x0E,0x00,0xFE,0x00,0x00,0x00,0x00,0x00 //  +, 0x00,0x00,0x00,0x00,0xE0,0x38,0x0E,0x38,0xE0,0x00,0xFE,0x00,0x00,0x00,0x00,0x00 //  +, 0x00,0x00,0x00,0x06,0x0C,0xFE,0x18,0x30,0xFE,0x60,0xC0,0x00,0x00,0x00,0x00,0x00 //  +, 0x00,0x00,0x00,0x00,0x06,0x1E,0x7E,0xFE,0x7E,0x1E,0x06,0x00,0x00,0x00,0x00,0x00 //  +, 0x00,0x00,0x00,0x00,0xC0,0xF0,0xFC,0xFE,0xFC,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00 //  +, 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00 //  +, 0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00 //  +, 0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00 // 0x1A +, 0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00 //  +, 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00 //  +, 0x00,0x00,0x00,0x00,0x00,0x28,0x6C,0xFE,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00 //  +, 0x00,0x00,0x00,0x00,0x06,0x36,0x66,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00 //  +, 0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00 //  +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // +, 0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00 // ! +, 0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // " +, 0x00,0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00 // # +, 0x00,0x10,0x10,0x7C,0xD6,0xD0,0xD0,0x7C,0x16,0x16,0xD6,0x7C,0x10,0x10,0x00,0x00 // $ +, 0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00 // % +, 0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00 // & +, 0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ' +, 0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00 // ( +, 0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00 // ) +, 0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00 // * +, 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00 // + +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00 // , +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // - +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00 // . +, 0x00,0x00,0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00,0x00,0x00,0x00,0x00 // / +, 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // 0 +, 0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00 // 1 +, 0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00 // 2 +, 0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00 // 3 +, 0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00 // 4 +, 0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00 // 5 +, 0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // 6 +, 0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00 // 7 +, 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // 8 +, 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00 // 9 +, 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00 // : +, 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00 // ; +, 0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00 // < +, 0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // = +, 0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00 // > +, 0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00 // ? +, 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0x7C,0x00,0x00,0x00,0x00 // @ +, 0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00 // A +, 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00 // B +, 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00 // C +, 0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00 // D +, 0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00 // E +, 0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00 // F +, 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00 // G +, 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00 // H +, 0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00 // I +, 0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00 // J +, 0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00 // K +, 0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00 // L +, 0x00,0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00 // M +, 0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00 // N +, 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // O +, 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00 // P +, 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00 // Q +, 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00 // R +, 0x00,0x00,0x7C,0xC6,0xC6,0x64,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // S +, 0x00,0x00,0x7E,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00 // T +, 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // U +, 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00 // V +, 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00 // W +, 0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00 // X +, 0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00 // Y +, 0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00 // Z +, 0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00 // [ +, 0x00,0x00,0x00,0x00,0x00,0xC0,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00,0x00 // \ . +, 0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00 // ] +, 0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ^ +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00 // _ +, 0x00,0x30,0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ` +, 0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00 // a +, 0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00 // b +, 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00 // c +, 0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00 // d +, 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00 // e +, 0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00 // f +, 0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0xCC,0x78,0x00 // g +, 0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00 // h +, 0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00 // i +, 0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00 // j +, 0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00 // k +, 0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00 // l +, 0x00,0x00,0x00,0x00,0x00,0xEC,0xFE,0xD6,0xD6,0xD6,0xD6,0xC6,0x00,0x00,0x00,0x00 // m +, 0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00 // n +, 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // o +, 0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00 // p +, 0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00 // q +, 0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00 // r +, 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00 // s +, 0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00 // t +, 0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00 // u +, 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00 // v +, 0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00 // w +, 0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00 // x +, 0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00 // y +, 0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00 // z +, 0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00 // { +, 0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00 // | +, 0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00 // } +, 0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ~ +, 0x00,0x66,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00 //  +, 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // € +, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ‚ +, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ƒ +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 // „ +, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 // … +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 // † +, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 // ‡ +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ˆ +, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ‰ +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // Š +, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ‹ +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 // Œ +, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 // +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 // Ž +, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 // +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00 // +, 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ‘ +, 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x60,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ’ +, 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6F,0x60,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // “ +, 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C // ” +, 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C // • +, 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x60,0x6F,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C // – +, 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6F,0x60,0x6F,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C // — +, 0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x0C,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ˜ +, 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0xEC,0x0C,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ™ +, 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // š +, 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0xEF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // › +, 0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x0C,0xEC,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C // œ +, 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0xEC,0x0C,0xEC,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C // +, 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xEF,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C // ž +, 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0xEF,0x00,0xEF,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C // Ÿ +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0xFE,0x00,0x00,0x00,0x00 //   +, 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00 // ¡ +, 0x00,0x00,0x00,0x00,0x10,0x7C,0xD6,0xD0,0xD0,0xD0,0xD6,0x7C,0x10,0x00,0x00,0x00 // ¢ +, 0x00,0x00,0x38,0x6C,0x60,0x60,0xF0,0x60,0x60,0x66,0xF6,0x6C,0x00,0x00,0x00,0x00 // £ +, 0x00,0x00,0x00,0x00,0xC6,0x7C,0x6C,0x6C,0x7C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00 // ¤ +, 0x00,0x00,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00 // ¥ +, 0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00 // ¦ +, 0x00,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00 // § +, 0x00,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ¨ +, 0x00,0x00,0x3C,0x42,0x99,0xA5,0xA1,0xA5,0x99,0x42,0x3C,0x00,0x00,0x00,0x00,0x00 // © +, 0x00,0x00,0x3C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ª +, 0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00 // « +, 0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00 // ¬ +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ­ +, 0x00,0x00,0x3C,0x42,0xB9,0xA5,0xB9,0xA5,0xA5,0x42,0x3C,0x00,0x00,0x00,0x00,0x00 // ® +, 0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ¯ +, 0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ° +, 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x7E,0x00,0x00,0x00,0x00 // ± +, 0x38,0x6C,0x18,0x30,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ² +, 0x38,0x6C,0x18,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ³ +, 0x00,0x18,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ´ +, 0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xF6,0xC0,0xC0,0xC0,0x00 // µ +, 0x00,0x00,0x7F,0xD6,0xD6,0x76,0x36,0x36,0x36,0x36,0x36,0x36,0x00,0x00,0x00,0x00 // ¶ +, 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // · +, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x6C,0x38,0x00 // ¸ +, 0x30,0x70,0x30,0x30,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // ¹ +, 0x00,0x00,0x38,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // º +, 0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,0x00 // » +, 0x00,0x60,0xE0,0x60,0x66,0x0C,0x18,0x30,0x66,0xCE,0x1A,0x3F,0x06,0x06,0x00,0x00 // ¼ +, 0x00,0x60,0xE0,0x60,0x66,0x0C,0x18,0x30,0x6E,0xDB,0x06,0x0C,0x1F,0x00,0x00,0x00 // ½ +, 0x70,0xD8,0x30,0xD8,0x76,0x0C,0x18,0x30,0x66,0xCE,0x1A,0x3F,0x06,0x06,0x00,0x00 // ¾ +, 0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x30,0x60,0xC6,0xC6,0x7C,0x00,0x00 // ¿ +, 0x60,0x30,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00 // À +, 0x0C,0x18,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00 // Á +, 0x10,0x38,0x6C,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00 //  +, 0x76,0xDC,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00 // à +, 0x00,0x6C,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00 // Ä +, 0x38,0x6C,0x38,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00 // Å +, 0x00,0x00,0x3E,0x78,0xD8,0xD8,0xFC,0xD8,0xD8,0xD8,0xD8,0xDE,0x00,0x00,0x00,0x00 // Æ +, 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x0C,0x66,0x3C,0x00 // Ç +, 0x60,0x30,0x00,0xFE,0x66,0x60,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00 // È +, 0x0C,0x18,0x00,0xFE,0x66,0x60,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00 // É +, 0x10,0x38,0x6C,0x00,0xFE,0x66,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00 // Ê +, 0x00,0x6C,0x00,0xFE,0x66,0x60,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00 // Ë +, 0x60,0x30,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00 // Ì +, 0x06,0x0C,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00 // Í +, 0x18,0x3C,0x66,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00 // Î +, 0x00,0x66,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00 // Ï +, 0x00,0x00,0xF8,0x6C,0x66,0x66,0xF6,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00 // Ð +, 0x76,0xDC,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00 // Ñ +, 0x60,0x30,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // Ò +, 0x0C,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // Ó +, 0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // Ô +, 0x76,0xDC,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // Õ +, 0x00,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // Ö +, 0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0x18,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00 // × +, 0x00,0x00,0x7E,0xC6,0xCE,0xCE,0xDE,0xF6,0xE6,0xE6,0xC6,0xFC,0x00,0x00,0x00,0x00 // Ø +, 0x60,0x30,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // Ù +, 0x0C,0x18,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // Ú +, 0x10,0x38,0x6C,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // Û +, 0x00,0x6C,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // Ü +, 0x06,0x0C,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00 // Ý +, 0x00,0x00,0xF0,0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x60,0xF0,0x00,0x00,0x00,0x00 // Þ +, 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xCC,0xC6,0xC6,0xC6,0xD6,0xDC,0x80,0x00,0x00,0x00 // ß +, 0x00,0x60,0x30,0x18,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00 // à +, 0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00 // á +, 0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00 // â +, 0x00,0x00,0x76,0xDC,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00 // ã +, 0x00,0x00,0x00,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00 // ä +, 0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00 // å +, 0x00,0x00,0x00,0x00,0x00,0x7E,0xDB,0x1B,0x7F,0xD8,0xDB,0x7E,0x00,0x00,0x00,0x00 // æ +, 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x18,0x6C,0x38,0x00 // ç +, 0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00 // è +, 0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00 // é +, 0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00 // ê +, 0x00,0x00,0x00,0x6C,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00 // ë +, 0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00 // ì +, 0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00 // í +, 0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00 // î +, 0x00,0x00,0x00,0x6C,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00 // ï +, 0x00,0x78,0x30,0x78,0x0C,0x7E,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // ð +, 0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00 // ñ +, 0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // ò +, 0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // ó +, 0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // ô +, 0x00,0x00,0x76,0xDC,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // õ +, 0x00,0x00,0x00,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00 // ö +, 0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00 // ÷ +, 0x00,0x00,0x00,0x00,0x00,0x7E,0xCE,0xDE,0xFE,0xF6,0xE6,0xFC,0x00,0x00,0x00,0x00 // ø +, 0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00 // ù +, 0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00 // ú +, 0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00 // û +, 0x00,0x00,0x00,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00 // ü +, 0x00,0x0C,0x18,0x30,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00 // ý +, 0x00,0x00,0xF0,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00,0x00 // þ +, 0x00,0x00,0x00,0x6C,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00 // 255 +}; + +TScreenFont256 TDisplayWinGr::font8x16 ={ 8, 16, (uchar *)shapeFont8x16 }; +TScreenFont256 TDisplayWinGr::font10x20={ 10, 20, shapeFont10x20 }; +TScreenFont256 * TDisplayWinGr::defaultFont= &TDisplayWinGr::font8x16; + + +/* + * JASC, ene 2006, new raster fonts + */ + +int TDisplayWinGr::selectFont( bitmapFontRec & fontResource + , TScreenFont256 * fontData ) +{ if ( !hdc ) /* No resources now */ + { return( -1 ); + } + + if ( !fontData ) + { fontData= TDisplayWinGr::defaultFont; + } + + if ( !fontResource.bitmapMemo ) + { fontResource.bitmapMemo= CreateCompatibleDC( hdc ); /* Memory needed */ + } + + if ( fontResource.bitmapRaster ) + { DeleteObject( fontResource.bitmapRaster ); /* Free rersources */ + } + +/* + * Bitmaps are word aligned but fonts are byte aligned Aghh... + */ + + ushort * data= (ushort *)fontData->data; + ushort * dst= (ushort *) alloca( 256 * sizeof( ushort ) * fontData->h ); + + if ((( fontData->w - 8 ) % 16 ) == 0 ) /* 8, 24, 40 etc ... (byte aligned) */ + { int sz= 256 * fontData->h ; /* Iterate whole chars */ + uchar * src= fontData->data; + data= dst; /* Point to the new buffer */ + + while ( sz -- ) + { *dst ++ = *src ++; // *src ++; + } + } + +/* + * Arrange all 256 chars in a single row + */ + + fontResource.w= fontData->w; + fontResource.h= fontData->h; + + fontResource.bitmapRaster= + CreateBitmap( fontData->w + , fontData->h * 256 /* 256 chars */ + , 1 , 1 /* Monochome bitmap */ + , data ); /* font data */ + + + fontResource.bitmapObject= + SelectObject( fontResource.bitmapMemo + , fontResource.bitmapRaster ); + +/* + * The this hardcoded bitmap fonts have evidently a fixed codepage. + */ + + TVCodePage::SetScreenCodePage( TVCodePage::ISOLatin1Linux ); + return( 0 ); +} + + +/* + * JASC, feb 2006, Emulated DOS modes + */ + +VideoModeData TDisplayWinGr::videoModes[]= +{{ smBW80 , 80, 25, 8, 16 } +,{ smCO80 , 80, 25, 8, 16 } +,{ smCO80x25, 80, 25, 8, 16 } +,{ smMono , 80, 25, 8, 16 } +,{ smFont8x8, 80, 50, 8, 8 } + +/* + * Modes defined by Robert + * Extended + */ + +,{ smCO80x28, 80,28, 8, 12 } +,{ smCO80x35, 80,35, 8, 12 } +,{ smCO80x40, 80,40, 8, 12 } +,{ smCO80x43, 80,43, 8, 8 } +,{ smCO80x50, 80,50, 8, 8 } + +/* Tweaked + */ +,{ smCO80x30, 80,30, 8, 12 } +,{ smCO80x34, 80,34, 8, 12 } +,{ smCO90x30, 90,30, 7, 12 } +,{ smCO90x34, 90,34, 5, 12 } +,{ smCO94x30, 94,30, 5, 12 } +,{ smCO94x34, 94,34, 5, 12 } +,{ smCO82x25, 82,25, 0, 0 } /* Created by SET to get 8x16 char cells */ + +/* Common VESA text modes + */ + +,{ smCO80x60 , 80, 60, 8, 8 } +,{ smCO132x25, 132, 25, 5, 12 } +,{ smCO132x43, 132, 43, 5, 12 } +,{ smCO132x50, 132, 50, 4, 6 } +,{ smCO132x60, 132, 60, 4, 6 } +,{}}; + + + +/* + * JASC, feb 2006, Load a windows font + */ + +int TDisplayWinGr::SetFontCrt( bitmapFontRec & fontResource + , ushort w, ushort h ) +{ HGDIOBJ fontObject; + int loop; + RECT celda; + char letra; + + if ( !hdc ) /* No resources now */ + { return( -1 ); + } + + HFONT hFont= CreateFont( h /* Font height */ + , w /* Font width */ + , 0 /* Escapement */ + , 0 /* Orientation */ + , FW_DONTCARE /* Weigth */ + , false /* Italic */ + , false /* Underline */ + , false /* Bold */ + , OEM_CHARSET /* Charset */ + , OUT_DEFAULT_PRECIS /* output precision */ + , CLIP_DEFAULT_PRECIS /* clipping precision */ + , DEFAULT_QUALITY /* output quality */ + , DEFAULT_PITCH /* pitch and family */ + , "Terminal" ); /* typeface name */ + + + if ( !fontResource.bitmapMemo ) + { fontResource.bitmapMemo= CreateCompatibleDC( hdc ); /* Memory needed */ + } + + if ( fontResource.bitmapRaster ) + { DeleteObject( fontResource.bitmapRaster ); /* Free rersources */ + } + + fontResource.h= h; + fontResource.w= w; + + fontResource.bitmapRaster= + CreateBitmap( fontResource.w + , fontResource.h * 256 /* 256 chars */ + , 1 , 1 /* Monochome bitmap */ + , NULL ); /* font data */ + + fontResource.bitmapObject= + SelectObject( fontResource.bitmapMemo + , fontResource.bitmapRaster ); + fontObject= + SelectObject( fontResource.bitmapMemo + , hFont ); + + + SetBkColor ( fontResource.bitmapMemo, 0 ); // Color de fondo + SetTextColor( fontResource.bitmapMemo, 1 ); // Color de fondo + + for( loop= 0 /* Fill in the bitmap */ + ; loop<256 + ; loop ++ ) + { letra= loop; /* poiter problems */ + + celda.top= fontResource.h * loop; + celda.bottom= fontResource.h + celda.top; + celda.left= 0; + celda.right= fontResource.w; + + DrawText( fontResource.bitmapMemo /* Memory device */ + , &letra, 1 + , &celda + + , DT_NOPREFIX + | DT_SINGLELINE + | DT_BOTTOM ); + } + + TVCodePage::SetScreenCodePage( TVCodePage::PC437 ); + + DeleteObject( hFont ); /* Not needed yet */ + return( 0 ); +} + + +/* + * JASC, feb 2006, Load a mode + */ + +int TDisplayWinGr::SetFontMode( bitmapFontRec & fontResource + , ushort newMode ) +{ const VideoModeData * ptr; + + for( ptr= videoModes + ; ptr->mode + ; ptr ++ ) + { if ( (ushort)ptr->mode == newMode ) + { SetFontCrt( fontResource + , ptr->wFont /* Font height */ + , ptr->hFont ); /* Font width */ + } + } + return( -1 ); +} + +/* + * + */ +void TDisplayWinGr::lowSetCursor( int x + , int y + , bool dir ) +{ ushort * dst; + char fg, bg; + uchar letra; + int to, fr; + + if ( THWMouseWinGr::lastCursor == sizeCursor ) /* Resizing window */ + { return; + } + + if ( !TScreen::screenBuffer ) + { return; + } + + if ( zPos ) // Cursor not visible now + { dir= false; + } + + if ((unsigned) x >= (unsigned)getCols() ) // JASC, this tests both bounds + { return; + } + + if ((unsigned) y >= (unsigned)getRows() ) // JASC, this tests both bounds + { return; + } + + dst = TScreen::screenBuffer // Calc new cursor position + + x + + y*TScreen::screenWidth; + + if ( dir ) + { bg= attrColor(*dst) >> 4; // Swap colors (reverse) + fg= attrColor(*dst) & 0xF; + } + else + { fg= attrColor(*dst) >> 4; // Normal + bg= attrColor(*dst) & 0xF; + } + + letra= attrChar( *dst ); + + SetBkColor ( hdc, colorMap[(int)bg] ); // Background color + SetTextColor( hdc, colorMap[(int)fg] ); // Foreground color + + fr= dir ? cShapeFr:0; + to= dir ? cShapeTo:primary.h; + + BitBlt( hdc + , x * primary.w + , y * primary.h + fr + , primary.w + , to - fr - 1 + , primary.bitmapMemo + , 0, letra * primary.h + , SRCCOPY ); + + } + + + +/* + * JASC, feb 2006 + * + * Those functions assure that the screen size have suitable values + */ +int TDisplayWinGr::CheckWindowSize( RECT & windowArea ) +{ int w= wGeo.right ; + int h= wGeo.bottom; + int recalcFlag; + +/* + * Check a reasonable minimun size + */ + + TScreen::screenWidth = TScreen::screenWidth < 10 ? 10 : TScreen::screenWidth; + TScreen::screenHeight= TScreen::screenHeight< 3 ? 3 : TScreen::screenHeight; + + wGeo.right= TScreen::screenWidth * primary.w; /* quantize width */ + wGeo.bottom= TScreen::screenHeight * primary.h; /* quantize height */ + + + if (( wGeo.right == w ) /* No changes, all done */ + && ( wGeo.bottom == h )) + { return( 0 ); + } + + + do + { windowArea= wGeo; /* Desired client size and pos */ + AdjustWindowRectEx( &windowArea /* IN/OUT variable */ + , TScreenWinGr::style + , 0 /* No windows menu */ + , TScreenWinGr::exStyle ); /* Extended styles */ + + + /* + * Windows don´t have the same criteria in about ofsets in giving and demanding + */ + windowArea.right += wGeo.left - windowArea.left; + windowArea.bottom+= wGeo.top - windowArea.top; + + /* + * Check out of boundaries (Bigger than device size) + */ + + recalcFlag= 0; + + if ( windowArea.right > (ushort)dmPelsWidth ) /* Too wide */ + { TScreen::screenWidth --; /* Reduce width */ + wGeo.right-= primary.w; + recalcFlag ++; /* Request a new step */ + } + + if ( windowArea.bottom > (ushort)dmPelsHeight ) /* Too tall */ + { TScreen::screenWidth --; /* Reduce height */ + wGeo.bottom-= primary.h; /* quantize height */ + recalcFlag ++; /* Request a new step */ + } + } + while( recalcFlag ); + + return( 1 ); /* Must be resized */ +} + +/* + * + */ + +void TDisplayWinGr::winRecalc( ) +{ RECT windowArea; + + if ( CheckWindowSize( windowArea ) ) + { MoveWindow( hwnd + , windowArea.left + , windowArea.top + , windowArea.right + , windowArea.bottom + , true ); /* repaintin soon */ + } +} + + + + +/* + * JASC 2002 + * + * 10/3/2006 --> Draq 'n' drop support + */ +int TDisplayWinGr::testEvents( UINT message + , WPARAM wParam + , LPARAM lParam ) +{ PAINTSTRUCT ps; /* Also used during window drawing */ + + switch( message ) + { int w, h; + + case WM_DROPFILES: // JASC, mar 2006, drag 'n' drop support + dragDropHnd= (void *)wParam; + dragDropIdx= DragQueryFile( (HDROP)dragDropHnd // DragQueryFile is very overloaded + , 0xFFFFFFFF + , NULL + , 0 ); + +/* + * JASC 2006 + * + * Enable this block to make dragging a directory opens a file dialog + * is not a good idea since windows file manages is better + * + * if ( dragDropIdx == 1 ) // Test posibility of a directory + * { DragQueryFile( (HDROP)dragDropHnd // DragQueryFile is very overloaded + * , 1 + * , dragDropName + * , sizeof( dragDropName )); + * + * if ( GetFileAttributes( dragDropName ) & FILE_ATTRIBUTE_DIRECTORY ) + * { dragDropIdx= -1; // Mark as directory + * } + * } + */ + return( 7 ); + + case WM_PASTE: + Beep(); + return( 1 ); + + case WM_QUIT: + storedEvent.what= evCommand; + storedEvent.message.command= cmQuit; + DestroyWindow( hwnd ); + return( 1 ); + + case WM_DESTROY: /* send a WM_QUIT to the messagequeue */ + PostQuitMessage(0); + exit( 0 ); + + case WM_MOVE: /* Catch the window position */ + wGeo.left= LOWORD( lParam ); + wGeo.top = HIWORD( lParam ); + return( 0 ); + + case WM_SIZE: + sizeChanged++; + if ( primary.w ) + { switch( wParam ) + { case SIZE_MINIMIZED: + return(0); + + case SIZE_RESTORED: + if ( !lParam ) + { return( 1 ); + } + + case SIZE_MAXIMIZED: + w= LOWORD( lParam ); /* JASC, Integer aritmetics */ + h= HIWORD( lParam ); /* JASC, Integer aritmetics */ + + w+= primary.w / 2; h+= primary.h / 2; /* quantize (nearest) */ + w/= primary.w ; h/= primary.h ; + + TScreen::screenWidth = w < 0x100 ? w : 0xFF; /* TScreen::screenWidth is a uchar !!! */ + TScreen::screenHeight= h < 0x100 ? h : 0xFF; /* TScreen::screenHeight is a uchar !!! */ + winRecalc(); + break; + } + } + return( 4 ); + + case WM_PAINT: /* The window needs to be painted (redrawn). */ + BeginPaint( hwnd, &ps ); + + if ( !sizeChanged ) /* if size changed, later repainting. crash repaninting now */ + { if ( TScreen::screenBuffer ) + { int x= ps.rcPaint.left / primary.w; + int y= ps.rcPaint.top / primary.h; + int w= ps.rcPaint.right / primary.w; + int h= ps.rcPaint.bottom/ primary.h; + + w-= x; h -= y; + + unsigned ofs= getCols()*y+x; + ushort *src= TScreen::screenBuffer+ofs; + + forceRedraw++ ; + + while (h>=0) + { TScreen::setCharacters( ofs + , src + , w+1 ); + src+= getCols(); /* Next line */ + ofs+= getCols(); + h --; y ++; /* A line minus left */ + } + } + } + + forceRedraw= 0; + EndPaint( hwnd, &ps ); + return( 5 ); + } + + return( 0 ); /* for messages that we don't deal with */ +} + + +/* + * + */ +LRESULT CALLBACK WindowProcedure( HWND hwnd /* This function is called by the Windowsfunction DispatchMessage( ) */ + , UINT message + , WPARAM wParam + , LPARAM lParam ) +{ int res; + + if ( THWMouseWinGr::hwnd ) + + { if ( TDisplayWinGr::primary.h ) /* Cells on screen */ + { if ( THWMouseWinGr::testEvents( message /* Try for mouse envens */ + , wParam + , lParam )) + { return( 0 ); /* Mouse event found */ + } + } + + + if ( TGKeyWinGr::testEvents( message /* Try for key envens */ + , wParam + , lParam )) + { return( 0 ); /* Key event found */ + } + + + if ( TDisplayWinGr::testEvents( message /* Try another interesting envents */ + , wParam + , lParam )) + { return( 0 ); /* Interesting event found */ + } + } + + res= DefWindowProc( hwnd // Other events must be forwardwed + , message + , wParam + , lParam ); +/* + * JASC, from WIN32 app reference: + * + * Threads that do not contain windows should use the Sleep function + * with a sleep time of zero milliseconds + * to give up the remainder of their current time slice. + */ + + + return( res ); + +} + +/* + * JASC 2002 + * + * Main windows queue + * + * first feeds drag 'n' drop files to the caller + * Processes windows messages + * releases CPU inan adaptative way. + * + */ + + +bool TDisplayWinGr::processEvent( ) +{ static int timer= 1; + + MSG message; /* Here messages to the application is saved */ + + switch ( dragDropIdx ) // Pending drag ´n´ drop + { case 0: break; +/* + * For dragging directories, not a good idea + * case -1: + * SetCurrentDirectory( dragDropName ); + * storedEvent.what= evCommand; + * storedEvent.message.command= cmOpen; // Use this old editor command + * storedEvent.message.infoPtr= NULL; // Opens a file dialog + * dragDropIdx= 0; + * return( true ); + */ + default: + storedEvent.what= evCommand; + storedEvent.message.command= cmOpen; // Use this old editor command + storedEvent.message.infoPtr= dragDropName; // Point to the file name + + DragQueryFile( (HDROP)dragDropHnd // Load name + , -- dragDropIdx + , dragDropName + , sizeof( dragDropName )); + + if ( GetFileAttributes( dragDropName ) + & ( FILE_ATTRIBUTE_DIRECTORY + | FILE_ATTRIBUTE_TEMPORARY + | FILE_ATTRIBUTE_OFFLINE )) + { storedEvent.what= evNothing; + } + + if ( !dragDropIdx ) // Free resources last time + { DragFinish( (HDROP) dragDropHnd ); + dragDropHnd= 0; + } + return( true ); + } + + if ( timer > 100 ) // Adaptative timer + { timer= 100 ; + } + + if ( MsgWaitForMultipleObjects + ( 0 // Handles in the object array + , NULL // Handle array + , false // D'ont care + , timer ++ + , QS_ALLINPUT ) == WAIT_OBJECT_0 ) // Wait for every message + { if ( GetMessage( &message + , NULL // Default window + , 0, 0 )) // All messages + switch( message.message ) // Catch some keys + { case WM_KEYUP: + case WM_KEYDOWN: + TGKeyWinGr::testEvents( message.message /* Try for key envens */ + , message.wParam + , message.lParam ); + } + + if ( message.message != WM_TIMER ) + { timer= 0; /* Reset adaptative counter */ + } + + TranslateMessage( &message ); /* Arrange key events */ + DispatchMessage ( &message ); /* Send message to WindowProcedure */ + return( true ); + } + return( false ); +} + + +/* + * JASC, jul 2002 + * + */ +void TDisplayWinGr::SetCursorPos( unsigned x + , unsigned y ) +{ if (( x != (unsigned)xPos ) + || ( y != (unsigned)yPos )) + { lowSetCursor( xPos // Remove old cursor + , yPos + , false ); + } + + xPos= x; yPos= y; // Update cursor position + lowSetCursor( x + , y + , true ); + } + +/* + * + */ +void TDisplayWinGr::GetCursorPos( unsigned & x + , unsigned & y ) +{ x= xPos; + y= yPos; +} + + +/* + * + */ + void TDisplayWinGr::GetCursorShape( unsigned & start // From SET code + , unsigned & end ) +{ start= cShapeFr; start*= 100; start/= primary.h; // Force integer aritmethic + end = cShapeTo; end *= 100; end /= primary.h; +} + + +/* + * + */ +void TDisplayWinGr::SetCursorShape( unsigned start // From SET code + , unsigned end ) +{ lowSetCursor( xPos // First of all, remove old cursor + , yPos + , false ); + + cShapeFr= ( start*primary.h ) / 100; // Force integer aritmethic + cShapeTo= ( end*primary.h ) / 100; + + if ( start>=end && getShowCursorEver() ) + { return; + } + + if ((unsigned)cShapeFr > (unsigned)primary.h ) // Pretty range test ( 1 test 2 comprobations ) + { cShapeFr= primary.h; + } + + if ((unsigned)cShapeTo > (unsigned)primary.h ) // Pretty range test ( 1 test 2 comprobations ) + { cShapeTo= primary.h; + } + + if ( start >= end ) + { zPos |= 1; /* Disable cursor */ + } + else + { zPos &= ~1; + } + + lowSetCursor( xPos + , yPos + , true ); +} + + +/* + * + */ +ushort TDisplayWinGr::GetRows() +{ return( TScreen::screenHeight ); +} + +/* + * + */ +ushort TDisplayWinGr::GetCols() +{ return( TScreen::screenWidth ); +} + + +/* + * + */ +int TDisplayWinGr::CheckForWindowSize() +{ int ret= sizeChanged; + + sizeChanged= 0; + return( ret ); +} + +/* + * Retrieves window manager window title + */ +const char * TDisplayWinGr::GetWindowTitle(void) +{ static char buff[ maxTitleSize ]; + + GetWindowText( hwnd + , buff + , sizeof( buff) ); + + return( buff );} + + +/* + * Window manager window title + */ +int TDisplayWinGr::SetWindowTitle( const char *name ) +{ SetWindowText( hwnd + , name ); + + return(0); +} + + +/* + * Returns hardware video mode + */ +ushort TDisplayWinGr::GetCrtMode() +{ return( TScreen::screenMode ); +} + + +/* + * JASC, feb 2006 + * + * Emulates harware crt mode + * + * The CRT mode controls three ortogonaly arranged hardware properties, + * colors, font size, and screen resolution, but the interface only takes one. + * As a solution, the tree "colored" modes ( BW80, CO80 and Mono ) + * can change the color (and put a standard font if no one), the other modes + * manage the font and display size in fixed steps, and the user change to + * other window sizes. + * + */ +void TDisplayWinGr::SetCrtMode( ushort newMode ) +{ const VideoModeData * ptr; + + SetCursorShape(0x58,0x64); + + if ( newMode == 0xFFFF ) + { return; + } + + switch ( newMode ) + { case smBW80: /* SET fonts */ + case smCO80: + case smMono: + if ( !TScreenWinGr::screenWidth ) /* Respect previous changes */ + { TScreenWinGr::screenWidth= 80; + } + + if ( !TScreenWinGr::screenHeight ) + { TScreenWinGr::screenHeight= 25; + } + + if ( !TScreenWinGr::screenMode ) + { selectFont( primary, TScreenWinGr::defaultFont ); + selectFont( secondary, TScreenWinGr::defaultFont ); + } + + TScreen::screenMode= newMode; + break; + + default: /* Windows fonts */ + SetFontMode( primary, newMode ); + SetFontMode( secondary, newMode ); + + for( ptr= videoModes + ; ptr->mode + ; ptr ++ ) + { if ( (ushort)ptr->mode == newMode ) + { TScreenWinGr::screenWidth= ptr->wScreen; + TScreenWinGr::screenHeight= ptr->hScreen; + } + } + break; + } + sizeChanged++; +} + +/* + * Try to find a suitable font + */ +typedef struct +{ LONG minError; /* Keeps track of the more adjusted font */ + LONG desiredW; /* The size we are locking for */ + LONG desiredH; + ushort fontW; /* More adjusted font size */ + ushort fontH; +} fontData; + + +int CALLBACK checkFonts( const LOGFONTA * lplf // address of logical-font data structure + , const TEXTMETRIC * lpntm // address of physical-font data structure + , long unsigned int // type of font + , LPARAM lpData ) // address of application-defined data +{ fontData * data= (fontData *) lpData; + + if ( lplf->lfItalic ) // No italics (bad box drawings) + { return( 2 ); + } + + if ( lplf->lfUnderline ) // No underlines (evident) + { return( 3 ); + } + + if ( lpntm->tmPitchAndFamily // Only fixed width + & TMPF_FIXED_PITCH ) + { return( 4 ); + } + +/* + * Estimate the average error as sum of sqares + */ + int ew= lpntm->tmMaxCharWidth - data->desiredW; ew *= ew; + int eh= lpntm->tmHeight - data->desiredH; eh *= eh; + + long error= ew + eh; + + TDisplayWinGr::foWmin= lpntm->tmMaxCharWidth + < TDisplayWinGr::foWmin + ? lpntm->tmMaxCharWidth + : TDisplayWinGr::foWmin; + + TDisplayWinGr::foWmax= lpntm->tmMaxCharWidth + > TDisplayWinGr::foWmax + ? lpntm->tmMaxCharWidth + : TDisplayWinGr::foWmax; + + TDisplayWinGr::foHmin= lpntm->tmHeight + < TDisplayWinGr::foHmin + ? lpntm->tmHeight + : TDisplayWinGr::foHmin; + + TDisplayWinGr::foHmax= lpntm->tmHeight + > TDisplayWinGr::foHmax + ? lpntm->tmHeight + : TDisplayWinGr::foHmax; + + if ( error < data->minError ) + { data->minError= error; + data->fontW = lpntm->tmMaxCharWidth; + data->fontH = lpntm->tmHeight; + } + + return( 1 /* error */ ); /* rerunrning "error" stops if the font matchs */ +} + + +/* + * + * + */ +int TDisplayWinGr::SetCrtModeRes( unsigned fW + , unsigned fH ) +{ fontData suitable; + + suitable.minError= 0x7FFF; + suitable.desiredW= fW; + suitable.desiredH= fH; + + EnumFontFamilies( hdc /* Iterate font list */ + , "Terminal" + , checkFonts + , (LPARAM)&suitable ); + + if (( fW == 8 ) && ( fH == 16 )) + { selectFont( primary, &TDisplayWinGr::font8x16 ); + selectFont( secondary, &TDisplayWinGr::font8x16 ); + return( 1 ); + } + + if (( fW == 10 ) && ( fH == 20 )) + { selectFont( primary, &TDisplayWinGr::font10x20 ); + selectFont( secondary, &TDisplayWinGr::font10x20 ); + return( 1 ); + } + + SetFontCrt( primary, suitable.fontW, suitable.fontH ); + SetFontCrt( secondary, suitable.fontW, suitable.fontH ); + + sizeChanged++; + return( 0 ); +} + +/* + * + * + */ +void TDisplayWinGr::TestAllFonts( unsigned fW + , unsigned fH ) + +{ fontData suitable; + + HDC hdc= CreateIC( "DISPLAY" + , "" + , NULL + , NULL ); + + suitable.minError= 0x7FFF; + suitable.desiredW= fW; + suitable.desiredH= fH; + + EnumFontFamilies( hdc /* Iterate font list */ + , "Terminal" + , checkFonts + , (LPARAM)&suitable ); + DeleteDC( hdc ); /* Free resources */ + + if (( fW == 8 ) && ( fH == 16 )) + { primary.w= secondary.w= fW; + primary.h= secondary.h= fH; + return; + } + + if (( fW == 10 ) && ( fH == 20 )) + { primary.w= secondary.w= fW; + primary.h= secondary.h= fH; + return; + } + + primary.w= secondary.w= suitable.fontW; /* Best fitting */ + primary.h= secondary.h= suitable.fontH; +} + + +/* + * Free resources + */ +TDisplayWinGr::~TDisplayWinGr() +{ +} + +/* + * Tries a beep in the sound card. If not, the speaker !!! + */ +void TDisplayWinGr::Beep() +{ MessageBeep(0xFFFFFFFF); +} + +/* + * Links funnction pointers + */ +void TDisplayWinGr::Init() +{ getRows= GetRows; + getCols= GetCols; + setCrtMode= SetCrtMode; + getCrtMode= GetCrtMode; + setCursorPos= SetCursorPos; + getCursorPos= GetCursorPos; + setWindowTitle= SetWindowTitle; + getWindowTitle= GetWindowTitle; + getCursorShape= GetCursorShape; + setCursorShape= SetCursorShape; + checkForWindowSize= CheckForWindowSize; + beep= Beep; + +// TProgram::doNotReleaseCPU= true; // annoys windows loop, implemented here + +} + + +#else + +#include +#include +#include + +#endif // TVOS_Win32 + + diff --git a/tvision/classes/wingr/wingrkey.cc b/tvision/classes/wingr/wingrkey.cc new file mode 100644 index 0000000..16a9fa3 --- /dev/null +++ b/tvision/classes/wingr/wingrkey.cc @@ -0,0 +1,517 @@ +/**[txh]******************************************************************** + + Copyright (c) 2002 by Jose Angel Sanchez Caso (JASC) + + Covered by the GPL license. + + It said: + + Console code based on code by Vadim Beloborodov + Squeleton based on code by Salvador E. Tropea (SET) (c) (1998) + windows GUI code by Jose Angel Sanchez Caso (JASC). + + Description: + Windows Keyboard routines. + +***************************************************************************/ +#include + +#define Uses_ctype +#define Uses_string +#define Uses_TEvent +#define Uses_TGKey +#define Uses_TKeys +#define Uses_TKeys_Extended +#define Uses_TDisplay +#define Uses_TScreen +#define Uses_TVCodePage +#include + +#if defined(TVOS_Win32) && !defined(TV_Disable_WinGr_Driver) + +#define WIN32_LEAN_AND_MEAN +#include + +#include +#include +#include + +/* else + sprintf( buff + , " SHIFT %u" + " CHARCODE %u" + " KEYCODE %u" + " SCANCODE %u " + , keyMask + , storedEvent.keyDown.charScan.charCode + , storedEvent.keyDown.keyCode + , storedEvent.keyDown.charScan.scanCode ); + + TScreenWinGr::writeLine( 1 + , 7 + , strlen(buff) + , buff + , 0xF1 ); + { + sprintf( buff + , " CHAR keycode: %d charcode: %d scancode: %d mask %d" + , storedEvent.keyDown.keyCode + , storedEvent.keyDown.charScan.charCode + , storedEvent.keyDown.charScan.scanCode + , storedEvent.keyDown.shiftState); + + TScreenWindows::writeLine( 1 + , 3 + , strlen(buff) + , buff + , 0xF1 ); } + static int rt= 0; + char buff[512]; + + */ + +/* + * Translate keyboard events to Salvador E. Tropea's key codes + * by Vadim Beloborodov + * Originally in trans.cc + */ + +ushort TGKeyWinGr::keyMask= 0; +CodePage * TGKeyWinGr::remapKey= NULL; // Multilingual keyboard support + + + +/* + * JASC, not implemented key codes ( may be in future ) + * + * VK_LBUTTON ( 1) + * VK_MBUTTON ( 4) + * VK_RBUTTON ( 2) + * VK_F13 (124) + * VK_F14 (125) + * VK_F15 (126) + * VK_F16 (127) + * VK_F17 (128) + * VK_F18 (129) + * VK_F19 (130) + * VK_F20 (131) + * VK_F21 (132) + * VK_F22 (133) + * VK_F23 (134) + * VK_F24 (135) + * + * VK_CANCEL ( 3) + * VK_CLEAR ( 12) + * VK_PAUSE ( 19) + * VK_SELECT ( 41) + * VK_EXECUTE ( 43) + * VK_SNAPSHOT ( 44) + * VK_HELP ( 47) + * + * kbWinLeft = 0x0063 + * kbWinRight= 0x0064 + * kbWinSel = 0x0065 + * + * + * , { '{' , kbOpenCurly , '{', 0 } 0x005f + * , { '|' , kbOr , '|', 0 } 0x005d + * , { '}' , kbCloseCurly , '}', 0 } 0x0060 + * , { '~' , kbTilde , '~', 0 } 0x0061 + * , { '' , kbMacro , '', 0 } + * , { 'Ç' , kbBackSpace , 'Ç', 0 } + *, { '!' , kbAdmid , '!', 0 } 0x0050 + *, { '"' , kbDobleQuote , '"', 0 } 0x0051 + *, { '#' , kbNumeral , '#', 0 } 0x0052 + * , { '$' , kbDolar , '$', 0 } 0x0053 + * , { '%' , kbPercent , '%', 0 } 0x0054 + * , { '&' , kbAmper , '&', 0 } 0x0055 + * , { '\'' , kbQuote , '\'', 0} 0x002e + * , { '(' , kbOpenPar , '(', 0 } 0x0056 + * , { ')' , kbClosePar , ')', 0 } 0x0057 + * , { ':' , kbDoubleDot , ':', 0 } 0x0058 + * , { ';' , kbColon , ';', 0 } 0x002d + * , { '<' , kbLessThan , '<', 0 } 0x0059 + * , { '=' , kbEqual , '=', 0 } 0x0038 + * , { '>' , kbGreaterThan, '>', 0 } 0x005a + * , { '?' , kbQuestion , '?', 0 } 0x005b + * , { '@' , kbA_Roba , '@', 0 } 0x005c + + * , { '[' , kbOpenBrace , '[', 0 } 0x001B + * , { ']' , kbCloseBrace , ']', 0 } 0x001D + * , { '^' , kbCaret , '^', 0 } 0x004f + * , { '_' , kbUnderLine , '_', 0 } 0x005e */ + +/*, { '0' , kb0 , '0', 0x45 } +, { '1' , kb1 , '1', 0x16 } +, { '2' , kb2 , '2', 0x1E } +, { '3' , kb3 , '3', 0x26 } +, { '4' , kb4 , '4', 0x25 } +, { '5' , kb5 , '5', 0x2E } +, { '6' , kb6 , '6', 0x36 } +, { '7' , kb7 , '7', 0x3D } +, { '8' , kb8 , '8', 0x3E } +, { '9' , kb9 , '9', 0x46 } +, { VK_NUMPAD0 , kb0 , '0', 0x70 } +, { VK_NUMPAD1 , kb1 , '1', 0x69 } +, { VK_NUMPAD2 , kb2 , '2', 0x72 } +, { VK_NUMPAD3 , kb3 , '3', 0x7A } +, { VK_NUMPAD4 , kb4 , '4', 0x6B } +, { VK_NUMPAD5 , kb5 , '5', 0x73 } +, { VK_NUMPAD6 , kb6 , '6', 0x74 } +, { VK_NUMPAD7 , kb7 , '7', 0x6C } +, { VK_NUMPAD8 , kb8 , '8', 0x75 } +, { VK_NUMPAD9 , kb9 , '9', 0x7D } + +, { 'A' , kbA , 'A', 0x1C } +, { 'B' , kbB , 'B', 0x32 } +, { 'C' , kbC , 'C', 0x21 } +, { 'D' , kbD , 'D', 0x23 } +, { 'E' , kbE , 'E', 0x24 } +, { 'F' , kbF , 'F', 0x2B } +, { 'G' , kbG , 'G', 0x34 } +, { 'H' , kbH , 'H', 0x33 } +, { 'I' , kbI , 'I', 0x43 } +, { 'J' , kbJ , 'J', 0x3B } +, { 'K' , kbK , 'K', 0x42 } +, { 'L' , kbL , 'L', 0x4B } +, { 'M' , kbM , 'M', 0x3A } +, { 'N' , kbM , 'N', 0x31 } +, { 'O' , kbO , 'O', 0x44 } +, { 'P' , kbP , 'P', 0x4D } +, { 'Q' , kbQ , 'Q', 0x15 } +, { 'R' , kbR , 'R', 0x2D } +, { 'S' , kbS , 'S', 0x1B } +, { 'T' , kbT , 'T', 0x2C } +, { 'U' , kbU , 'U', 0x3C } +, { 'V' , kbV , 'V', 0x2A } +, { 'W' , kbW , 'W', 0x1D } +, { 'X' , kbX , 'X', 0x22 } +, { 'Y' , kbY , 'Y', 0x35 } +, { 'Z' , kbZ , 'Z', 0x1A } +{ VK_SPACE , kbSpace , ' ', 0x29 } +//, { VK_MULTIPLY , kbAsterisk , '*', 0 } +//, { VK_ADD , kbPlus , '+', 0 } +//, { VK_SEPARATOR, kbBackSlash , ',', 0 } +//, { VK_SUBTRACT , kbMinus , '-', 0 } +//, { VK_DECIMAL , kbGrave , '.', 0 } +//, { VK_DIVIDE , kbSlash , '/', 0 } +//, { VK_SEPARATOR, kbBackSlash , '\\', 0} +//, { VK_DECIMAL , kbGrave , '`', 0 } + + */ + + +ConvKeyRec xlateTableKeys[]= +{{ ' ' , kbSpace } +,{ VK_UP , kbUp } /* Move up, up arrow */ +,{ VK_ESCAPE , kbEsc } +,{ VK_TAB , kbTab } +,{ VK_HOME , kbHome } +,{ VK_END , kbEnd } /* EOL */ +,{ VK_LEFT , kbLeft } /* Move left, left arrow */ +,{ VK_RIGHT , kbRight } /* Move right, right arrow */ +,{ VK_UP , kbUp } /* Move down, down arrow */ +,{ VK_DOWN , kbDown } /* Move down, down arrow */ +,{ VK_PRIOR , kbPgUp } +,{ VK_NEXT , kbPgDn } +,{ VK_RETURN , kbEnter } /* Return, enter */ +,{ VK_PAUSE , kbPause } /* Pause, hold */ +,{ VK_DELETE , kbDelete } /* Delete, rubout */ +,{ VK_INSERT , kbInsert } /* Insert, insert here */ +,{ VK_PRINT , kbPrnScr } +,{ VK_BACK , kbBackSpace } /* back space, back char */ + +,{ VK_F1 , kbF1 } +,{ VK_F2 , kbF2 } +,{ VK_F3 , kbF3 } +,{ VK_F4 , kbF4 } +,{ VK_F5 , kbF5 } +,{ VK_F6 , kbF6 } +,{ VK_F7 , kbF7 } +,{ VK_F8 , kbF8 } +,{ VK_F9 , kbF9 } +,{ VK_F10 , kbF10 } +,{ VK_F11 , kbF11 } +,{ VK_F12 , kbF12 } +,{ 0 , 0 }}; /* Terminator */ + +ConvKeyRec xlateTableChars[]= +{{ ' ' , kbSpace } +,{ '0' , kb0 } +,{ '1' , kb1 } +,{ '2' , kb2 } +,{ '3' , kb3 } +,{ '4' , kb4 } +,{ '5' , kb5 } +,{ '6' , kb6 } +,{ '7' , kb7 } +,{ '8' , kb8 } +,{ '9' , kb9 } +,{ 'A' , kbA } +,{ 'B' , kbB } +,{ 'C' , kbC } +,{ 'D' , kbD } +,{ 'E' , kbE } +,{ 'F' , kbF } +,{ 'G' , kbG } +,{ 'H' , kbH } +,{ 'I' , kbI } +,{ 'J' , kbJ } +,{ 'K' , kbK } +,{ 'L' , kbL } +,{ 'M' , kbM } +,{ 'N' , kbM } +,{ 'O' , kbO } +,{ 'P' , kbP } +,{ 'Q' , kbQ } +,{ 'R' , kbR } +,{ 'S' , kbS } +,{ 'T' , kbT } +,{ 'U' , kbU } +,{ 'V' , kbV } +,{ 'W' , kbW } +,{ 'X' , kbX } +,{ 'Y' , kbY } +,{ 'Z' , kbZ } +,{ 0 , 0 }}; /* Terminator */ + + +/* + * Driver entry, tells caller last know shift state + * + * + * those are not totally implemeted on TVISION + * + * + * GetKeyState( VK_CAPITAL ) & TOGGLED_KEY ? kbCapsLockToggle : 0 + * GetKeyState( VK_INSERT ) & TOGGLED_KEY ? kbInsertToggle : 0 + * + * GetKeyState( VK_SCROLL ) & PRESSED_KEY ? kbScrollLockDown : 0 + * GetKeyState( VK_CAPITAL ) & PRESSED_KEY ? kbCapsLockDown : 0 + * GetKeyState( VK_NUMLOCK ) & PRESSED_KEY ? kbNumLockDown : 0 + * GetKeyState( VK_SNAPSHOT ) & PRESSED_KEY ? kbSysReqPress : 0 + * + * GetKeyState( VK_SCROLL ) & TOGGLED_KEY ? kbScrollLockToggle : 0 + * + * GetKeyState( VK_NUMLOCK ) & TOGGLED_KEY ? kbNumLockToggle : 0 + */ + + +#define TOGGLED_KEY 0x01 /* The key is toggled */ +#define PRESSED_KEY 0x80 /* The key is pressed */ + +unsigned TGKeyWinGr::GetShiftState() +{ return( keyMask ); +} + + +int TGKeyWinGr::setKey( const ConvKeyRec * xlate + , int vcode ) +{ const ConvKeyRec * ptr; + + for( ptr= xlate /* Scan the special key table */ + ; ptr->win + ; ptr++ ) + { if (ptr->win == vcode ) + { storedEvent.what= evKeyDown; + storedEvent.keyDown.keyCode= ptr->key | keyMask; + storedEvent.keyDown.charScan.charCode= 0; + return( vcode ); + } + } + return(0); +} + +#include + +/* + * + */ +int TGKeyWinGr::testEvents( UINT message + , WPARAM wParam + , LPARAM lParam ) +{ storedEvent.what= evNothing; + + switch( message ) + { case WM_CHAR: + case WM_KEYDOWN: + case WM_SYSCHAR: + case WM_SYSKEYDOWN: + keyMask= /* Adapt keymask to TVISION */ + (( GetKeyState( VK_LSHIFT ) & PRESSED_KEY ? kbShiftCode : 0 ) + |( GetKeyState( VK_RSHIFT ) & PRESSED_KEY ? kbShiftCode : 0 ) + |( GetKeyState( VK_SHIFT ) & PRESSED_KEY ? kbShiftCode : 0 ) + |( GetKeyState( VK_LCONTROL) & PRESSED_KEY ? kbCtrlCode : 0 ) + |( GetKeyState( VK_RCONTROL) & PRESSED_KEY ? kbCtrlCode : 0 ) + |( GetKeyState( VK_CONTROL ) & PRESSED_KEY ? kbCtrlCode : 0 ) + |( GetKeyState( VK_LMENU ) & PRESSED_KEY ? kbAltLCode : 0 ) + |( GetKeyState( VK_RMENU ) & PRESSED_KEY ? kbAltRCode : 0 )); + + if ( keyMask & kbAltRCode ) + { keyMask&= ~kbCtrlCode; + } + storedEvent.keyDown.shiftState= keyMask; + storedEvent.keyDown.charScan.scanCode= + storedEvent.keyDown.raw_scanCode= ( lParam >> 16 ) & 0xFF; + } + + + switch( message ) + { case WM_SYSKEYDOWN: + case WM_KEYDOWN: + + if ( keyMask ) /* key + alt or ctrl */ + { if ( setKey( xlateTableChars + , wParam )) + { return( 1 ); + } + } + + if ( setKey( xlateTableKeys + , wParam )) + { if ( keyMask & kbAltRCode ) // Emulate alt for system keys + { keyMask &= ~kbAltRCode; + storedEvent.keyDown.keyCode&= ~kbAltRCode; + keyMask |= kbAltLCode; + storedEvent.keyDown.keyCode|= kbAltLCode; + } + else + { if ( keyMask & kbAltLCode ) // Windows event ? + { storedEvent.what= evNothing; // Give event to win + return( 0 ); + } + } + + return( 1 ); /* good event */ + } + break; + + case WM_SYSCHAR: /* (fixme) Block windows system keys, fix: not all of then must be blocked */ + return( 1 ); + + case WM_CHAR: + if( wParam >= 32 ) + { storedEvent.what= evKeyDown; + storedEvent.keyDown.charScan.charCode= wParam; + storedEvent.keyDown.keyCode= storedEvent.keyDown.shiftState; + } + +/* if ( remapKey ) + { if ( wParam>127 ) + { storedEvent.keyDown.charScan.charCode= remapKey->Font[ wParam - 128 ]; + } + } + */ + return( 2 ); /* good event */ + + } + + return(0); +} + + + +/* + * + */ + +int TGKeyWinGr::KbHit(void) +{ do + { + switch( storedEvent.what ) /* Is there a previous event? */ + { case evCommand: /* Windows says "exit" */ + case evKeyDown: /* Key event pending */ + return( evKeyDown ); /* There is a key event waiting */ + + case evMouseUp: + case evMouseDown: + case evMouseMove: + return( evMouseDown ); + } /* Not strictily necessary, but I do */ + } + while ( processEvent() ); /* Swallow new events */ + + return(0); } /* No events on queue */ + + +/* + * + */ + +void TGKeyWinGr::FillTEvent( TEvent &me ) +{ me.what= evNothing; /* The default is no message */ + + do + { switch( storedEvent.what ) /* Is there a previous event? */ + { case evCommand: /* Windows says "exit" */ + case evKeyDown: /* Key event pending */ + me= storedEvent; /* Give stored event */ + storedEvent.what= evNothing; /* Mark events exhausted */ + + case evMouseUp: + case evMouseDown: + case evMouseMove: + return; /* All done, exit function */ + } + } + while ( processEvent() ); /* Swallow new events */ +} + + +/* ------------------------------------------------------------------------- */ + void TGKeyWinGr::init( ) +/* ------------------------------------------------------------------------- */ +{ TGKey::kbhit= KbHit; + TGKey::fillTEvent= FillTEvent; + TGKey::getShiftState= GetShiftState; + +/* + * JASC, whe need a lot of work here since codepage returned by + * GetOEMCP() doesnot match TV codesymbols. only ISO8879_1 tested. + * if your keyboard provides another mapping, choice one from + * available in codepage.cc, test and publish to rhide mailing list o to me + * (jasanchez@polar.es or tachungo@yahoo.es ) + */ + + switch ( GetOEMCP() ) + { case 737: remapKey= &stPC737; break; // Greek (formerly 437G) + case 775: remapKey= &stPC775; break; // Baltic + case 850: remapKey= &ISO8879_1; break; // MS-DOS Multilingual (Latin I) ( JASC, only this is tested ) + case 852: remapKey= &stPC852; break; // MS-DOS Slavic (Latin II) + case 855: remapKey= &stPC855; break; // IBM Cyrillic (primarily Russian) + case 857: remapKey= &stPC857; break; // IBM Turkish + case 860: remapKey= &stPC860; break; // MS-DOS Portuguese + case 861: remapKey= &stPC861; break; // MS-DOS Icelandic + case 863: remapKey= &stPC863; break; // MS-DOS Canadian-French + case 865: remapKey= &stPC865; break; // MS-DOS Nordic + case 866: remapKey= &stPC866; break; // MS-DOS Russian (former USSR) + case 869: remapKey= &stPC869; break; // IBM Modern Greek + + +/* + * Not supported by SET's code pagger + */ + case 708: // Arabic (ASMO 708) + case 709: // Arabic (ASMO 449+, BCON V4) + case 710: // Arabic (Transparent Arabic) + case 720: // Arabic (Transparent ASMO) + case 862: // Hebrew + case 864: // Arabic + case 874: // Thai + case 932: // Japan + case 936: // Chinese (PRC, Singapore) + case 949: // Korean + case 950: // Chinese (Taiwan, Hong Kong) + case 1361: // Korean (Johab) + + case 437: remapKey= NULL; }} // MS-DOS United States, native format + + +#else + +#include +#include +#include + +#endif // TVOS_Win32 + diff --git a/tvision/classes/wingr/wingrmouse.cc b/tvision/classes/wingr/wingrmouse.cc new file mode 100644 index 0000000..3cd860e --- /dev/null +++ b/tvision/classes/wingr/wingrmouse.cc @@ -0,0 +1,188 @@ +/**[txh]******************************************************************** + + Copyright (c) 2002 by Jose Angel Sanchez Caso (JASC) + + Covered by the GPL license. + + Squeletons and modeling by Salvador E. Tropea (SET) (c) (1998) + + THWindows mouse stuff. + +*****************************************************************************/ +#include + +#define Uses_TDisplay +#define Uses_TScreen +#define Uses_TGKey +#define Uses_TMouse +#define Uses_TEvent +#define Uses_TEventQueue +#define Uses_TVCodePage +#include + +#if defined(TVOS_Win32) && !defined(TV_Disable_WinGr_Driver) + +// #define WIN32_LEAN_AND_MEAN +#include + +#include +#include +#include + +bool THWMouseWinGr::pressed= false; /* JASC, feb 2006, must be known */ +HCURSOR THWMouseWinGr::lastCursor= NULL; + + +/* + * + */ +int THWMouseWinGr::setMouse( LPARAM lParam + , int ev ) +{ storedEvent.what= ev; + storedEvent.mouse.doubleClick= False; + + storedEvent.mouse.where.x = (short)LOWORD( lParam ) < 0 ? 0 + : (short)LOWORD( lParam ); + storedEvent.mouse.where.x/= primary.w; + + storedEvent.mouse.where.y = (short)HIWORD( lParam ) < 0 ? 0 + : (short)HIWORD( lParam ); + + storedEvent.mouse.where.y/= primary.h; + + switch( ev ) + { case evMouseUp: + ReleaseCapture(); pressed= false; + break; + + case evMouseDown: /* Store press coordinates */ + SetCapture( hwnd ); pressed= true; + break; + + case evMouseMove: + if ( pressed ) /* Mouse is down */ + { if ( lastCursor != sizeCursor ) /* Not in the resizing area */ + { break; + } + + storedEvent.what= evNothing; /* Not a system event */ + storedEvent.mouse.where.x += 1; + storedEvent.mouse.where.y += 1; + + if ( TScreen::screenWidth == storedEvent.mouse.where.x + && TScreen::screenHeight == storedEvent.mouse.where.y ) + { break; /* No resizing needed */ + } + + TScreen::screenWidth = storedEvent.mouse.where.x < 0x100 ? storedEvent.mouse.where.x : 0xFF; ; + TScreen::screenHeight= storedEvent.mouse.where.y < 0x100 ? storedEvent.mouse.where.y : 0xFF;; + winRecalc( ); /* Recalc new window size */ + break; + } + + if ( ! storedEvent.mouse.where.y ) + { lastCursor= handCursor; + } + else + { if ( storedEvent.mouse.where.y > ( TScreen::screenHeight-2 )) + { lastCursor= storedEvent.mouse.where.x > ( TScreen::screenWidth-2 ) + ? sizeCursor + : handCursor; + } + else + { lastCursor= normCursor; + } + } + } + + SetCursor( lastCursor ); + return(0); +} + + +/* + * + */ +int THWMouseWinGr::testEvents( UINT message + , WPARAM wParam + , LPARAM lParam ) +{ switch( message ) + { case WM_MOUSEMOVE: setMouse( lParam, evMouseMove ); break; + case WM_LBUTTONUP: setMouse( lParam, evMouseUp ); break; + case WM_MBUTTONUP: setMouse( lParam, evMouseUp ); break; + case WM_RBUTTONUP: setMouse( lParam, evMouseUp ); break; + case WM_LBUTTONDOWN: setMouse( lParam, evMouseDown ); break; + case WM_MBUTTONDOWN: setMouse( lParam, evMouseDown ); break; + case WM_RBUTTONDOWN: setMouse( lParam, evMouseDown ); break; + + case WM_MOUSEWHEEL : + storedEvent.what= evMouseMove; /* Emulate wheel */ + storedEvent.mouse.where.x= (short)LOWORD( lParam ) / primary.w; + storedEvent.mouse.where.y= (short)HIWORD( lParam ) / primary.h; + storedEvent.mouse.buttons= ((short) HIWORD( wParam )) > 0 ? mbButton4 : mbButton5; + return( message ); /* Was a mouse event */ + + default: return( 0 ); + } + + storedEvent.mouse.buttons= ( wParam & MK_LBUTTON ) ? mbLeftButton : 0 + | ( wParam & MK_MBUTTON ) ? mbMiddleButton : 0 + | ( wParam & MK_RBUTTON ) ? mbRightButton : 0 ; + + return( message ); /* Was a mouse event */ +} + + + + +/* + * + */ +void THWMouseWinGr::GetEvent( MouseEventType & me ) +{ static int xOld= 0; /* Persistent across calls */ + static int yOld= 0; /* Persistent across calls */ + static int bOld= 0; /* Persistent across calls */ + + me.buttons= bOld; + me.where.x= xOld; + me.where.y= yOld; + + do + { + switch( storedEvent.what ) /* Is there a previous event? */ + { case evCommand: /* Windows says "exit" */ + return; + + case evMouseUp: + case evMouseDown: + case evMouseMove: + me= storedEvent.mouse; /* Give stored event */ + bOld= me.buttons; /* The default is no message */ + xOld= me.where.x; + yOld= me.where.y; + storedEvent.what= /* Mark as exhausted */ + evNothing; + + + case evKeyDown: /* Key event pending */ + return; }} /* All done, exit function */ + while ( processEvent()); /* Swallow new events */ +} + + +/* + * + */ +void THWMouseWinGr::init( ) +{ THWMouse::GetEvent= THWMouseWinGr::GetEvent; + buttonCount= 5; +} + +#else + +#include +#include +#include + +#endif // TVOS_Win32 + diff --git a/tvision/classes/wingr/wingrscr.cc b/tvision/classes/wingr/wingrscr.cc new file mode 100644 index 0000000..9ee860a --- /dev/null +++ b/tvision/classes/wingr/wingrscr.cc @@ -0,0 +1,776 @@ +/**[txh]******************************************************************** + + Copyright (c) 2002 by Jose Angel Sánchez Caso (JASC) + + -> altomaltes@yahoo.es + -> altomaltes@gmail.com + + Squeletons by Salvador E. Tropea (SET) + + Description: + Windows Screen routines. + + + Defaults loaded from resource file tvrc or .tvrc + + HalfColor -> Palette brightness + FullColor + + ScreenWidth -> Screen font and size + ScreenHeight + FontWidth + FontHeight + Font10x20 + + optSearch + optSearch + optSearch + + +***************************************************************************/ + + +//#define DEBUG + +#include + +#define Uses_string +#define Uses_stdlib +#define Uses_unistd +#define Uses_AllocLocal +#define Uses_TScreen +#define Uses_TEvent +#define Uses_TGKey +#define Uses_TVCodePage +#define Uses_alloca +#define Uses_TVOSClipboard +#include + +#include + + +#if defined(TVOS_Win32) && !defined(TV_Disable_WinGr_Driver) + +#define WIN32_LEAN_AND_MEAN +#include + +#include +#include +#include + +/* Not always defined */ +#ifndef IDC_ARROW + #define IDC_ARROW MAKEINTRESOURCE(32512) +#endif +#ifndef IDC_HAND + #define IDC_HAND MAKEINTRESOURCE(32649) +#endif +#ifndef IDC_SIZENWSE + #define IDC_SIZENWSE MAKEINTRESOURCE(32642) +#endif + + +int TScreenWinGr::amountOfCells= 0; /* Allocated screen cells */ + +DWORD TScreenWinGr::style= WS_CAPTION /* Window style */ + | WS_SYSMENU + | WS_MAXIMIZEBOX + | WS_MINIMIZEBOX; + +/* Window new styles */ + +DWORD TScreenWinGr::exStyle= WS_EX_ACCEPTFILES // Drag 'n' drop files +// | WS_EX_CLIENTEDGE // Raised edge + ; + +long TScreenWinGr::cursorDelay= 300000; +long TScreenWinGr::HalfColor= 0xB0; +long TScreenWinGr::FullColor= 0xFF; + + +/* + * + */ + +int TScreenWinGr::SetFont( int changeP, TScreenFont256 *fontP + , int changeS, TScreenFont256 *fontS + , int fontCP, int appCP ) +{ if (!changeP && !changeS) + { return 1; + } + + if ( !fontP ) + { fontP= defaultFont; + } + + if ( !fontS ) + { fontS= defaultFont; + } + if ( changeP ) + { selectFont( primary, fontP ); + } + + if ( changeS ) + { selectFont( secondary, fontS ); + } + + if ( appCP==-1 ) + { TVCodePage::SetScreenCodePage( fontCP ); + } + else + { TVCodePage::SetCodePage( appCP + , fontCP + ,-1 ); + } + + return( 1 ); +} + +/* + * + */ + +void TScreenWinGr::RestoreFonts() +{ SetFont( 1, NULL + , 1, NULL + , TVCodePage::ISOLatin1Linux + , TVCodePage::ISOLatin1Linux); +} + + +/* + * + */ + +int TScreenWinGr::GetFontGeometry(unsigned &w, unsigned &h) +{ w= primary.w; + h= primary.h; + return 1; +} + +/* + * + */ + +int TScreenWinGr::GetFontGeometryRange( unsigned &wmin, unsigned &hmin + , unsigned &wmax, unsigned &hmax ) +{ wmin= foWmin; + hmin= foHmin; + wmax= foWmax; + hmax= foHmax; + return 1; +} + + +/* + * Time callback to blink the cursor + */ +VOID CALLBACK cursorProc( HWND hwnd // handle of window for timer messages + , UINT uMsg // WM_TIMER message + , UINT idEvent // timer identifier + , DWORD /*dwTime*/ ) // current system time +{ if ( uMsg ) + { TScreenWinGr::zPos ^= 0x80; /* Toggle phase (turn 180 degrees) */ + + if ( TScreenWinGr::xPos >= 0 ) + { TScreenWinGr::lowSetCursor( TScreenWinGr::xPos /* Show or hide cursor */ + , TScreenWinGr::yPos + , true ); + } + } + + SetTimer( hwnd /* Reload timer */ + , idEvent + , TScreenWinGr::cursorDelay / 1000 /* from usecs to msecs */ + , cursorProc ); +} + + +/* + * JASC, 2002 + * + * Make a windows screen + */ +TScreenWinGr::TScreenWinGr() +{ WNDCLASSEX wincl; /* Datastructure for the windowclass */ + STARTUPINFO startinfo; + RECT windowArea; + + TvWinInstance= GetModuleHandle (NULL); + +#ifndef DEBUG /* Use the console to debug messages */ + FreeConsole(); +#endif + + GetStartupInfoA (&startinfo); /* Get the command line passed to the process. */ + +/* + * JASC, ene 2006, now bitmap fonts + */ + + +/* Look for defaults */ + + optSearch("HalfColor", HalfColor ); /* Palette brightness */ + optSearch("FullColor", FullColor ); + +/* + * Screen font and size + */ + + long maxX= 80; optSearch("ScreenWidth" , maxX ); + long maxY= 25; optSearch("ScreenHeight", maxY ); + long fontW= 8; optSearch("FontWidth" , fontW ); + long fontH= 16; optSearch("FontHeight" , fontH ); + + long aux; if ( optSearch( "Font10x20", aux ) && aux ) + { fontW= 10, fontH= 20; + } + +/* + * Get and store the device size + * + */ + + DEVMODE ret; + ret.dmSize= sizeof( ret ); + EnumDisplaySettings( NULL + , ENUM_CURRENT_SETTINGS + , &ret ); + + dmPelsWidth = ret.dmPelsWidth ; + dmPelsHeight= ret.dmPelsHeight; + screenWidth = maxX; + screenHeight= maxY; + + TestAllFonts( fontW /* Try the best fit */ + , fontH ); + CheckWindowSize( windowArea ); + +/* + * Code page, User settings have more priority than detected settings + */ + optSearch("AppCP", forcedAppCP ); + optSearch("ScrCP", forcedScrCP ); + optSearch("InpCP", forcedInpCP ); + + codePage= + new TVCodePage( forcedAppCP != -1 ? forcedAppCP : TVCodePage::ISOLatin1Linux + , forcedScrCP != -1 ? forcedScrCP : TVCodePage::ISOLatin1Linux + , forcedInpCP != -1 ? forcedInpCP : TVCodePage::ISOLatin1Linux ); + + SetDefaultCodePages( TVCodePage::ISOLatin1Linux + , TVCodePage::ISOLatin1Linux + , TVCodePage::ISOLatin1Linux ); + + normCursor= LoadCursor( NULL, IDC_ARROW ); + handCursor= LoadCursor( NULL, IDC_HAND ); + + if( handCursor==NULL ) /* Not available in 95 and NT */ + { handCursor= LoadCursor(NULL, IDC_ARROW ); + } + sizeCursor= LoadCursor(NULL, IDC_SIZENWSE ); + + wincl.hIcon = LoadIcon( NULL /* Use default icon and mousepointer */ + , IDI_APPLICATION); + + wincl.hIconSm= LoadIcon( NULL + , IDI_APPLICATION); + + wincl.style = 0; /* no CS_DBLCLKS (Catch dbl-clicks) */ + wincl.cbSize = sizeof(WNDCLASSEX); + wincl.hCursor = normCursor; + wincl.hInstance = TvWinInstance; + wincl.cbClsExtra = 0; /* No extra bytes after window class */ + wincl.cbWndExtra = 0; /* structure or the window instance */ + wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */ + wincl.lpszMenuName = NULL; /* No menu */ + wincl.lpszClassName= className; + wincl.hbrBackground= NULL; + +/* + * Register the window class, if fail quit the program + */ + + if( !RegisterClassEx( &wincl ) ) + { return; + } + + +/* + * The class is registered, lets create a program + */ + hwnd= CreateWindowEx + ( exStyle /* Possible styles */ + , className /* Classname ("MyLittleWindow") */ + , className /* Title Text */ + , style /* defaultwindow */ + , CW_USEDEFAULT /* Window dimensions */ + , CW_USEDEFAULT + , windowArea.right + , windowArea.bottom + , HWND_DESKTOP /* The window is a childwindow to desktop */ + , NULL /* No menu */ + , TvWinInstance /* Program Instance handler */ + , NULL ); /* No Window Creation data */ + + if ( ! hwnd ) /* Fails to create (font creation assigns) */ + { return; + } + +/* + * Store the window geometry and client size + */ + + hdc= GetDC( hwnd ); + + /* + * Now we have an hwnd, and can create fonts + */ + + initialized++ ; + + ShowWindow( hwnd /* Make the window visible on the screen */ + , startinfo.dwFlags + & STARTF_USESHOWWINDOW + ? startinfo.wShowWindow + : SW_SHOWDEFAULT ); + + for ( int col= 0 + ; col<16 + ; col++ ) + { colorMap[ col ]= RGB( (col&4) ? (col&8) ? FullColor:HalfColor:0 + , (col&2) ? (col&8) ? FullColor:HalfColor:0 + , (col&1) ? (col&8) ? FullColor:HalfColor:0 ); + } + + flags0= CodePageVar + | CursorShapes + | CanSetBFont + | CanSetSBFont + | NoUserScreen + | CanSetVideoSize + | CanSetFontSize + | CanSetPalette + | CanReadPalette; + + + cursorLines= + startupCursor= + getCursorType(); + + + screenMode= startupMode= smCO80; + + +/* + * Start cursor blinking handler + */ + + cursorProc( hwnd // handle of window for timer messages + , 0 // Don´t draw cursor + , 0 // timer identifier + , 0 ); // current system time + +} + + + +/* + * JASC, 2002 + * + * Link the driver by loading the static method pointers + */ +void TScreenWinGr::Init() +{ TScreen::System_p = System; + TScreen::Resume = Resume; + TScreen::Suspend = Suspend; + TScreen::setFont_p = SetFont; + TScreen::setCharacter = setCharacter; + TScreen::setCharacters = setCharacters; + TScreen::setVideoMode = setVideoMode; + TScreen::setVideoModeRes_p = SetVideoModeRes; + TScreen::getFontGeometry = GetFontGeometry; + TScreen::restoreFonts = RestoreFonts; + TScreen::setDisPaletteColors = SetDisPaletteColors; + TScreen::getFontGeometryRange= GetFontGeometryRange; + + TVWin32Clipboard::Init(); /* Use the windows clipboard */ + setVideoModeRes( 0xFFFF + , 0xFFFF + , -1, -1 ); +} + +/* + * + */ +void TScreenWinGr::Resume() +{ SaveScreen(); +} + +/* + * + */ +void TScreenWinGr::Suspend() +{ RestoreScreen(); +} + +/* + * Free screen resources + */ +TScreenWinGr::~TScreenWinGr() +{ UnregisterClass( className /* Free class resources */ + , TvWinInstance ); + DestroyWindow ( hwnd ); /* Free the window */ + + if ( screenBuffer ) + { delete screenBuffer; + screenBuffer= NULL; + } +} + +/* + + * JASC jul/2002, write a unique colored line + */ +void TScreenWinGr::writeLine( unsigned x + , unsigned y + , int w + , char * org + , uchar color ) +{ unsigned letter; + uchar * str= (uchar *) org; + + if ( w<=0 ) // Nothing to do + { return; + } + + SetBkColor ( hdc, colorMap[ color&15 ]); // Color de fondo + SetTextColor( hdc, colorMap[ color>>4 ]); // Color de fondo + + while( w -- ) + { letter= *str++; /* Next character */ + BitBlt( hdc + , x ++ * primary.w /* Move right */ + , y * primary.h + , primary.w + , primary.h + + , useSecondaryFont && ( color & 0x8 ) + ? secondary.bitmapMemo + : primary.bitmapMemo + + , 0, letter * primary.h + , SRCCOPY ); + } + + if ( y==yPos ) + { if ( xPos >= x) + { if ( xPos<= x+w ) + { if ( xPos >= 0 ) + { lowSetCursor( xPos + , yPos + , true ); + } + } + } + } +} + + +/* + * JASC jul/2002 + * + * Write a unique colored line to memory and screen + */ +void TScreenWinGr::setCharacters( unsigned offset + , ushort * src + , unsigned len ) +{ uchar letra; + uchar color; + int add ; + int last ; + + ushort x= offset % screenWidth; // Regenerate cartesian coordinates + ushort y= offset / screenWidth; + + ushort *old = screenBuffer + offset; + ushort *old_right = old + len - 1; + ushort *src_right = src + len - 1; + + char * dst; + + if ( !len ) + { return; + } + +/* + * remove unchanged characters from left to right + */ + if ( !forceRedraw ) + { while (len > 0 && *old == *src) + { x++; offset++; old++; src++; len--; + } + +/* + * remove unchanged characters from right to left + */ + while (len > 0 && *old_right == *src_right) + { old_right--; src_right--; len--; + } + } + + AllocLocalStr(tmp,len); /* write only middle changed characters */ + dst= tmp; add= 0; last= -1; + + memcpy( old /* Copy to screen buffer */ + , src + , len*2 ); + + while(len--) /* Iterate */ + { letra= attrChar(*src); /* JASC, are macros (endian dependent) */ + color= attrColor(*src); + + if ( color != last ) + { if (last>=0) + { writeLine( x + , y + , add + , tmp + , last ); /* Print last same color block */ + dst= tmp; x+= add; add= 0; } + last= color; } + *dst= letra; + dst++; src++; add++; } + + if (!add) + { return; } + + writeLine( x + , y + , add + , tmp + , last ); /* Print last block */ +} + + + +/* + * + */ +void TScreenWinGr::setCharacter( unsigned offset + , ushort value ) // JASC dic 2006, change from uint32. New interace ? +{ setCharacters( offset + , &value + , 1 ); +} + +/* + * + */ +void TScreenWinGr::SaveScreen() +{ +} + +/* + * + */ +void TScreenWinGr::RestoreScreen() +{ +} + +/* + * + */ +int TScreenWinGr::SetDisPaletteColors( int from + , int number + , TScreenColor *colors ) +{ int to; + +/* + * Some boundaries cheching + */ + from= from < 0 ? 0 : from; + to = from+number; + to = to > 16 ? 16: to; + number= 0; /* Now is a counter */ + + while( from < to ) + { colorMap[ from++ ]= RGB( colors[ from ].R + , colors[ from ].G + , colors[ from ].B ); + number ++; + } + + return( number ); +} + + + +/* + * JASC, 2006 + * + * Change the amount of memory for cells. Avoid heap fragmentation, only + * realloqing if more memory requested. + */ +void TScreenWinGr::resizeMemoryBuffer() +{ int newAmountOfCells= getRows()*getCols(); + + if ( newAmountOfCells > amountOfCells ) + { if ( screenBuffer ) + { free( screenBuffer ); + } + amountOfCells= newAmountOfCells; + screenBuffer= ( ushort *) calloc( sizeof(ushort) * 10 + , amountOfCells ); + } + else + { memset( screenBuffer, 0, sizeof(ushort)*amountOfCells ); + } +} + + +/* + * JASC, 2002 + * + * Changes the video mode, both hardware ( resolution ) and software + * ( resources ) layers. Only realocates memory on growing, avoiding heap + * fragmentation. + */ +void TScreenWinGr::setVideoMode( ushort mode ) +{ setCrtMode( mode ); + resizeMemoryBuffer(); + setCrtData(); /* Do the hardware layer */ + winRecalc(); +} + +int TScreenWinGr::SetVideoModeRes( unsigned w + , unsigned h + , int fW + , int fH ) +{ if ( w != 0xFFFF ) + { screenWidth= w; + } + + if ( h != 0xFFFF ) + { screenHeight= h; + } + + if ( fW == -1 ) + { fW= primary.w; + } + + if ( fH == -1 ) + { fH= primary.h; + } + + SetCrtModeRes( fW, fH ); + resizeMemoryBuffer(); + winRecalc(); + return( 1 ); +} + +/* ##### + * JASC, feb 2006 ## + * ## + * Execute an external program in a syncronous way redirecting input, ## + * output and error. ## + * ## + * Originally, From SET code, in a MSDOS or UNIX way. ## + * Now in a windows way. ##### + */ +int TScreenWinGr::System( const char * command + , pid_t * pidChild + , int in + , int out + , int err ) +{ PROCESS_INFORMATION pi; + STARTUPINFO si; + char cmdLine[ 4096 ]; + + memset(&si, 0, sizeof(si)); + memset(&pi, 0, sizeof(pi)); + si.cb = sizeof(si); + +// If the caller asks for redirection replace the requested handles + + if ( pidChild ) + { si.hStdInput = GetStdHandle( STD_INPUT_HANDLE ); // Default values + si.hStdOutput= GetStdHandle( STD_OUTPUT_HANDLE ); + si.hStdError = GetStdHandle( STD_ERROR_HANDLE ); + + if ( in != -1 ) + { si.dwFlags|= STARTF_USESTDHANDLES; // Use new handles + si.hStdInput = (HANDLE)_get_osfhandle( in ); + } + + if ( out != -1 ) + { si.dwFlags|= STARTF_USESTDHANDLES; // Use new handles + si.hStdOutput= (HANDLE)_get_osfhandle( out ); + } + + if ( err != -1 ) + { si.dwFlags|= STARTF_USESTDHANDLES; // Use new handles + si.hStdError = (HANDLE)_get_osfhandle( err ); + } + } + + sprintf( cmdLine + , "/C %s" + , command ); + + if ( !CreateProcess( getenv( "COMSPEC" ) // Do it trough a shell (scrips, etc) + , cmdLine // pointer to command line string + , NULL // pointer to process security attributes + , NULL // pointer to thread security attributes + , true // handle inheritance flag + , 0 // creation flags + , NULL // pointer to new environment block + , NULL // pointer to current directory name + , &si + , &pi )) + { return( -1 ); // Error + } + + if ( pidChild ) // Leave in the background + { return( *pidChild= (int)pi.hProcess ); // Give process identifier + } + else + { WaitForSingleObject // DO NOT leave in the background + ( pi.hProcess + , INFINITE ); + return( NULL ); // Return task done + } + + +} + +/* ##### + * JASC 2002 ## + * ## + * ##### + */ +TScreen * TV_WinGrDriverCheck() +{ TScreenWinGr *drv=new TScreenWinGr(); + + if ( !TScreen::initialized ) + { delete drv; + drv= NULL; + } + + TDisplayWinGr::Init(); /* First */ + TGKeyWinGr::init(); + TScreenWinGr::Init(); + THWMouseWinGr::init(); + + return( drv ); +} + +#else + +#include +#include +#include + +#endif // TVOS_Win32 + diff --git a/tvision/classes/winnt/winntdis.cc b/tvision/classes/winnt/winntdis.cc new file mode 100644 index 0000000..2b47ddb --- /dev/null +++ b/tvision/classes/winnt/winntdis.cc @@ -0,0 +1,218 @@ +/**[txh]******************************************************************** + + Copyright (c) 2002 by Salvador E. Tropea (SET) + Based on code contributed by Anatoli Soltan. + + Description: + Win32 Display routines. + The original implementation was done by Anatoli, I removed some code, added +some routines and adapted it to the new architecture. + + Notes: + 1) At least in W98SE the cursor can't be hided if we are windowed. I think +that's some bug in Windows. Something interesting: when I resize the window +and it can't go full screen anymore the colors get wrong (as observed in +NT 4.0) looks like Windows uses another drawing technic. In this particular +mode the cursor can be hided properly. + 2) The API reference I have says the cursor size can range from 1 to 100, +but in my system 99 is the maximum. + +***************************************************************************/ +#include + +#define Uses_TScreen +#define Uses_TEvent +#define Uses_TFrame +#include + +// I delay the check to generate as much dependencies as possible +#ifdef TVOS_Win32 + +#define WIN32_LEAN_AND_MEAN +#include + +#include + +HANDLE TDisplayWinNT::hIn =INVALID_HANDLE_VALUE; +HANDLE TDisplayWinNT::hOut=INVALID_HANDLE_VALUE; +#ifdef USE_NEW_BUFFER +HANDLE TDisplayWinNT::hStdOut=INVALID_HANDLE_VALUE; +#endif +unsigned TDisplayWinNT::currentCursorX, + TDisplayWinNT::currentCursorY, + TDisplayWinNT::curStart, + TDisplayWinNT::curEnd; + +void TDisplayWinNT::SetCursorPos(unsigned x, unsigned y) +{ + if (x!=currentCursorX || y!=currentCursorY) + { + SetCursorPosLow(x,y); + currentCursorX=x; + currentCursorY=y; + } +} + +// by SET +void TDisplayWinNT::SetCursorPosLow(unsigned x, unsigned y) +{ + COORD coord; + coord.X=(SHORT)x; + coord.Y=(SHORT)y; + SetConsoleCursorPosition(hOut,coord); +} + +void TDisplayWinNT::GetCursorPos(unsigned &x, unsigned &y) +{ + x=currentCursorX; + y=currentCursorY; +} + +// by SET +void TDisplayWinNT::GetCursorPosLow(unsigned &x, unsigned &y) +{ + CONSOLE_SCREEN_BUFFER_INFO screenInf; + GetConsoleScreenBufferInfo(hOut,&screenInf); + x=screenInf.dwCursorPosition.X; + y=screenInf.dwCursorPosition.Y; +} + +// by SET +void TDisplayWinNT::GetCursorShapeLow(unsigned &start, unsigned &end) +{ + CONSOLE_CURSOR_INFO cursorInf; + GetConsoleCursorInfo(hOut,&cursorInf); + if (cursorInf.bVisible) + {// Visible + // Win32API returns a "percent filled" value. + start=100-cursorInf.dwSize; + // Ever upto the end + end =100; + } + else + // Invisible cursor + start=end=0; +} + +void TDisplayWinNT::GetCursorShape(unsigned &start, unsigned &end) +{ + start=curStart; + end=curEnd; +} + +// by SET +void TDisplayWinNT::SetCursorShape(unsigned start, unsigned end) +{ + if (start>=end && getShowCursorEver()) + return; + + if (start!=curStart || end!=curEnd) + { + SetCursorShapeLow(start,end); + curStart=start; + curEnd=end; + } +} + +// by SET +void TDisplayWinNT::SetCursorShapeLow(unsigned start, unsigned end) +{ + CONSOLE_CURSOR_INFO inf; + inf.bVisible=start>=end ? FALSE : TRUE; + inf.dwSize=inf.bVisible ? end-start : 1; + if (inf.dwSize>99) inf.dwSize=99; + SetConsoleCursorInfo(hOut,&inf); +} + +void TDisplayWinNT::ClearScreen(uchar screenWidth, uchar screenHeight) +{ + COORD coord={0,0}; + DWORD cWritten; + + FillConsoleOutputCharacter(hOut,' ',screenWidth*screenHeight,coord,&cWritten); + FillConsoleOutputAttribute(hOut,FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, + screenWidth*screenHeight,coord,&cWritten); +} + +ushort TDisplayWinNT::GetRows() +{ + CONSOLE_SCREEN_BUFFER_INFO inf; + GetConsoleScreenBufferInfo(hOut,&inf); + return (ushort)inf.dwSize.Y; +} + +ushort TDisplayWinNT::GetCols() +{ + CONSOLE_SCREEN_BUFFER_INFO inf; + GetConsoleScreenBufferInfo(hOut,&inf); + return (ushort)inf.dwSize.X; +} + +const int mxTitleSize=256; + +/**[txh]******************************************************************** + + Description: + Finds the main window title. + + Return: + A pointer to a newly allocated string (new[]). Or 0 if fail. by SET. + +***************************************************************************/ + +const char *TDisplayWinNT::GetWindowTitle(void) +{ + char buf[mxTitleSize]; + DWORD ret=GetConsoleTitle(buf,mxTitleSize); + if (ret) + { + char *s=new char[ret+1]; + memcpy(s,buf,ret); + s[ret]=0; + return s; + } + return 0; +} + +/**[txh]******************************************************************** + + Description: + Sets the main window title. + + Return: + non-zero successful. by SET. + +***************************************************************************/ + +int TDisplayWinNT::SetWindowTitle(const char *name) +{ + return SetConsoleTitle(name); +} + +void TDisplayWinNT::Beep() +{ + MessageBeep(0xFFFFFFFF); +} + +TDisplayWinNT::~TDisplayWinNT() {} + +void TDisplayWinNT::Init() +{ + setCursorPos=SetCursorPos; + getCursorPos=GetCursorPos; + getCursorShape=GetCursorShape; + setCursorShape=SetCursorShape; + getRows=GetRows; + getCols=GetCols; + setWindowTitle=SetWindowTitle; + getWindowTitle=GetWindowTitle; + clearScreen=ClearScreen; + beep=Beep; +} + +#else + +#include + +#endif // TVOS_Win32 + diff --git a/tvision/classes/winnt/winntkey.cc b/tvision/classes/winnt/winntkey.cc new file mode 100644 index 0000000..75893b7 --- /dev/null +++ b/tvision/classes/winnt/winntkey.cc @@ -0,0 +1,326 @@ +/**[txh]******************************************************************** + + Copyright (c) 2002 by Salvador E. Tropea (SET) + It said: + This code is GPL, see copying file for more details. + Keyboard handler for Win32 Copyright by Anatoli Soltan (2000) + Based on the handler for Linux Copyright by Salvador E. Tropea (SET) (1998,1999) + + Description: + WinNT Keyboard routines. + The original implementation was done by Anatoli, I removed some code, added +some routines and adapted it to the new architecture. + + ToDo: + * Must check GetShiftState, I think the return value is wrong. + +***************************************************************************/ +#include + +#define Uses_TEvent +#define Uses_TGKey +#define Uses_FullSingleKeySymbols +#define Uses_TScreen +#include + +// I delay the check to generate as much dependencies as possible +#ifdef TVOS_Win32 +#define WIN32_LEAN_AND_MEAN +#include + +#include +#include + +INPUT_RECORD TGKeyWinNT::inpRec; +unsigned TGKeyWinNT::shiftState; +ushort TGKeyWinNT::vk2kk[]= +{ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x002a, 0x002b, 0x0000, 0x0000, 0x0000, 0x002c, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x001f, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0034, 0x0047, 0x004c, 0x004a, 0x0045, 0x0048, 0x0046, 0x0049, + 0x004b, 0x0000, 0x0000, 0x0000, 0x0000, 0x004d, 0x004e, 0x0000, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x0063, 0x0064, 0x0065, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0033, 0x0036, 0x0000, 0x0035, 0x0000, 0x0032, + 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, + 0x0041, 0x0042, 0x0043, 0x0044, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x002d, 0x0038, 0x0059, 0x005e, 0x005a, 0x005b, + 0x0061, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0056, 0x001c, 0x0057, 0x002e, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +unsigned TGKeyWinNT::GetShiftState() +{ + return shiftState; +} + +void TGKeyWinNT::Clear(void) +{ + FlushConsoleInputBuffer(TScreenWinNT::hIn); +} + +int TGKeyWinNT::KbHit(void) +{ + DWORD cEvents; + + while (PeekConsoleInput(TScreenWinNT::hIn,&inpRec,1,&cEvents) && cEvents==1) + { + if (inpRec.EventType!=KEY_EVENT) + { + // The following two lines are commented because if someone waits for + // a key press by calling kbhit in a loop and a mouse event is in the + // queue, the loop will never end. + //if (inpRec.EventType == MOUSE_EVENT) + // return 0; + ReadConsoleInput(TScreenWinNT::hIn,&inpRec,1,&cEvents); + continue; + } + if (!inpRec.Event.KeyEvent.bKeyDown) // skeek keyup events + ReadConsoleInput(TScreenWinNT::hIn,&inpRec,1,&cEvents); + else + return 1; + } + return 0; +} + +void TGKeyWinNT::FillTEvent(TEvent &e) +{ + DWORD cEvents; + ReadConsoleInput(TScreenWinNT::hIn,&inpRec,1,&cEvents); + + DWORD dwCtlState=inpRec.Event.KeyEvent.dwControlKeyState; + shiftState=0; + if (dwCtlState & SHIFT_PRESSED) + shiftState|=kbShiftCode; + if (dwCtlState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)) + shiftState|=kbCtrlCode; + if (dwCtlState & LEFT_ALT_PRESSED) + shiftState|=kbAltLCode; + if (dwCtlState & RIGHT_ALT_PRESSED) + shiftState|=kbAltRCode; + //if (dwCtlState & SCROLLLOCK_ON) + // shiftState |= kbScrollState; + //if (dwCtlState & NUMLOCK_ON) + // shiftState |= kbNumState; + //if (dwCtlState & CAPSLOCK_ON) + // shiftState |= kbCapsState; + + e.keyDown.charScan.scanCode=inpRec.Event.KeyEvent.wVirtualScanCode; + uchar Symbol=inpRec.Event.KeyEvent.uChar.AsciiChar; + e.keyDown.charScan.charCode=((shiftState & kbAltLCode) && (Symbol<128)) ? + 0 : Symbol; + e.keyDown.shiftState=shiftState; + // To debug the codes + //fprintf(stderr,"inpRec.Event.KeyEvent.wVirtualKeyCode=%d\n", + // inpRec.Event.KeyEvent.wVirtualKeyCode); + e.keyDown.keyCode=(inpRec.Event.KeyEvent.wVirtualKeyCode<256) ? + vk2kk[inpRec.Event.KeyEvent.wVirtualKeyCode] : + (ushort)0; + if (e.keyDown.keyCode==0) + return; + e.what=evKeyDown; + e.keyDown.keyCode|=shiftState; +} + +void TGKeyWinNT::Init() +{ + TGKey::kbhit=KbHit; + TGKey::getShiftState=GetShiftState; + TGKey::fillTEvent=FillTEvent; + TGKey::clear=Clear; +} +#else + +#include +#include + +#endif // TVOS_Win32 + +/* +This code was used by Anatoli to check what key codes generates Win32 API. + +<------- start of codes.cpp +#define WIN32_LEAN_AND_MEAN +#include +#include + +void main() +{ + INPUT_RECORD ir; + HANDLE hInp; + DWORD cEvents; + + hInp=GetStdHandle(STD_INPUT_HANDLE); + + while (1) + { + ReadConsoleInput(hInp, &ir, 1, &cEvents); + if (ir.EventType == KEY_EVENT) + { + printf("KeyDown = %d, VK = %d, SC = %x Char = %d\n", + ir.Event.KeyEvent.bKeyDown, + ir.Event.KeyEvent.wVirtualKeyCode, + ir.Event.KeyEvent.wVirtualScanCode, + ir.Event.KeyEvent.uChar.AsciiChar); + } + } +} +<------- end of codes.cpp + +Perl script used by Anatoli to generate the translation table + +@table = qw( +kbUnknown=0x0000 +kbA=0x0001=65 +kbB=0x0002=66 +kbC=0x0003=67 +kbD=0x0004=68 +kbE=0x0005=69 +kbF=0x0006=70 +kbG=0x0007=71 +kbH=0x0008=72 +kbI=0x0009=73 +kbJ=0x000a=74 +kbK=0x000b=75 +kbL=0x000c=76 +kbM=0x000d=77 +kbN=0x000e=78 +kbO=0x000f=79 +kbP=0x0010=80 +kbQ=0x0011=81 +kbR=0x0012=82 +kbS=0x0013=83 +kbT=0x0014=84 +kbU=0x0015=85 +kbV=0x0016=86 +kbW=0x0017=87 +kbX=0x0018=88 +kbY=0x0019=89 +kbZ=0x001a=90 + +kbOpenBrace=0x001b +kbBackSlash=0x001c=220 +kbCloseBrace=0x001d +kbPause=0x001e +kbEsc=0x001f=27 + +kb0=0x0020=48 +kb1=0x0021=49 +kb2=0x0022=50 +kb3=0x0023=51 +kb4=0x0024=52 +kb5=0x0025=53 +kb6=0x0026=54 +kb7=0x0027=55 +kb8=0x0028=56 +kb9=0x0029=57 + +kbBackSpace=0x002a=8 +kbTab=0x002b=9 +kbEnter=0x002c=13 + +kbColon=0x002d=186 +kbQuote=0x002e=222 +kbGrave=0x002f +kbComma=0x0030 + +kbStop=0x0031 +kbSlash=0x0032=111 +kbAsterisk=0x0033=106 +kbSpace=0x0034=32 + +kbMinus=0x0035=109 +kbPlus=0x0036=107 +kbPrnScr=0x0037 +kbEqual=0x0038=187 + +kbF1=0x0039=112 +kbF2=0x003a=113 +kbF3=0x003b=114 +kbF4=0x003c=115 +kbF5=0x003d=116 +kbF6=0x003e=117 +kbF7=0x003f=118 +kbF8=0x0040=119 +kbF9=0x0041=120 +kbF10=0x0042=121 +kbF11=0x0043=122 +kbF12=0x0044=123 + +kbHome=0x0045=36 +kbUp=0x0046=38 +kbPgUp=0x0047=33 +kbLeft=0x0048=37 +kbRight=0x0049=39 +kbEnd=0x004a=35 +kbDown=0x004b=40 +kbPgDn=0x004c=34 + +kbInsert=0x004d=45 +kbDelete=0x004e=46 +kbCaret=0x004f +kbAdmid=0x0050 + +kbDobleQuote=0x0051 +kbNumeral=0x0052 +kbDolar=0x0053 +kbPercent=0x0054 + +kbAmper=0x0055 +kbOpenPar=0x0056=219 +kbClosePar=0x0057=221 +kbDoubleDot=0x0058 + +kbLessThan=0x0059=188 +kbGreaterThan=0x005a=190 +kbQuestion=0x005b=191 +kbA_Roba=0x005c +kbOr=0x005d +kbUnderLine=0x005e=189 +kbOpenCurly=0x005f +kbCloseCurly=0x0060 +kbTilde=0x0061=192 +kbMacro=0x0062 +kbWinLeft=0x0063=91 +kbWinRight=0x0064=92 +kbWinSel=0x0065=93 +kbMouse=0x0066 +); + +for $e (@table) { + ($kname, $kcode, $vcode) = split(/=/, $e); + $map[$vcode] = $kcode if $vcode ne ''; +} + +for ($i = 0; $i < 256; $i++) { + $map[$i] = '0x0000' if !defined($map[$i]); +} + +for ($i = 0; $i < 256; ) { + for ($j = 0; $j < 8; $j++, $i++) { + print $map[$i], (($i == 255) ? '' : ', '); + } + print "\n"; +} +*/ + diff --git a/tvision/classes/winnt/winntmouse.cc b/tvision/classes/winnt/winntmouse.cc new file mode 100644 index 0000000..878157c --- /dev/null +++ b/tvision/classes/winnt/winntmouse.cc @@ -0,0 +1,78 @@ +/**[txh]******************************************************************** + + Copyright (c) 2002 by Salvador E. Tropea (SET) + Based on code contributed by Anatoli Soltan. + + Description: + WinNT Mouse routines. + The original implementation was done by Anatoli, I removed some code and +adapted it to the new architecture. + +***************************************************************************/ +#include + +#define Uses_TEvent +#define Uses_TEventQueue +#define Uses_TScreen +#include + +// I delay the check to generate as much dependencies as possible +#ifdef TVOS_Win32 + +#define WIN32_LEAN_AND_MEAN +#include + +#include +#include + +INPUT_RECORD THWMouseWinNT::inpRec; + +void THWMouseWinNT::GetEvent(MouseEventType &me) +{ + DWORD cEvents; + INPUT_RECORD ir; + + while (PeekConsoleInput(TScreenWinNT::hIn,&ir,1,&cEvents) && cEvents==1) + { + if (ir.EventType==KEY_EVENT) + break; + if (ir.EventType!=MOUSE_EVENT) + { + ReadConsoleInput(TScreenWinNT::hIn,&ir,1,&cEvents); + continue; + } + ReadConsoleInput(TScreenWinNT::hIn,&inpRec,1,&cEvents); + break; + } + me.buttons=(uchar)inpRec.Event.MouseEvent.dwButtonState; + me.doubleClick=False; + me.where.x=inpRec.Event.MouseEvent.dwMousePosition.X; + me.where.y=inpRec.Event.MouseEvent.dwMousePosition.Y; +} + +void THWMouseWinNT::Init() +{ + THWMouse::GetEvent=THWMouseWinNT::GetEvent; + THWMouse::Resume=THWMouseWinNT::Resume; + Resume(); +} + +void THWMouseWinNT::Resume() +{ + // SET: According to Win32 API reference an application should check if the + // mouse is installed and can find how many buttons have the mouse using + // calls to GetSystemMetrics. Windows supports upto 3 buttons :-( + // Note that in my system I have a 5 buttons mouse, 3 of them generates + // events and this call returns 2. I don't thing Windows is doing the right + // thing ;-) In my system the wheel works for IE, but I don't get mouse + // events from the wheel. + buttonCount=GetSystemMetrics(SM_CMOUSEBUTTONS); +} + +#else + +#include +#include + +#endif // TVOS_Win32 + diff --git a/tvision/classes/winnt/winntscr.cc b/tvision/classes/winnt/winntscr.cc new file mode 100644 index 0000000..e9ebf8a --- /dev/null +++ b/tvision/classes/winnt/winntscr.cc @@ -0,0 +1,577 @@ +/**[txh]******************************************************************** + + Copyright (c) 2002-2005 by Salvador E. Tropea (SET) + Based on code contributed by Anatoli Soltan. + + Description: + WinNT Screen routines. + The original implementation was done by Anatoli, I removed some code, +added some routines and adapted it to the new architecture. + + ToDo: Set UseScreenSaver when we are in full screen. + + Configuration variables: + ScreenWidth + ScreenHeight + AppCP + ScrCP + InpCP + + Notes: + 1) I saw a problem in W98SE, it looks like a bug in Windows: If I +suspend to a shell and the resume doing window size changes at exit the +screen seems to be partially restored. But if you force windows to redraw +it (minimize/maximize for example) things gets right. This is problem only +affects the cursor when using USE_NEW_BUFFER. + 2) The USE_NEW_BUFFER mode is something I (SET) found in the Win32 API +docs that's much cleaver than saving/restoring the screen contents. When +defined I just create a new screen buffer and use it. To restore the screen +you just need to set the original STDOUT handle as the active. It makes the +code easier and exposes less Windows problems (bugs?). The only bizarre +thing I observe is "invisible cursor", but this is just Windows forgets to +update, as soon as the window needs a redraw the cursor gets visible again. + 3) Anatoli left commented: + hIn=CreateFile("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + hOut=CreateFile("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); +I think they aren't useful but I left it here in case I need this example. + +***************************************************************************/ +#include + +#define Uses_stdlib +#define Uses_TScreen +#define Uses_TEvent +#define Uses_TGKey +#define Uses_TVCodePage +#define Uses_unistd +#include +#include + +// I delay the check to generate as much dependencies as possible +#ifdef TVOS_Win32 + +#define WIN32_LEAN_AND_MEAN +#include +#undef YieldProcessor + +#include +#include +#include + +//#define DEBUG +#ifdef DEBUG + #define DBPr1(a) fputs(a,stderr) + #define DBPr2(a,b) fprintf(stderr,a,b) + #define DBPr3(a,b,c) fprintf(stderr,a,b,c) +#else + #define DBPr1(a) + #define DBPr2(a,b) + #define DBPr3(a,b,c) +#endif + +#define TV_CONSOLE_MODE (ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT) + +#ifndef USE_NEW_BUFFER +ushort *TScreenWinNT::saveScreenBuf; +unsigned TScreenWinNT::saveScreenSize; +unsigned TScreenWinNT::saveScreenCursorStart, + TScreenWinNT::saveScreenCursorEnd; +unsigned TScreenWinNT::saveScreenCursorX, + TScreenWinNT::saveScreenCursorY; +#else + #define SaveScreenReleaseMemory() +#endif +DWORD TScreenWinNT::saveScreenConsoleMode; +unsigned TScreenWinNT::saveScreenWidth, + TScreenWinNT::saveScreenHeight; + +// Buffer used to arrange the data as needed by Win32 API +CHAR *TScreenWinNT::outBuf; +WORD *TScreenWinNT::outBufAttr; +CHAR_INFO *TScreenWinNT::outBufCI; +unsigned TScreenWinNT::outBufCapacity; + +void TScreenWinNT::ensureOutBufCapacity(unsigned count) +{ + count=(count+1) & 0xFFFFFFFE; + if (outBufCapacity>8); + + COORD dwBufferSize={1,1}; + COORD dwBufferCoord={0,0}; + SMALL_RECT rcWriteRegion={coord.X, coord.Y, coord.X, coord.Y}; + WriteConsoleOutput(hOut,outBufCI,dwBufferSize,dwBufferCoord,&rcWriteRegion); + + //FillConsoleOutputCharacter(hOut,(CHAR)(value & 0xFF),1,coord,&cWritten); + //FillConsoleOutputAttribute(hOut,(WORD)(value >> 8),1,coord,&cWritten); +} + +void TScreenWinNT::SetCharacters(unsigned offset, ushort *values, unsigned count) +{ + ensureOutBufCapacity(count); + COORD coord; + coord.Y=(SHORT)((offset)/screenWidth); + coord.X=(SHORT)((offset)%screenWidth); + unsigned i; + + for (i=0; i>8); + } + + COORD dwBufferSize={count,1}; + COORD dwBufferCoord={0, 0}; + SMALL_RECT rcWriteRegion={coord.X, coord.Y, coord.X+count-1, coord.Y}; + WriteConsoleOutput(hOut,outBufCI,dwBufferSize,dwBufferCoord,&rcWriteRegion); +} + +#ifndef USE_NEW_BUFFER +void TScreenWinNT::SaveScreen() +{ + unsigned rows=GetRows(); + unsigned cols=GetCols(); + + saveScreenSize=rows*cols; + free(saveScreenBuf); + saveScreenBuf=(ushort *)malloc(saveScreenSize*sizeof(ushort)); + + // Temporarily set these variables to let getCharacter work properly + uchar screenWidthSave=screenWidth; + uchar screenHeightSave=screenHeight; + screenWidth=(uchar)cols; + screenHeight=(uchar)rows; + unsigned row, ofs; + for (row=0, ofs=0; rowmax.X) newSize.X=max.X; + if (newSize.Y>max.Y) newSize.Y=max.Y; + // The buffer must be large enough to hold both modes (current and new) + COORD newBufSize=newSize; + if (info.dwMaximumWindowSize.X>newBufSize.X) + newBufSize.X=info.dwMaximumWindowSize.X; + if (info.dwMaximumWindowSize.Y>newBufSize.Y) + newBufSize.Y=info.dwMaximumWindowSize.Y; + // Enlarge the buffer size. It fails if not windowed. + if (!SetConsoleScreenBufferSize(hCurrentOut,newBufSize)) return 0; + // Resize the window. + SMALL_RECT r={0,0,newSize.X-1,newSize.Y-1}; + if (!SetConsoleWindowInfo(hCurrentOut,TRUE,&r)) + {// Revert buffer size + newSize.X=info.dwMaximumWindowSize.X; + newSize.Y=info.dwMaximumWindowSize.Y; + SetConsoleScreenBufferSize(hCurrentOut,newSize); + return 0; + } + // Now we can shrink the buffer to the needed size + SetConsoleScreenBufferSize(hCurrentOut,newSize); + // This is something silly TV code spects: after a video mode change the + // cursor should go to the "default" state. + setCursorType(cursorLines); + // Ok! we did it. + return fW!=-1 || fH!=-1 || newSize.X!=(int)w || newSize.Y!=(int)h ? 2 : 1; +} + +#else + +#include +#include +#include + +#endif // TVOSf_WIN32 +/* +Win32 API reference names 45 code pages. Only 20 of them are supported. + +Code page identifiers: + +*037 EBCDIC + 437 MS-DOS United States * +*500 EBCDIC "500V1" +*708 Arabic (ASMO 708) +*709 Arabic (ASMO 449+, BCON V4) +*710 Arabic (Transparent Arabic) +*720 Arabic (Transparent ASMO) + 737 Greek (formerly 437G) * + 775 Baltic * + 850 MS-DOS Multilingual (Latin I) * + 852 MS-DOS Slavic (Latin II) * + 855 IBM Cyrillic (primarily Russian* + 857 IBM Turkish * + 860 MS-DOS Portuguese + 861 MS-DOS Icelandic +*862 Hebrew + 863 MS-DOS Canadian-French +*864 Arabic + 865 MS-DOS Nordic + 866 MS-DOS Russian * + 869 IBM Modern Greek * +*874 Thai +*875 EBCDIC +*932 Japan +*936 Chinese (PRC, Singapore) +*949 Korean +*950 Chinese (Taiwan, Hong Kong) +*1026 EBCDIC +*1200 Unicode (BMP of ISO 10646) + 1250 Windows 3.1 Eastern European * + 1251 Windows 3.1 Cyrillic * + 1252 Windows 3.1 US (ANSI) * + 1253 Windows 3.1 Greek * + 1254 Windows 3.1 Turkish * +*1255 Hebrew +*1256 Arabic + 1257 Baltic * +*1361 Korean (Johab) +*10000 Macintosh Roman +*10001 Macintosh Japanese +*10006 Macintosh Greek I + 10007 Macintosh Cyrillic +*10029 Macintosh Latin 2 +*10079 Macintosh Icelandic +*10081 Macintosh Turkish +----------------- +My registry also says: + +20866 +28591 +28592 +28595 +28597 + +As a Windows 9x is shipped working with only one code page I can't test what +a hell are these code pages. They seems to be some variant of 866 and some +kind of ISO cp, just a guess. +*/ + diff --git a/tvision/classes/x11/x11dis.cc b/tvision/classes/x11/x11dis.cc new file mode 100644 index 0000000..c5e1770 --- /dev/null +++ b/tvision/classes/x11/x11dis.cc @@ -0,0 +1,129 @@ +/* X11 display routines. + Copyright (c) 2001-2002 by Salvador E. Tropea (SET) + Covered by the GPL license. */ +#include + +#define Uses_string +#define Uses_TDisplay +#define Uses_TScreen +#include + +// I delay the check to generate as much dependencies as possible +#if (defined(TVOS_UNIX) || defined(TVCompf_Cygwin)) && defined(HAVE_X11) + +// X11 defines their own values +#undef True +#undef False +#include +#include + +#include + +/***************************************************************************** + + TDisplayX11 display stuff, that's very easy because we control all the + variables involved + +*****************************************************************************/ + +int TDisplayX11::cursorX; +int TDisplayX11::cursorY; +int TDisplayX11::cursorPX; +int TDisplayX11::cursorPY; +char TDisplayX11::cShapeFrom; +char TDisplayX11::cShapeTo; +char TDisplayX11::windowSizeChanged=0; +int TDisplayX11::maxX; +int TDisplayX11::maxY; +int TDisplayX11::newX; +int TDisplayX11::newY; +unsigned TDisplayX11::fontW; +unsigned TDisplayX11::fontWb; +unsigned TDisplayX11::fontH; +unsigned TDisplayX11::fontSz; + +TDisplayX11::~TDisplayX11() {} + +void TDisplayX11::Init() +{ + setCursorPos=SetCursorPos; + getCursorPos=GetCursorPos; + getCursorShape=GetCursorShape; + setCursorShape=SetCursorShape; + getRows=GetRows; + getCols=GetCols; + checkForWindowSize=CheckForWindowSize; +} + +void TDisplayX11::SetCursorPos(unsigned x, unsigned y) +{ + TScreenX11::UnDrawCursor(); + cursorX=x; cursorY=y; + cursorPX=x*fontW; cursorPY=y*fontH; + TScreenX11::DrawCursor(); +} + +void TDisplayX11::GetCursorPos(unsigned &x, unsigned &y) +{ + x=cursorX; y=cursorY; +} + +void TDisplayX11::GetCursorShape(unsigned &start, unsigned &end) +{ + start=100*cShapeFrom/fontH; + end =100*cShapeTo/fontH; + //fprintf(stderr,"GetCursorShape: %d,%d\n",start,end); +} + +void TDisplayX11::SetCursorShape(unsigned start, unsigned end) +{ + //fprintf(stderr,"SetCursorShape: %d,%d start>=end? %d\n",start,end,start>=end); + if (start>=end && getShowCursorEver()) + return; + cShapeFrom=start*fontH/100; + cShapeTo =end*fontH/100; + if ((unsigned)cShapeFrom>fontH) cShapeFrom=fontH; + if ((unsigned)cShapeTo>fontH) cShapeTo =fontH; + if (start>=end) + TScreenX11::DisableCursor(); + else + TScreenX11::EnableCursor(); + //fprintf(stderr,"Seteando X11: %d a %d\n",cShapeFrom,cShapeTo); +} + +ushort TDisplayX11::GetRows() +{ + return maxY; +} + +ushort TDisplayX11::GetCols() +{ + return maxX; +} + +int TDisplayX11::CheckForWindowSize(void) +{ + int ret=0; + SEMAPHORE_ON; + if (windowSizeChanged) + { + // Now we can change the values because the application is aware + maxX=newX; + maxY=newY; + // Reallocate the buffer cleaning it to force a deep redraw + delete[] TScreen::screenBuffer; + TScreen::screenBuffer=new ushort[maxX*maxY]; + memset(TScreen::screenBuffer,0,maxX*maxY*sizeof(ushort)); + windowSizeChanged=0; + ret=1; + } + SEMAPHORE_OFF; + return ret; +} + +#else + +#include + +#endif // defined(TVOS_UNIX) && defined(HAVE_X11) + diff --git a/tvision/classes/x11/x11key.cc b/tvision/classes/x11/x11key.cc new file mode 100644 index 0000000..8086e97 --- /dev/null +++ b/tvision/classes/x11/x11key.cc @@ -0,0 +1,479 @@ +/* X11 keyboard routines. + Copyright (c) 2001-2003 by Salvador E. Tropea (SET) + Covered by the GPL license. */ +#include + +#define Uses_stdio // debug +#define Uses_stdlib // bsearch +#define Uses_TDisplay +#define Uses_TScreen +#define Uses_TGKey +#define Uses_FullSingleKeySymbols +#define Uses_TEvent +#define Uses_TVCodePage +#include + +// I delay the check to generate as much dependencies as possible +#if (defined(TVOS_UNIX) || defined(TVCompf_Cygwin)) && defined(HAVE_X11) + +// X11 defines their own values +#undef True +#undef False +#include +#include +#include + +#include +#include + +#define x11AltMask Mod1Mask // Alt for XFree86 and Solaris +#ifdef TVOSf_Solaris + #define x11NumLockMask Mod3Mask // NumLock for Solaris +#else + #define x11NumLockMask Mod2Mask // NumLock for XFree86 +#endif +// What's that for Solaris? I couldn't get Scroll Lock to work on Solaris. +#define x11ScrollLockMask Mod5Mask // ScrollLock for XFree86 +/* + In Solaris: + Mod2Mask is for Alt Graphic. + Mod4Mask is for the key with a diamond. + + In XFree86: + Mod4Mask is for the Windows key. +*/ +#if X_HAVE_UTF8_STRING + // XFree86 4.0.2 introduced a very nice function to retreive a key using + // Unicode. + #define XimLookupString Xutf8LookupString + #define UTF8_2_Symbol(a) utf8_2_u16(a) + #define Unicode_2_CP(a) Unicode2CP(a) +#else + #define XimLookupString XmbLookupString + #define UTF8_2_Symbol(a) a[0] + #define Unicode_2_CP(a) (a) +#endif + +/***************************************************************************** + + TGKeyX11 keyboard stuff. + +*****************************************************************************/ + +int TGKeyX11::lenKb; +int TGKeyX11::kbWaiting=0; +char TGKeyX11::bufferKb[MaxKbLen+1]; +KeySym TGKeyX11::Key; +unsigned TGKeyX11::kbFlags=0; +uchar TGKeyX11::KeyCodeByKeySym[256]; +unsigned TGKeyX11::Symbol; +unsigned TGKeyX11::Flags; +uchar TGKeyX11::Scan; +uchar TGKeyX11::sendQuit=0; +stIntCodePairs + *TGKeyX11::inputCP=NULL; + +static +uint16 utf8_2_u16(const char *b) +{ + int c=*((uchar *)(b++)); + int n,t; + + if (c & 0x80) + { + n=1; + while (c & (0x80>>n)) + n++; + + c&=(1<<(8-n))-1; + + while (--n>0) + { + t=*((unsigned char *)(b++)); + if ((!(t&0x80)) || (t&0x40)) + return '^'; + c=(c<<6) | (t&0x3F); + } + } + + return c; +} + +int TGKeyX11::getKeyEvent(int block) +{ + Status status; // Currently ignored, but Solaris doesn't support NULL as argument + XEvent event; + + /* If we already have a key use it */ + if (kbWaiting) + return 1; + + SEMAPHORE_ON; + while (1) + { + /* Get the next keyboard event */ + if (XCheckMaskEvent(TScreenX11::disp,aKeyEvent,&event)!=True) + { + if (!IS_SECOND_THREAD_ON) + TScreenX11::ProcessGenericEvents(); + if (block) + continue; + SEMAPHORE_OFF; + return 0; + } + /* Now check if it is a key that will be combined */ + if (XFilterEvent(&event,0)==True) + continue; + if (event.type==KeyPress) + { + //printf("Key event 0x%04X Keysym: 0x%08X\n",event.xkey.state,XLookupKeysym(&event.xkey,3)); + // Ask for the UTF-8 character, better for future applications + lenKb=XimLookupString(TScreenX11::xic,&event.xkey,bufferKb,MaxKbLen,&Key,&status); + bufferKb[lenKb]=0; + //printf("Key event %d %s 0x%04X %d\n",lenKb,bufferKb,(unsigned)Key,bufferKb[0]); + /* FIXME: how can I know the state before entering the application? */ + #define ToggleBit(a) if (kbFlags & a) kbFlags&=~a; else kbFlags|=a + /* Look if that's a modifier */ + switch (Key) + { + case XK_Shift_R: + kbFlags|=kbRightShiftDown; + break; + case XK_Shift_L: + kbFlags|=kbLeftShiftDown; + break; + case XK_Control_R: + kbFlags|=kbRightCtrlDown | kbCtrlDown; + break; + case XK_Control_L: + kbFlags|=kbLeftCtrlDown | kbCtrlDown; + break; + case XK_Alt_R: + kbFlags|=kbRightAltDown | kbAltDown; + break; + case XK_Alt_L: + kbFlags|=kbLeftAltDown | kbAltDown; + break; + case XK_Scroll_Lock: + kbFlags|=kbScrollLockDown; + ToggleBit(kbScrollLockToggle); + break; + case XK_Num_Lock: + kbFlags|=kbNumLockDown; + ToggleBit(kbNumLockToggle); + break; + case XK_Caps_Lock: + kbFlags|=kbCapsLockDown; + ToggleBit(kbCapsLockToggle); + break; + case XK_Insert: + ToggleBit(kbInsertToggle); + kbWaiting=1; + SEMAPHORE_OFF; + return 1; /* Report the key */ + case XK_Sys_Req: + kbFlags|=kbSysReqPress; + kbWaiting=1; + SEMAPHORE_OFF; + return 1; /* Report the key */ + default: + /* If a modifier key is released when we don't have the focus + we get unsynchronized, this code helps to keep in sync. */ + /* Extract the modifiers info: */ + if (event.xkey.state & ShiftMask) + { + if (!(kbFlags & (kbRightShiftDown | kbLeftShiftDown))) + kbFlags|=kbLeftShiftDown; + } + else + { + if (kbFlags & (kbRightShiftDown | kbLeftShiftDown)) + kbFlags&=~(kbRightShiftDown | kbLeftShiftDown); + } + if (event.xkey.state & LockMask) + kbFlags|=kbCapsLockDown; + else + kbFlags&=~kbCapsLockDown; + if (event.xkey.state & ControlMask) + { + if (!(kbFlags & kbCtrlDown)) + kbFlags|=kbCtrlDown | kbLeftCtrlDown; + } + else + { + if (kbFlags & kbCtrlDown) + kbFlags&=~(kbLeftCtrlDown | kbRightCtrlDown | kbCtrlDown); + } + if (event.xkey.state & x11AltMask) + { + if (!(kbFlags & kbAltDown)) + kbFlags|=kbAltDown | kbLeftAltDown; + } + else + { + if (kbFlags & kbAltDown) + kbFlags&=~(kbLeftAltDown | kbRightAltDown | kbAltDown); + } + if (event.xkey.state & x11NumLockMask) + kbFlags|=kbNumLockDown; + else + kbFlags&=~kbNumLockDown; + if (event.xkey.state & x11ScrollLockMask) + kbFlags|=kbScrollLockDown; + else + kbFlags&=~kbScrollLockDown; + kbWaiting=1; + SEMAPHORE_OFF; + return 1; + } + #undef ToggleBit + } + else + { + KeySym k=XLookupKeysym(&event.xkey,0); + switch (k) + { + case XK_Shift_R: + kbFlags&=~kbRightShiftDown; + break; + case XK_Shift_L: + kbFlags&=~kbLeftShiftDown; + break; + case XK_Control_R: + kbFlags&=~kbRightCtrlDown; + if ((kbFlags & kbLeftCtrlDown)==0) + kbFlags&=~kbCtrlDown; + break; + case XK_Control_L: + kbFlags&=~kbLeftCtrlDown; + if ((kbFlags & kbRightCtrlDown)==0) + kbFlags&=~kbCtrlDown; + break; + case XK_Alt_R: + kbFlags&=~kbRightAltDown; + if ((kbFlags & kbLeftAltDown)==0) + kbFlags&=~kbAltDown; + break; + case XK_Alt_L: + kbFlags&=~kbLeftAltDown; + if ((kbFlags & kbRightAltDown)==0) + kbFlags&=~kbAltDown; + break; + case XK_Scroll_Lock: + kbFlags&=~kbScrollLockDown; + break; + case XK_Num_Lock: + kbFlags&=~kbNumLockDown; + break; + case XK_Caps_Lock: + kbFlags&=~kbCapsLockDown; + break; + } + } + } + SEMAPHORE_OFF; + return 0; +} + +int TGKeyX11::KbHit() +{ + if (sendQuit) return 1; + return getKeyEvent(0); +} + +keyEquiv TGKeyX11::XEquiv[]= +{ + /* Cursor control & motion */ + {XK_Home,kbHome}, {XK_Left,kbLeft}, {XK_Up,kbUp}, {XK_Right,kbRight}, + {XK_Down,kbDown}, {XK_Page_Up,kbPgUp}, {XK_Page_Down, kbPgDn}, + {XK_End,kbEnd}, {XK_Begin,kbHome}, + /* Misc Functions */ + {XK_Insert, kbInsert}, {XK_Delete, kbDelete}, + /* TTY Functions */ + {XK_Return, kbEnter}, {XK_BackSpace, kbBackSpace}, {XK_Tab, kbTab}, + {XK_Escape, kbEsc}, + /* Auxilliary Functions */ + {XK_F1, kbF1}, {XK_F2, kbF2}, {XK_F3, kbF3}, {XK_F4, kbF4}, {XK_F5, kbF5}, + {XK_F6, kbF6}, {XK_F7, kbF7}, {XK_F8, kbF8}, {XK_F9, kbF9}, {XK_F10, kbF10}, + {XK_F11, kbF11}, {XK_F12, kbF12}, + /* Keypad Functions */ + {XK_KP_0,kb0}, {XK_KP_1,kb1}, {XK_KP_2,kb2}, {XK_KP_3,kb3}, {XK_KP_4,kb4}, + {XK_KP_5,kb5}, {XK_KP_6,kb6}, {XK_KP_7,kb7}, {XK_KP_8,kb8}, {XK_KP_9,kb9}, + {XK_KP_Enter, kbEnter}, {XK_KP_Home,kbHome}, {XK_KP_Left,kbLeft}, + {XK_KP_Up, kbUp}, {XK_KP_Right,kbRight}, {XK_KP_Down, kbDown}, + {XK_KP_Page_Up, kbPgUp}, {XK_KP_Page_Down,kbPgDn}, {XK_KP_End,kbEnd}, + {XK_KP_Begin, kbHome}, {XK_KP_Insert, kbInsert}, {XK_KP_Delete, kbDelete}, + {XK_KP_Equal, kbEqual}, {XK_KP_Multiply, kbAsterisk}, {XK_KP_Add, kbPlus}, + {XK_KP_Subtract, kbMinus}, {XK_KP_Decimal, kbStop}, {XK_KP_Divide, kbSlash}, + /* End */ + {0,0} +}; + +uchar TGKeyX11::KeyCodeByASCII[96]= +{ + kbSpace,kbAdmid,kbDobleQuote,kbNumeral,kbDolar,kbPercent,kbAmper,kbQuote, + kbOpenPar,kbClosePar,kbAsterisk,kbPlus,kbComma,kbMinus,kbStop,kbSlash, + kb0,kb1,kb2,kb3,kb4,kb5,kb6,kb7, + kb8,kb9,kbDoubleDot,kbColon,kbLessThan,kbEqual,kbGreaterThan,kbQuestion, + kbA_Roba,kbA,kbB,kbC,kbD,kbE,kbF,kbG, + kbH,kbI,kbJ,kbK,kbL,kbM,kbN,kbO, + kbP,kbQ,kbR,kbS,kbT,kbU,kbV,kbW, + kbX,kbY,kbZ,kbOpenBrace,kbBackSlash,kbCloseBrace,kbCaret,kbUnderLine, + kbGrave,kbA,kbB,kbC,kbD,kbE,kbF,kbG, + kbH,kbI,kbJ,kbK,kbL,kbM,kbN,kbO, + kbP,kbQ,kbR,kbS,kbT,kbU,kbV,kbW, + kbX,kbY,kbZ,kbOpenCurly,kbOr,kbCloseCurly,kbTilde,kbBackSpace +}; + +ushort TGKeyX11::GKey() +{ + unsigned name; + + getKeyEvent(1); + kbWaiting=0; + + if ((Key & 0xFF00)==0xFF00) + {/* Special keys by keysym */ + Symbol=(unsigned char)bufferKb[0]; + name=KeyCodeByKeySym[Key & 0xFF]; + //printf("Key by keysym 0x%X name: %d Symbol %d\n",(unsigned)Key,name,Symbol); + } + else if (lenKb!=0) + {/* A key by their ASCII */ + Symbol=UTF8_2_Symbol(bufferKb); + if (Symbol==0 && Key==' ') + name=kbSpace; // Why Ctrl+Space reports it? is my X? + else if (Symbol==0 && Key=='2') + name=kb2; // And this one? + else + { + if (Symbol>=32 && Symbol<128) + name=KeyCodeByASCII[Symbol-32]; + else + { + if (Symbol>=1 && Symbol<=26) // ^A to ^Z + name=kbA+Symbol-1; + else + { + if (Symbol>26 && Symbol<32) // ^{ ^\ ^} ?? ^/ + name=KeyCodeByASCII[Key-32]; + else + {// >=128, handle them using Unicode + name=kbUnkNown; + Symbol=Unicode_2_CP(Symbol); + } + } + } + } + //printf("Key of lenght %d: name: %d Symbol %04X Key: 0x%04X\n",lenKb,name,Symbol,(unsigned)Key); + } + else + {/* A key with something else, not handled yet */ + Symbol=0; + name=kbUnkNown; + } + Scan=Key & 0xFF; + + /* Process the flags, just like if it came from an IBM BIOS */ + Flags=0; + if (kbFlags & (kbLeftShiftDown | kbRightShiftDown)) + Flags|=kbShiftCode; + if (kbFlags & kbCtrlDown) + Flags|=kbCtrlCode; + switch (AltSet) + { + case 0: // Normal thing, left is left, right is right + if (kbFlags & kbLeftAltDown) + Flags|=kbAltLCode; + else + if (kbFlags & kbAltDown) + Flags|=kbAltRCode; + break; + case 1: // Reverse thing + if (kbFlags & kbLeftAltDown) + Flags|=kbAltRCode; + else + if (kbFlags & kbAltDown) + Flags|=kbAltLCode; + break; + default: // Compatibility + if (kbFlags & (kbLeftAltDown | kbAltDown)) + Flags|=kbAltLCode; + } + + return name|Flags; +} + +static +int compare(const void *v1, const void *v2) +{ + stIntCodePairs *p1=(stIntCodePairs *)v1; + stIntCodePairs *p2=(stIntCodePairs *)v2; + return (p1->unicode>p2->unicode)-(p1->unicodeunicode); +} + +unsigned TGKeyX11::Unicode2CP(uint16 unicode) +{ + if (!inputCP) + return unicode; + stIntCodePairs se,*re; + se.unicode=unicode; + re=(stIntCodePairs *)bsearch(&se,inputCP,256,sizeof(stIntCodePairs),compare); + /*if (!re) + printf("No encuentro U+%04X\n",unicode);*/ + return re ? re->code : '?'; +} + +unsigned TGKeyX11::GetShiftState() +{ + return kbFlags; +} + +void TGKeyX11::FillTEvent(TEvent &e) +{ + if (sendQuit) + { + sendQuit=0; + e.what=evCommand; + e.message.command=cmQuit; + return; + } + ushort Abstract=GKey(); + e.keyDown.charScan.charCode=((Flags & kbAltLCode) && (Symbol<128)) ? 0 : Symbol; + e.keyDown.charScan.scanCode=Scan; + e.keyDown.raw_scanCode=Scan; + e.keyDown.keyCode=Abstract; + e.keyDown.shiftState=kbFlags; + e.what=evKeyDown; +} + +void TGKeyX11::Init() +{ + TGKey::kbhit =KbHit; + TGKey::gkey =GKey; + TGKey::getShiftState=GetShiftState; + TGKey::fillTEvent =FillTEvent; + TGKey::SetCodePage =SetCodePage; + /* Initialize keyboard tables */ + for (int i=0; XEquiv[i].symbol; i++) + KeyCodeByKeySym[XEquiv[i].symbol & 0xFF]=XEquiv[i].key; + /* Find which encoding is used for input */ + if (!inputCP) + inputCP=new stIntCodePairs[256]; + TVCodePage::GetUnicodesForCP(TVCodePage::GetInpCodePage(),inputCP); +} + +int TGKeyX11::SetCodePage(int id) +{ + if (!inputCP) + inputCP=new stIntCodePairs[256]; + TVCodePage::GetUnicodesForCP(id,inputCP); + return TGKey::defaultSetCodePage(id); +} +#else + +#include +#include + +#endif // defined(TVOS_UNIX) && defined(HAVE_X11) + diff --git a/tvision/classes/x11/x11mouse.cc b/tvision/classes/x11/x11mouse.cc new file mode 100644 index 0000000..d81abd6 --- /dev/null +++ b/tvision/classes/x11/x11mouse.cc @@ -0,0 +1,107 @@ +/* X11 mouse routines. + Copyright (c) 2001-2003 by Salvador E. Tropea (SET) + Covered by the GPL license. */ +#include + +//#define Uses_stdio +#define Uses_TDisplay +#define Uses_TScreen +#define Uses_TEvent +#define Uses_TEventQueue +#include + +// I delay the check to generate as much dependencies as possible +#if (defined(TVOS_UNIX) || defined(TVCompf_Cygwin)) && defined(HAVE_X11) + +// X11 defines their own values +#undef True +#undef False +#include +#include + +#include +#include + +/***************************************************************************** + + THWMouseX11 mouse stuff. + +*****************************************************************************/ + +unsigned THWMouseX11::mouseButtons=0; +unsigned THWMouseX11::mouseX=0; +unsigned THWMouseX11::mouseY=0; +unsigned THWMouseX11::buttonTranslate[8]= +{ + 0, // First button is 1 + mbLeftButton,mbMiddleButton,mbRightButton,mbButton4,mbButton5, + 0,0 +}; + +int THWMouseX11::getMouseEvent() +{ + XEvent event; + + SEMAPHORE_ON; + while (1) + { + /* Get the next mouse event */ + if (XCheckMaskEvent(TScreenX11::disp,aMouseEvent,&event)!=True) + { + if (!IS_SECOND_THREAD_ON) + TScreenX11::ProcessGenericEvents(); + SEMAPHORE_OFF; + return 0; + } + /* Is that needed here? */ + if (XFilterEvent(&event,0)==True) + continue; + if (event.type==ButtonPress || event.type==ButtonRelease || + event.type==MotionNotify) + { + mouseX=event.xbutton.x/TScreenX11::fontW; + mouseY=event.xbutton.y/TScreenX11::fontH; + // Clamp the values, they could be negative + if (event.xbutton.x<0) mouseX=0; + if (event.xbutton.y<0) mouseY=0; + if (event.type==ButtonPress) + mouseButtons|=buttonTranslate[event.xbutton.button & 0x7]; + else + if (event.type==ButtonRelease) + mouseButtons&=~buttonTranslate[event.xbutton.button & 0x7]; + //printf("Button Press %d mouseButtons=%d\n",event.xbutton.button,mouseButtons); + //printf("Button Release %d (%d,%d) vs (%d,%d)\n",event.xbutton.button,event.xbutton.x/TScreenX11::fontW,event.xbutton.y/TScreenX11::fontH,mouseX,mouseY); + //printf("Motion Notify %d,%d\n",mouseX,mouseY); + SEMAPHORE_OFF; + return 1; + } + } + SEMAPHORE_OFF; + return 0; +} + +void THWMouseX11::GetEvent(MouseEventType &me) +{ + getMouseEvent(); + me.where.x=mouseX; + me.where.y=mouseY; + me.buttons=mouseButtons; + me.doubleClick=False; +} + +void THWMouseX11::Init() +{ + THWMouse::GetEvent=GetEvent; + buttonCount=5; +} + +THWMouseX11::~THWMouseX11() +{ +} +#else + +#include +#include + +#endif // defined(TVOS_UNIX) && defined(HAVE_X11) + diff --git a/tvision/classes/x11/x11src.cc b/tvision/classes/x11/x11src.cc new file mode 100644 index 0000000..9cdc398 --- /dev/null +++ b/tvision/classes/x11/x11src.cc @@ -0,0 +1,2710 @@ +/* X11 screen routines. + Copyright (c) 2001-2007 by Salvador E. Tropea (SET) + Covered by the GPL license. + Thanks to José Ángel Sánchez Caso (JASC). He implemented a first X11 + driver. + This implementation is completly different but JASC's code gave me the + first notions about how an X11 application works. + + ToDo: + * The SetDisPaletteColors does a redraw, it should be avoided, at least + for 8 bpp modes, BTW they are untested. + + Configuration variables: + Font10x20=0 Selects the 10x20 font instead of 8x16 + ScreenWidth + ScreenHeight + ScreenPalette + FontWidth + FontHeight + LoadSecondaryFont + AppCP + ScrCP + InpCP + HideCursorWhenNoFocus + DontResizeToCells Don't resize the window to a cells multiple size if the WM + fails to follow the hints. This helps to avoid problems found + in KDE 3.1 alpha. + InternalBusyCursor When enabled we use our own mouse cursor for it + UseUpdateThread Uses a separated thread to update the window content. + +*/ +#ifndef _GNU_SOURCE + #define _GNU_SOURCE +#endif + +#include + +// That's a nasty side effect: X defines Boolean! +#if (defined(TVOS_UNIX) || defined(TVCompf_Cygwin)) && defined(HAVE_X11) + #include +#endif + +#define Uses_stdio +#define Uses_stdlib +#define Uses_string +#define Uses_unistd // TScreenX11::System +#define Uses_signal +#define Uses_fcntl // open +#define Uses_snprintf +#define Uses_AllocLocal +#define Uses_TDisplay +#define Uses_TScreen +#define Uses_TGKey // For TGKeyX11 +#define Uses_TEvent // For THWMouseX11 +#define Uses_TVCodePage +#define Uses_TVOSClipboard +#define Uses_TNSCollection +#include + +// I delay the check to generate as much dependencies as possible +#if (defined(TVOS_UNIX) || defined(TVCompf_Cygwin)) && defined(HAVE_X11) + +// X11 defines their own values +#undef True +#undef False +#define True 1 +#define False 0 + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#ifdef HAVE_LINUX_PTHREAD + #include +#endif + +#ifdef TVOSf_Solaris + // At least in the Solaris 7 box I tested looks like ITIMER_REAL is broken + // and behaves like ITIMER_VIRTUAL + #define ITIMER_USED ITIMER_REALPROF + #define TIMER_ALARM SIGPROF +#else + #define ITIMER_USED ITIMER_REAL + #define TIMER_ALARM SIGALRM +#endif + +const unsigned foWmin=5, foHmin=7, foWmax=20, foHmax=32; +const int cursorDelay=300000; + +/***************************************************************************** + + TScreenX11 screen stuff. + +*****************************************************************************/ + +Display *TScreenX11::disp; +ulong TScreenX11::screen; +Visual *TScreenX11::visual; +Window TScreenX11::rootWin; +Window TScreenX11::mainWin; +Colormap TScreenX11::cMap; +GC TScreenX11::gc; +GC TScreenX11::cursorGC=NULL; +XIC TScreenX11::xic=NULL; +XIM TScreenX11::xim=NULL; +Atom TScreenX11::theProtocols; +ulong TScreenX11::colorMap[16]; +XImage *TScreenX11::ximgFont[256]; /* Our "font" is just a collection of images */ +XImage *TScreenX11::ximgSecFont[256]; +XImage *TScreenX11::cursorImage=NULL; +int TScreenX11::fg; +int TScreenX11::bg; +char TScreenX11::cursorEnabled=1; +char TScreenX11::cursorInScreen=0; +uchar TScreenX11::curAttr; +uchar TScreenX11::primaryFontChanged=0; +char *TScreenX11::cursorData=NULL; +char TScreenX11::hideCursorWhenNoFocus=1; +char TScreenX11::dontResizeToCells=0; +struct +timeval TScreenX11::refCursorTime, + TScreenX11::curCursorTime; +XSizeHints *TScreenX11::sizeHints=NULL; +XClassHint *TScreenX11::classHint=NULL; + +TScreenX11::~TScreenX11() +{ + STOP_UPDATE_THREAD; + + if (sizeHints) + XFree(sizeHints); + if (classHint) + { + delete[] classHint->res_name; + delete[] classHint->res_class; + classHint->res_name=NULL; + classHint->res_class=NULL; + XFree(classHint); + } + + if (xic) + XDestroyIC(xic); + if (xim) + XCloseIM(xim); + + DestroyXImageFont(0); + DestroyXImageFont(1); + if (cursorImage) + XDestroyImage(cursorImage); + + if (disp) + { + if (TScreen::showBusyState==ShowBusyState) + { + XFreeCursor(disp,busyCursor); + XFreeCursor(disp,leftPtr); + } + + if (cursorGC) + XFreeGC(disp,cursorGC); + XDestroyWindow(disp,mainWin); + XCloseDisplay(disp); //This could do all of the above for us, but anyway... + } + + delete[] screenBuffer; + +} + +void TScreenX11::clearScreen() +{ + SEMAPHORE_ON; + XSetForeground(disp,gc,colorMap[bg]); + XFillRectangle(disp,mainWin,gc,0,0,maxX*fontW,maxY*fontH); + XSetForeground(disp,gc,colorMap[fg]); + + char space[2]; + space[charPos]=' '; + space[attrPos]=curAttr; + + unsigned c=maxX*maxY; + while (c--) + screenBuffer[c]=*((ushort *)space); + SEMAPHORE_OFF; +} + +inline +void TScreenX11::drawChar(GC gc, unsigned x, unsigned y, uchar aChar, uchar aAttr) +{ + if (useSecondaryFont && (aAttr & 0x8)) + XPutImage(disp,mainWin,gc,ximgSecFont[aChar],0,0,x,y,fontW,fontH); + else + XPutImage(disp,mainWin,gc,ximgFont[aChar],0,0,x,y,fontW,fontH); +} + +void TScreenX11::setCharacter(unsigned offset, ushort value) +{ + if (screenBuffer[offset]==value) + return; + screenBuffer[offset]=value; + + unsigned x,y; + x=(offset%maxX)*fontW; + y=(offset/maxX)*fontH; + + uchar *theChar=(uchar *)(screenBuffer+offset); + uchar newChar=theChar[charPos]; + uchar newAttr=theChar[attrPos]; + + SEMAPHORE_ON; + XSetBgFg(newAttr); + UnDrawCursor(); + drawChar(gc,x,y,newChar,newAttr); + DrawCursor(); + XFlush(disp); + SEMAPHORE_OFF; +} + +void TScreenX11::setCharacters(unsigned offset, ushort *values, unsigned count) +{ + // Skip repeated characters at the left + for (; count && screenBuffer[offset]==*values; count--, offset++, values++); + // Skip repeated characters at the right + for (; count && screenBuffer[offset+count-1]==values[count-1]; count--); + if (!count) // All skipped + return; + + unsigned x,y; + x=(offset%maxX)*fontW; + y=(offset/maxX)*fontH; + + uchar *b=(uchar *)values,newChar,newAttr; + uchar *sb=(uchar *)(screenBuffer+offset); + unsigned oldAttr=0x100; + + SEMAPHORE_ON; + UnDrawCursor(); + while (count--) + { + newChar=b[charPos]; + newAttr=b[attrPos]; + if (newChar!=sb[charPos] || newAttr!=sb[attrPos]) + { + sb[charPos]=newChar; + sb[attrPos]=newAttr; + if (newAttr!=oldAttr) + { + XSetBgFg(newAttr); + oldAttr=newAttr; + } + drawChar(gc,x,y,newChar,newAttr); + } + x+=fontW; b+=2; sb+=2; + } + DrawCursor(); + XFlush(disp); + SEMAPHORE_OFF; +} + +int TScreenX11::System(const char *command, pid_t *pidChild, int in, int out, + int err) +{ + if (!pidChild) + { + // If the caller asks for redirection replace the requested handles + if (in!=-1) + dup2(in,STDIN_FILENO); + if (out!=-1) + dup2(out,STDOUT_FILENO); + if (err!=-1) + dup2(err,STDERR_FILENO); + return system(command); + } + + pid_t cpid=fork(); + if (cpid==0) + {// Ok, we are the child + // I'm not sure about it, but is the best I have right now. + // Doing it we can kill this child and all the subprocesses + // it creates by killing the group. It also have an interesting + // effect that I must evaluate: By doing it this process lose + // the controlling terminal and won't be able to read/write + // to the parents console. I think that's good. + if (setsid()==-1) + _exit(127); + + // If the caller asks for redirection replace the requested handles + if (in!=-1) + dup2(in,STDIN_FILENO); + if (out!=-1) + dup2(out,STDOUT_FILENO); + if (err!=-1) + dup2(err,STDERR_FILENO); + + if (NO_EXEC_IN_THREAD && IS_SECOND_THREAD_ON) + {// That's very Linux specific: + // For some (unknown) reason we can't use exec here. If we use exec then + // the update thread dies and the "monitoring" thread becomes a Zombie. + // The only safe way is to call system(), it have code to stop + // multithreading and then call exec. That's the only safe way. + //pthread_kill_other_threads_np(); <= Useless + + // Note: this solution is incomplete, if the user tries to kill the + // child using pidChild then the update thread will misteriously die. + // For this reason I use a watchdog that checks if the thread worked + // in the last second. If not we revert to manual screen update. + + system(command); + // Here we must exit but without deallocating resources! just exit, + // that's all + _exit(0); + } + else + {// This is much more efficient, but only works if pthreads are off. + char *argv[4]; + argv[0]=newStr(getenv("SHELL")); + if (!argv[0]) + argv[0]=newStr("/bin/sh"); + argv[1]=newStr("-c"); + argv[2]=newStr(command); + argv[3]=0; + execvp(argv[0],argv); + delete[] argv[0]; + delete[] argv[1]; + delete[] argv[2]; + // We get here only if exec failed + _exit(127); + } + } + if (cpid==-1) + {// Fork failed do it manually + *pidChild=0; + return system(command); + } + *pidChild=cpid; + return 0; +} + +uchar TScreenX11::shapeFont10x20[]= +{ + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x4C,0x80,0x4C,0x80,0x7C,0x80,0x79,0x80,0x73,0x80,0x73,0x80,0x73,0x80,0x7F,0x80,0x73,0x80,0x73,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x80,0x6D,0x80,0x67,0x00,0x00,0x00,0x39,0x80,0x6D,0x80,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x36,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x67,0x80,0x66,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x36,0x00,0x1F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x6D,0x80,0x6D,0x80,0x6F,0x80,0x6C,0x00,0x6C,0x00,0x6D,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x3F,0x00,0x7F,0x80,0x7F,0x80,0x3F,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x7E,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x00,0x00,0x1F,0x80,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x7C,0x00,0x60,0x00,0x60,0x00,0x78,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x0F,0x80,0x0C,0x00,0x0C,0x00,0x0F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x3C,0x00,0x66,0x00,0x60,0x00,0x60,0x00,0x66,0x00,0x3C,0x00,0x00,0x00,0x1F,0x00,0x19,0x80,0x19,0x80,0x1F,0x00,0x1E,0x00,0x1B,0x00,0x19,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x3E,0x00,0x00,0x00,0x0F,0x80,0x0C,0x00,0x0C,0x00,0x0F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x55,0x40,0x00,0x00,0xAA,0x80,0x00,0x00,0x55,0x40,0x00,0x00,0xAA,0x80,0x00,0x00,0x55,0x40,0x00,0x00,0xAA,0x80,0x00,0x00,0x55,0x40,0x00,0x00,0xAA,0x80,0x00,0x00,0x55,0x40,0x00,0x00,0xAA,0x80,0x00,0x00, + 0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80,0x55,0x40,0xAA,0x80, + 0x55,0x40,0xFF,0xC0,0xAA,0x80,0xFF,0xC0,0x55,0x40,0xFF,0xC0,0xAA,0x80,0xFF,0xC0,0x55,0x40,0xFF,0xC0,0xAA,0x80,0xFF,0xC0,0x55,0x40,0xFF,0xC0,0xAA,0x80,0xFF,0xC0,0x55,0x40,0xFF,0xC0,0xAA,0x80,0xFF,0xC0, + 0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0, + 0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00, + 0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0, + 0x00,0x00,0x00,0x00,0x66,0x00,0x76,0x00,0x7E,0x00,0x7E,0x00,0x6E,0x00,0x66,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x3C,0x00,0x3C,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x1F,0x80,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x38,0x00,0x0E,0x00,0x03,0x80,0x0E,0x00,0x38,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,0x0E,0x00,0x38,0x00,0xE0,0x00,0x38,0x00,0x0E,0x00,0x03,0x80,0x00,0x00,0x00,0x00,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x18,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x07,0x80,0x1F,0x80,0x7F,0x80,0x7F,0x80,0x1F,0x80,0x07,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x78,0x00,0x7E,0x00,0x7F,0x80,0x7F,0x80,0x7E,0x00,0x78,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x3F,0x00,0x6D,0x80,0x4C,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x4C,0x80,0x6D,0x80,0x3F,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x06,0x00,0x03,0x00,0xFF,0x80,0xFF,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0xFF,0x80,0xFF,0x80,0x60,0x00,0x30,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x3F,0x00,0x6D,0x80,0x4C,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x4C,0x80,0x6D,0x80,0x3F,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0x33,0x00,0x61,0x80,0xFF,0xC0,0xFF,0xC0,0x61,0x80,0x33,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x19,0x80,0x31,0x80,0x7F,0x80,0x7F,0x80,0x30,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x33,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x3F,0xC0,0x1B,0x00,0x1B,0x00,0x1B,0x00,0x7F,0x80,0x36,0x00,0x36,0x00,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x3F,0x00,0x6D,0x80,0x6C,0x00,0x6C,0x00,0x6C,0x00,0x3F,0x00,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x6D,0x80,0x3F,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x80,0x6D,0x80,0x6F,0x00,0x3B,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x1B,0x80,0x1E,0xC0,0x36,0xC0,0x33,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x3C,0x00,0x18,0x00,0x38,0x00,0x6C,0x00,0x66,0xC0,0x63,0x80,0x63,0x00,0x77,0x80,0x3C,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x7F,0x80,0x1E,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1C,0x00,0x3C,0x00,0x6C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x01,0x80,0x01,0x80,0x03,0x00,0x0E,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x01,0x80,0x03,0x00,0x0E,0x00,0x03,0x00,0x01,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x07,0x00,0x0F,0x00,0x1B,0x00,0x33,0x00,0x63,0x00,0x63,0x00,0x7F,0x80,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0x80,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x01,0x80,0x21,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x00,0x01,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x67,0x80,0x6F,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6F,0x00,0x66,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x66,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x66,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x67,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x63,0x00,0x63,0x00,0x66,0x00,0x66,0x00,0x7C,0x00,0x66,0x00,0x66,0x00,0x63,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x73,0x80,0x73,0x80,0x7F,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x71,0x80,0x71,0x80,0x79,0x80,0x79,0x80,0x6D,0x80,0x6D,0x80,0x67,0x80,0x67,0x80,0x63,0x80,0x63,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x6D,0x80,0x67,0x80,0x33,0x00,0x1F,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x66,0x00,0x63,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x60,0x00,0x60,0x00,0x30,0x00,0x1E,0x00,0x03,0x00,0x01,0x80,0x01,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x73,0x80,0x73,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x1E,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0x80,0x01,0x80,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x06,0x00,0x03,0x00,0x03,0x00,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x73,0x00,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x1D,0x80,0x33,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x7F,0x80,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x19,0x80,0x19,0x80,0x18,0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x80,0x63,0x80,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x60,0x00,0x3F,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x3F,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x00,0x00,0x07,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x31,0x80,0x31,0x80,0x31,0x80,0x1F,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x63,0x00,0x66,0x00,0x6C,0x00,0x78,0x00,0x7C,0x00,0x66,0x00,0x63,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5B,0x00,0x7F,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x73,0x00,0x6E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1D,0x80,0x33,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0x00,0x39,0x80,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x60,0x00,0x3F,0x00,0x01,0x80,0x01,0x80,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x19,0x80,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x7F,0x80,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x33,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x61,0x80,0x33,0x00,0x1E,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x01,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x3F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x78,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x07,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x07,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x80,0x6D,0x80,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00, + 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00, + 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x0F,0xC0,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00, + 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0xF8,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00, + 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0xFF,0xC0,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x04,0x00,0x07,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x13,0xC0,0x10,0x00,0x1F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00, + 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xC0,0x10,0x00,0x13,0xC0,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00, + 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x13,0xC0,0x10,0x00,0x13,0xC0,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x08,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0xF2,0x00,0x02,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0xF3,0xC0,0x00,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x02,0x00,0xF2,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00, + 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0xF2,0x00,0x02,0x00,0xF2,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00,0xF3,0xC0,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00, + 0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0xF3,0xC0,0x00,0x00,0xF3,0xC0,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x00,0x60,0x00,0x60,0x00,0x61,0x00,0x33,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x19,0x80,0x19,0x80,0x18,0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x7C,0x00,0x56,0xC0,0x73,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x3F,0x00,0x6D,0x80,0x6C,0x00,0x6C,0x00,0x6C,0x00,0x3F,0x00,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x6D,0x80,0x3F,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x3F,0x00,0x0C,0x00,0x3F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x63,0x00,0x30,0x00,0x3C,0x00,0x66,0x00,0x33,0x00,0x19,0x80,0x0F,0x00,0x03,0x00,0x31,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x5E,0x80,0x52,0x80,0x50,0x80,0x52,0x80,0x5E,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x21,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x80,0x0D,0x80,0x1B,0x00,0x36,0x00,0x6C,0x00,0xD8,0x00,0x6C,0x00,0x36,0x00,0x1B,0x00,0x0D,0x80,0x04,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x7F,0x80,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x5E,0x80,0x52,0x80,0x5E,0x80,0x54,0x80,0x56,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x00,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x36,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x36,0x00,0x06,0x00,0x0C,0x00,0x06,0x00,0x36,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x77,0x00,0x7D,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x7F,0x80,0x7D,0x80,0x7D,0x80,0x7D,0x80,0x3D,0x80,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x0D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x06,0x00,0x36,0x00,0x1C,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x38,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x36,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x1C,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x6C,0x00,0x36,0x00,0x1B,0x00,0x0D,0x80,0x06,0xC0,0x0D,0x80,0x1B,0x00,0x36,0x00,0x6C,0x00,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x60,0x00,0x20,0x80,0x21,0x00,0x72,0x00,0x04,0x00,0x09,0x00,0x13,0x00,0x25,0x00,0x4F,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x60,0x00,0x20,0x80,0x21,0x00,0x72,0x00,0x04,0x00,0x0B,0x00,0x14,0x80,0x20,0x80,0x41,0x00,0x02,0x00,0x07,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x08,0x00,0x30,0x80,0x09,0x00,0x72,0x00,0x04,0x00,0x09,0x00,0x13,0x00,0x25,0x00,0x4F,0x80,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x19,0x00,0x3F,0x00,0x26,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x1E,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x1E,0x00,0x36,0x00,0x36,0x00,0x66,0x00,0x66,0x00,0x7F,0x80,0x66,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x67,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x61,0x80,0x33,0x00,0x1E,0x00,0x0C,0x00,0x06,0x00,0x36,0x00,0x1C,0x00, + 0x00,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x00,0x00,0x3F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x3F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x3F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x3F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0xF9,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x19,0x00,0x3F,0x00,0x26,0x00,0x00,0x00,0x61,0x80,0x71,0x80,0x79,0x80,0x79,0x80,0x6D,0x80,0x6D,0x80,0x67,0x80,0x67,0x80,0x63,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x19,0x00,0x3F,0x00,0x26,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x63,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x36,0x00,0x63,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x80,0x1F,0x00,0x33,0x00,0x63,0x80,0x63,0x80,0x65,0x80,0x65,0x80,0x65,0x80,0x69,0x80,0x69,0x80,0x69,0x80,0x71,0x80,0x33,0x00,0x3E,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x3F,0x00,0x31,0x80,0x31,0x80,0x31,0x80,0x31,0x80,0x31,0x80,0x3F,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x1B,0x00,0x31,0x80,0x31,0x80,0x33,0x00,0x76,0x00,0x36,0x00,0x33,0x00,0x31,0x80,0x31,0x80,0x31,0x80,0x33,0x00,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x00,0x3F,0x00,0x26,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3B,0x00,0x4D,0x80,0x0D,0x80,0x0F,0x00,0x3C,0x00,0x6C,0x00,0x6C,0x80,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x0C,0x00,0x06,0x00,0x36,0x00,0x1C,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x7F,0x80,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x7F,0x80,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x7F,0x80,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x7F,0x80,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x00,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x07,0xC0,0x01,0x80,0x1D,0x80,0x33,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x00,0x3F,0x00,0x26,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x00,0x3F,0x00,0x26,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x7F,0x80,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x1F,0x00,0x33,0x00,0x65,0x80,0x65,0x80,0x69,0x80,0x69,0x80,0x33,0x00,0x3E,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x61,0x80,0x33,0x00,0x1E,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x3E,0x00,0x33,0x00,0x31,0x80,0x31,0x80,0x31,0x80,0x33,0x00,0x3E,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x33,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x61,0x80,0x33,0x00,0x1E,0x00, +}; + +uchar TScreenX11::shapeFont8x16[]= +{ + 0x00,0x00,0x7E,0xC3,0x99,0x99,0xF3,0xE7,0xE7,0xFF,0xE7,0xE7,0x7E,0x00,0x00,0x00, // 0 + 0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x6E,0xF8,0xD8,0xD8,0xDC,0xD8,0xD8,0xD8,0xF8,0x6E,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0x00,0x6E,0xDB,0xDB,0xDF,0xD8,0xDB,0x6E,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00, //  + 0x00,0x88,0x88,0xF8,0x88,0x88,0x00,0x3E,0x08,0x08,0x08,0x08,0x00,0x00,0x00,0x00, //  + 0x00,0xF8,0x80,0xE0,0x80,0x80,0x00,0x3E,0x20,0x38,0x20,0x20,0x00,0x00,0x00,0x00, //  + 0x00,0x70,0x88,0x80,0x88,0x70,0x00,0x3C,0x22,0x3C,0x24,0x22,0x00,0x00,0x00,0x00, //  + 0x00,0x80,0x80,0x80,0x80,0xF8,0x00,0x3E,0x20,0x38,0x20,0x20,0x00,0x00,0x00,0x00, //  + 0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44, // \t + 0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA, // \n + 0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77, // + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // \r + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //  + 0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0, //  + 0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, //  + 0x00,0x88,0xC8,0xA8,0x98,0x88,0x00,0x20,0x20,0x20,0x20,0x3E,0x00,0x00,0x00,0x00, //  + 0x00,0x88,0x88,0x50,0x50,0x20,0x00,0x3E,0x08,0x08,0x08,0x08,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0x0E,0x38,0xE0,0x38,0x0E,0x00,0xFE,0x00,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0xE0,0x38,0x0E,0x38,0xE0,0x00,0xFE,0x00,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x06,0x0C,0xFE,0x18,0x30,0xFE,0x60,0xC0,0x00,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0x06,0x1E,0x7E,0xFE,0x7E,0x1E,0x06,0x00,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0xC0,0xF0,0xFC,0xFE,0xFC,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // 0x1A + 0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0x00,0x28,0x6C,0xFE,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0x06,0x36,0x66,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // + 0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // ! + 0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // " + 0x00,0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00, // # + 0x00,0x10,0x10,0x7C,0xD6,0xD0,0xD0,0x7C,0x16,0x16,0xD6,0x7C,0x10,0x10,0x00,0x00, // $ + 0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00, // % + 0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // & + 0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ' + 0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00, // ( + 0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00, // ) + 0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00, // * + 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // + + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00, // , + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // - + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // . + 0x00,0x00,0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00,0x00,0x00,0x00,0x00, // / + 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 0 + 0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00, // 1 + 0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00, // 2 + 0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3 + 0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00, // 4 + 0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5 + 0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 6 + 0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00, // 7 + 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 8 + 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00, // 9 + 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, // : + 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00, // ; + 0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00, // < + 0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // = + 0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00, // > + 0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // ? + 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0x7C,0x00,0x00,0x00,0x00, // @ + 0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // A + 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00, // B + 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00, // C + 0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00, // D + 0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00, // E + 0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // F + 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00, // G + 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // H + 0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // I + 0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00, // J + 0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // K + 0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00, // L + 0x00,0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // M + 0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // N + 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // O + 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // P + 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00, // Q + 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // R + 0x00,0x00,0x7C,0xC6,0xC6,0x64,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // S + 0x00,0x00,0x7E,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // T + 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // U + 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00, // V + 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00, // W + 0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00, // X + 0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // Y + 0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00, // Z + 0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00, // [ + 0x00,0x00,0x00,0x00,0x00,0xC0,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00,0x00, // \ . + 0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00, // ] + 0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ^ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00, // _ + 0x00,0x30,0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ` + 0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // a + 0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00, // b + 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // c + 0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // d + 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // e + 0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // f + 0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0xCC,0x78,0x00, // g + 0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // h + 0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // i + 0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00, // j + 0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00, // k + 0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // l + 0x00,0x00,0x00,0x00,0x00,0xEC,0xFE,0xD6,0xD6,0xD6,0xD6,0xC6,0x00,0x00,0x00,0x00, // m + 0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, // n + 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // o + 0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00, // p + 0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00, // q + 0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // r + 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00, // s + 0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00, // t + 0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // u + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00, // v + 0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00, // w + 0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00, // x + 0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00, // y + 0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00, // z + 0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00, // { + 0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // | + 0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00, // } + 0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ~ + 0x00,0x66,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, //  + 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // € + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ‚ + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ƒ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // „ + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // … + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // † + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // ‡ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ˆ + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ‰ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Š + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ‹ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // Œ + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // Ž + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00, // + 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ‘ + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x60,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ’ + 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6F,0x60,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // “ + 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C, // ” + 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C, // • + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x60,0x6F,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C, // – + 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6F,0x60,0x6F,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C, // — + 0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x0C,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ˜ + 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0xEC,0x0C,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ™ + 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // š + 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0xEF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // › + 0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x0C,0xEC,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C, // œ + 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0xEC,0x0C,0xEC,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C, // + 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xEF,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C, // ž + 0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0xEF,0x00,0xEF,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C, // Ÿ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0xFE,0x00,0x00,0x00,0x00, //   + 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00, // ¡ + 0x00,0x00,0x00,0x00,0x10,0x7C,0xD6,0xD0,0xD0,0xD0,0xD6,0x7C,0x10,0x00,0x00,0x00, // ¢ + 0x00,0x00,0x38,0x6C,0x60,0x60,0xF0,0x60,0x60,0x66,0xF6,0x6C,0x00,0x00,0x00,0x00, // £ + 0x00,0x00,0x00,0x00,0xC6,0x7C,0x6C,0x6C,0x7C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00, // ¤ + 0x00,0x00,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // ¥ + 0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // ¦ + 0x00,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00, // § + 0x00,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ¨ + 0x00,0x00,0x3C,0x42,0x99,0xA5,0xA1,0xA5,0x99,0x42,0x3C,0x00,0x00,0x00,0x00,0x00, // © + 0x00,0x00,0x3C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ª + 0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00, // « + 0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00, // ¬ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ­ + 0x00,0x00,0x3C,0x42,0xB9,0xA5,0xB9,0xA5,0xA5,0x42,0x3C,0x00,0x00,0x00,0x00,0x00, // ® + 0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ¯ + 0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ° + 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x7E,0x00,0x00,0x00,0x00, // ± + 0x38,0x6C,0x18,0x30,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ² + 0x38,0x6C,0x18,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ³ + 0x00,0x18,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ´ + 0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xF6,0xC0,0xC0,0xC0,0x00, // µ + 0x00,0x00,0x7F,0xD6,0xD6,0x76,0x36,0x36,0x36,0x36,0x36,0x36,0x00,0x00,0x00,0x00, // ¶ + 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // · + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x6C,0x38,0x00, // ¸ + 0x30,0x70,0x30,0x30,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ¹ + 0x00,0x00,0x38,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // º + 0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,0x00, // » + 0x00,0x60,0xE0,0x60,0x66,0x0C,0x18,0x30,0x66,0xCE,0x1A,0x3F,0x06,0x06,0x00,0x00, // ¼ + 0x00,0x60,0xE0,0x60,0x66,0x0C,0x18,0x30,0x6E,0xDB,0x06,0x0C,0x1F,0x00,0x00,0x00, // ½ + 0x70,0xD8,0x30,0xD8,0x76,0x0C,0x18,0x30,0x66,0xCE,0x1A,0x3F,0x06,0x06,0x00,0x00, // ¾ + 0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x30,0x60,0xC6,0xC6,0x7C,0x00,0x00, // ¿ + 0x60,0x30,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // À + 0x0C,0x18,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // Á + 0x10,0x38,0x6C,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, //  + 0x76,0xDC,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // à + 0x00,0x6C,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // Ä + 0x38,0x6C,0x38,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // Å + 0x00,0x00,0x3E,0x78,0xD8,0xD8,0xFC,0xD8,0xD8,0xD8,0xD8,0xDE,0x00,0x00,0x00,0x00, // Æ + 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x0C,0x66,0x3C,0x00, // Ç + 0x60,0x30,0x00,0xFE,0x66,0x60,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00, // È + 0x0C,0x18,0x00,0xFE,0x66,0x60,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00, // É + 0x10,0x38,0x6C,0x00,0xFE,0x66,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00, // Ê + 0x00,0x6C,0x00,0xFE,0x66,0x60,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00, // Ë + 0x60,0x30,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // Ì + 0x06,0x0C,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // Í + 0x18,0x3C,0x66,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // Î + 0x00,0x66,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // Ï + 0x00,0x00,0xF8,0x6C,0x66,0x66,0xF6,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00, // Ð + 0x76,0xDC,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // Ñ + 0x60,0x30,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // Ò + 0x0C,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // Ó + 0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // Ô + 0x76,0xDC,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // Õ + 0x00,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // Ö + 0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0x18,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00, // × + 0x00,0x00,0x7E,0xC6,0xCE,0xCE,0xDE,0xF6,0xE6,0xE6,0xC6,0xFC,0x00,0x00,0x00,0x00, // Ø + 0x60,0x30,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // Ù + 0x0C,0x18,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // Ú + 0x10,0x38,0x6C,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // Û + 0x00,0x6C,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // Ü + 0x06,0x0C,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // Ý + 0x00,0x00,0xF0,0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x60,0xF0,0x00,0x00,0x00,0x00, // Þ + 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xCC,0xC6,0xC6,0xC6,0xD6,0xDC,0x80,0x00,0x00,0x00, // ß + 0x00,0x60,0x30,0x18,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // à + 0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // á + 0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // â + 0x00,0x00,0x76,0xDC,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // ã + 0x00,0x00,0x00,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // ä + 0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // å + 0x00,0x00,0x00,0x00,0x00,0x7E,0xDB,0x1B,0x7F,0xD8,0xDB,0x7E,0x00,0x00,0x00,0x00, // æ + 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x18,0x6C,0x38,0x00, // ç + 0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // è + 0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // é + 0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // ê + 0x00,0x00,0x00,0x6C,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // ë + 0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // ì + 0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // í + 0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // î + 0x00,0x00,0x00,0x6C,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // ï + 0x00,0x78,0x30,0x78,0x0C,0x7E,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // ð + 0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, // ñ + 0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // ò + 0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // ó + 0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // ô + 0x00,0x00,0x76,0xDC,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // õ + 0x00,0x00,0x00,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // ö + 0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // ÷ + 0x00,0x00,0x00,0x00,0x00,0x7E,0xCE,0xDE,0xFE,0xF6,0xE6,0xFC,0x00,0x00,0x00,0x00, // ø + 0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // ù + 0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // ú + 0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // û + 0x00,0x00,0x00,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // ü + 0x00,0x0C,0x18,0x30,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00, // ý + 0x00,0x00,0xF0,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00,0x00, // þ + 0x00,0x00,0x00,0x6C,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00 // 255 +}; + +TScreenFont256 TScreenX11::font8x16={ 8,16,shapeFont8x16 }; +TScreenFont256 TScreenX11::font10x20={ 10,20,shapeFont10x20 }; +TScreenFont256 *TScreenX11::defaultFont=&font8x16; + +void TScreenX11::AdjustCursorImage() +{ + if (cursorImage) + XDestroyImage(cursorImage); + cursorData=(char *)malloc(fontSz); + cursorImage=XCreateImage(disp,visual,1,XYBitmap,0,cursorData,fontW,fontH,8,0); + cursorImage->byte_order=cursorImage->bitmap_bit_order=MSBFirst; +} + +TScreenX11::TScreenX11() +{ + memset(ximgFont,0,sizeof(XImage *)*256); + memset(ximgSecFont,0,sizeof(XImage *)*256); + + /* Try to connect to the X server */ + disp=XOpenDisplay(NULL); + /* If we fail just return */ + if (!disp) + return; + /* Allocate memory for these structures. Note that is safer to do it instead + of using a static structure because the number of fields can change. */ + sizeHints=XAllocSizeHints(); + classHint=XAllocClassHint(); + if (!sizeHints || !classHint) + return; + + /* Don't need special rights anymore */ + seteuid(getuid()); + setegid(getgid()); + + /* Initialize driver */ + initialized=1; + if (dCB) dCB(); + + maxX=80; maxY=25; + fontW=8; fontH=16; + + /* Look for defaults */ + + /* Code page */ + optSearch("AppCP",forcedAppCP); + optSearch("ScrCP",forcedScrCP); + optSearch("InpCP",forcedInpCP); + /* User settings have more priority than detected settings */ + codePage=new TVCodePage(forcedAppCP!=-1 ? forcedAppCP : TVCodePage::ISOLatin1Linux, + forcedScrCP!=-1 ? forcedScrCP : TVCodePage::ISOLatin1Linux, + forcedInpCP!=-1 ? forcedInpCP : TVCodePage::ISOLatin1Linux); + SetDefaultCodePages(TVCodePage::ISOLatin1Linux,TVCodePage::ISOLatin1Linux, + TVCodePage::ISOLatin1Linux); + + long aux; + if (optSearch("ScreenWidth",aux)) + maxX=aux; + if (optSearch("ScreenHeight",aux)) + maxY=aux; + if (optSearch("FontWidth",aux)) + fontW=aux; + if (optSearch("FontHeight",aux)) + fontH=aux; + if (optSearch("Font10x20",aux) && aux) + fontW=10, fontH=20; + + if (fontW==10 || fontH==20) + defaultFont=&font10x20; + else + defaultFont=&font8x16; + TScreenFont256 *useFont; + int freeFontData=1; + if (!frCB || !(useFont=frCB(0,fontW,fontH))) + { + useFont=defaultFont; + freeFontData=0; + } + fontW=useFont->w; + fontH=useFont->h; + fontWb=(useFont->w+7)/8; + fontSz=fontWb*fontH; + uchar *fontData=useFont->data; + + aux=0; + TScreenFont256 *secFont=NULL; + if (frCB && optSearch("LoadSecondaryFont",aux) && aux) + secFont=frCB(1,fontW,fontH); + + /* Setting to fine tune this driver */ + aux=1; + if (optSearch("HideCursorWhenNoFocus",aux)) + hideCursorWhenNoFocus=aux; + if (optSearch("DontResizeToCells",aux)) + dontResizeToCells=aux; + + TDisplayX11::Init(); + + TScreen::clearScreen=clearScreen; + TScreen::getCharacters=getCharacters; + TScreen::getCharacter=getCharacter; + TScreen::setCharacter=setCharacter; + TScreen::setCharacters=setCharacters; + TScreen::System_p=System; + TScreen::setWindowTitle=setWindowTitle; + TScreen::getWindowTitle=getWindowTitle; + TScreen::setDisPaletteColors=SetDisPaletteColors; + TScreen::getFontGeometry=GetFontGeometry; + TScreen::getFontGeometryRange=GetFontGeometryRange; + TScreen::setFont_p=SetFont; + TScreen::restoreFonts=RestoreFonts; + TScreen::setCrtModeRes_p=SetCrtModeRes; + TDisplay::beep=Beep; + TScreen::openHelperApp=OpenHelperApp; + TScreen::closeHelperApp=CloseHelperApp; + TScreen::sendFileToHelper=SendFileToHelper; + TScreen::getHelperAppError=GetHelperAppError; + + TVX11Clipboard::Init(); + TGKeyX11::Init(); + THWMouseX11::Init(); + + /* Initialize common variables */ + cShapeFrom=fontH*875/1000; + cShapeTo=fontH; + setCrtData(); + startupCursor=cursorLines; + startupMode=screenMode; + screenBuffer=new ushort[screenWidth*screenHeight]; + + /* Get screen and graphic context */ + screen=DefaultScreen(disp); + gc=DefaultGC(disp,screen); + visual=DefaultVisual(disp,screen); + + /* Create what we'll use as font */ + CreateXImageFont(0,fontData,fontW,fontH); + if (freeFontData) + {/* Provided by the call back */ + DeleteArray(useFont->data); + delete useFont; + } + if (secFont) + { + CreateXImageFont(1,secFont->data,fontW,fontH); + DeleteArray(secFont->data); + delete secFont; + } + + /* Create the cursor image */ + AdjustCursorImage(); + + /* Set the locales */ + if (setlocale(LC_ALL,"")==NULL) + fprintf(stderr,"Error: setlocale()!\n"); + + /* Create a simple window */ + rootWin=RootWindow(disp,screen); + mainWin=XCreateSimpleWindow(disp,rootWin, + 0,0, /* win position */ + maxX*fontW,maxY*fontH, /* win size */ + 0, /* frame width */ + BlackPixel(disp,screen), /* Border color */ + BlackPixel(disp,screen)); /* Background */ + + /* This is useful if we use subwindows. + hints.flags=InputHint; + hints.input=True; + XSetWMHints(disp,mainWin,&hints);*/ + /* This is how we provide a title for the window. + If the application wants it should call setWindowTitle. + XTextProperty name; + char *s="Test"; + XStringListToTextProperty(&s,1,&name);*/ + + classHint->res_name=newStr("tvapp"); /* Take resources for tvapp */ + classHint->res_class=newStr("XTVApp"); /* X Turbo Vision Application */ + + /* Size hints are just hints, not all WM take care about them */ + sizeHints->flags=PResizeInc | PMinSize | PBaseSize; + /* Fonts increments */ + sizeHints->width_inc =fontW; + sizeHints->height_inc=fontH; + sizeHints->min_width =fontW*40; + sizeHints->min_height=fontH*20; + sizeHints->base_width=sizeHints->base_height=0; + + XSetWMProperties(disp,mainWin, + NULL, /* Visible title, i.e. &name */ + NULL, /* Icon title, i.e. &name */ + NULL,0, /* Command line */ + sizeHints, /* Normal size hints, resize increments */ + NULL, /* Window manager hints, nothing (i.e. icon) */ + classHint); /* Resource name and class of window */ + + /* This is needed to release the memory used for the title + XFree((char *)name.value);*/ + + /* Ask to be notified when they kill the window */ + theProtocols=XInternAtom(disp,"WM_DELETE_WINDOW",True); + XSetWMProtocols(disp,mainWin,&theProtocols,1); + + /* Initialize the Input Context for international support */ + if ((xim=XOpenIM(disp,NULL,NULL,NULL))==NULL) + { + printf("Error: XOpenIM()!\n"); + exit(0); + } + xic=XCreateIC(xim,XNInputStyle,XIMPreeditNothing | XIMStatusNothing, + XNClientWindow,mainWin,NULL); + if (xic==NULL) + { + printf("Error: XCreateIC()!\n"); + XCloseIM(xim); + exit(0); + } + // This prints which locale was detected for the X Input Methode. + // It should have a very big impact in the way input is interpreted, but I + // couldn't verify it. I'm trying using japanese ;-) + //printf("Locale: %s\n",XLocaleOfIM(xim)); + + /* We will accept the Input Context default events ... */ + unsigned long mask, fevent; + XGetICValues(xic,XNFilterEvents,&fevent,NULL); + /* plus these */ + mask=ExposureMask | KeyPressMask | KeyReleaseMask | FocusChangeMask | + StructureNotifyMask | ButtonPressMask | ButtonReleaseMask | + ButtonMotionMask/*PointerMotionMask*/; + XSelectInput(disp,mainWin,mask|fevent); + + /* OK, now put the window on the display */ + XMapWindow(disp,mainWin); + + /* Map the VGA Text BIOS colors */ + cMap=DefaultColormap(disp,screen); + XColor query; + TScreenColor *pal=parseUserPalette() ? UserStartPalette : PC_BIOSPalette; + for (int col=0; col<16; col++) + { + query.red =pal[col].R*256; + query.green=pal[col].G*256; + query.blue =pal[col].B*256; + query.flags= ~0; + XAllocColor(disp,cMap,&query); + colorMap[col]=query.pixel; + } + memcpy(ActualPalette,pal,sizeof(ActualPalette)); + + /* A graphics context for the text cursor */ + cursorGC=XCreateGC(disp,mainWin,0,0); + + /* Create the cursor timer */ + gettimeofday(&refCursorTime,0); + + XSetBackground(disp,gc,colorMap[0]); + XSetForeground(disp,gc,colorMap[7]); + clearScreen(); + + // Setup the driver properties. + // Our code page isn't fixed. + // We can change the palette. + // A redraw is needed after setting the palette. But currently is in the color setting. + // We can set the fonts and even change their size. + flags0=CanSetPalette | CanReadPalette | CodePageVar | CursorShapes /*| PalNeedsRedraw*/ | + CanSetBFont | CanSetSBFont | CanSetFontSize | CanSetVideoSize | + NoUserScreen; + + if (createCursors()) + TScreen::showBusyState=ShowBusyState; + + START_UPDATE_THREAD; +} + +void TScreenX11::CreateXImageFont(int which, uchar *font, unsigned w, unsigned h) +{ + char *data; + int i,bytesLine,bytesShape; + + bytesLine=(w+7)/8; + bytesShape=bytesLine*h; + XImage **f=which ? ximgSecFont : ximgFont; + for (i=0; i<256; font+=bytesShape, i++) + {/* Load the shape */ + data=(char *)malloc(bytesShape); + memcpy(data,font,bytesShape); + /* Create a BitMap Image with this data */ + f[i]=XCreateImage(disp,visual,1,XYBitmap,0,data,w,h,8,0); + /* Set the bit order, this is faster */ + f[i]->byte_order=f[i]->bitmap_bit_order=MSBFirst; + } + if (which) + useSecondaryFont=1; +} + +void TScreenX11::DestroyXImageFont(int which) +{ + int i; + + if (which) + { + if (useSecondaryFont) + { + for (i=0; i<256; i++) + if (ximgSecFont[i]) + XDestroyImage(ximgSecFont[i]); + useSecondaryFont=0; + } + } + else + for (i=0; i<256; i++) + if (ximgFont[i]) + XDestroyImage(ximgFont[i]); +} + +int TScreenX11::setWindowTitle(const char *aName) +{ + SEMAPHORE_ON; + XTextProperty name; + char *s=(char *)aName; + XStringListToTextProperty(&s,1,&name); + XSetWMName(disp,mainWin,&name); + XFree((char *)name.value); + SEMAPHORE_OFF; + + return 1; +} + +const char *TScreenX11::getWindowTitle(void) +{ + SEMAPHORE_ON; + XTextProperty name; + const char *ret=NULL; + if (XGetWMName(disp,mainWin,&name)) + { + char *s=newStr((char *)name.value); + XFree((char *)name.value); + ret=s; + } + SEMAPHORE_OFF; + + return ret; +} + +int TScreenX11::SetDisPaletteColors(int from, int number, TScreenColor *colors) +{ + SEMAPHORE_ON; + XColor query; + int i; + ulong newMap[16]; + + for (i=0; i0) + {// If we allocated at least one color: + // Deallocated the old colors + XFreeColors(disp,cMap,colorMap+from,i,0); + // Copy the new ones + memcpy(colorMap+from,newMap,sizeof(ulong)*i); + // Force a redraw. This is not needed for 8 bpp. + // Is just a dirty hack. + FullRedraw(); + } + SEMAPHORE_OFF; + return i; +} + +void TScreenX11::FullRedraw() +{ + unsigned y,off; + for (y=0,off=0; y<(unsigned)maxY; y++,off+=maxX) + redrawBuf(0,y,maxX,off); +} + +/***************************************************************************** + Routines to create a blinking cursor +*****************************************************************************/ + +void TScreenX11::UnDrawCursor() +{ + if (!cursorInScreen) + return; + SEMAPHORE_ON; + unsigned offset=cursorX+cursorY*maxX; + uchar *theChar=(uchar *)(screenBuffer+offset); + uchar newChar=theChar[charPos]; + uchar newAttr=theChar[attrPos]; + + XSetBgFgC(newAttr); + drawChar(cursorGC,cursorX*fontW,cursorY*fontH,newChar,newAttr); + cursorInScreen=0; + SEMAPHORE_OFF; + return; +} + +void TScreenX11::XSetBgFgC(uint16 attr) +{ + int bg=attr>>4; + int fg=attr & 0xF; + if (bg==fg) + fg=~bg & 0xF; + XSetBackground(disp,cursorGC,colorMap[bg]); + XSetForeground(disp,cursorGC,colorMap[fg]); +} + +void TScreenX11::XSetBgFg(uint16 attr) +{ + int bg=attr>>4; + int fg=attr & 0xF; + XSetBackground(disp,gc,colorMap[bg]); + XSetForeground(disp,gc,colorMap[fg]); +} + +void TScreenX11::DrawCursor() +{ + //fprintf(stderr,"DrawCursor: cursorEnabled=%d\n",cursorEnabled); + if (cursorEnabled) + { + SEMAPHORE_ON; + cursorInScreen=!cursorInScreen; + + /* Create an image with the character under cursor */ + unsigned offset=cursorX+cursorY*maxX; + uchar *theChar=(uchar *)(screenBuffer+offset); + int attr=theChar[attrPos]; + XSetBgFgC(attr); + memcpy(cursorData,useSecondaryFont && (attr & 8) ? + ximgSecFont[theChar[charPos]]->data : + ximgFont[theChar[charPos]]->data,fontSz); + + //fprintf(stderr,"DrawCursor: cursorInScreen=%d from/to %d/%d\n",cursorInScreen,cShapeFrom,cShapeTo); + /* If the cursor is on draw it over the character */ + if (cursorInScreen) + memset(cursorData+cShapeFrom*fontWb,0xFF,(cShapeTo-cShapeFrom)*fontWb); + + /* Now put it in the screen */ + XPutImage(disp,mainWin,cursorGC,cursorImage,0,0,cursorPX,cursorPY,fontW,fontH); + XFlush(disp); + SEMAPHORE_OFF; + } +} + +void TScreenX11::DisableCursor() +{ + cursorEnabled=0; + UnDrawCursor(); +} + +void TScreenX11::EnableCursor() +{ + cursorEnabled=1; + //DrawCursor(); +} + +static +void SubstractRef(timeval &curCursorTime, timeval &refCursorTime) +{ + curCursorTime.tv_sec-=refCursorTime.tv_sec; + if (curCursorTime.tv_usec0 || curCursorTime.tv_usec>cursorDelay) + { + DrawCursor(); + gettimeofday(&refCursorTime,0); + } + while (1) + { + /* Check if we have generic events in the queue */ + if (XCheckMaskEvent(disp,~(aMouseEvent|aKeyEvent),&event)!=True) + { + /* Process message that doesn't have mask */ + if (XCheckTypedEvent(disp,ClientMessage,&event)==True) + { + if ((Atom)event.xclient.data.l[0]==theProtocols) + { + TGKeyX11::sendQuit=1; + } + } + else if (XCheckTypedEvent(disp,SelectionRequest,&event)==True) + {// Another application wants the content of our clipboard + XEvent respond; + XSelectionRequestEvent *req=&(event.xselectionrequest); + if (req->target==XA_STRING && TVX11Clipboard::buffer) + { + XChangeProperty(disp,req->requestor,req->property,XA_STRING, + 8/*bits*/,PropModeReplace, + (const uchar *)TVX11Clipboard::buffer, + TVX11Clipboard::length); + respond.xselection.property=req->property; + } + else // Strings only please + respond.xselection.property= None; + respond.xselection.type=SelectionNotify; + respond.xselection.display=req->display; + respond.xselection.requestor=req->requestor; + respond.xselection.selection=req->selection; + respond.xselection.target=req->target; + respond.xselection.time=req->time; + XSendEvent(disp,req->requestor,0,0,&respond); + XFlush(disp); + } + else if (XCheckTypedEvent(disp,SelectionNotify,&event)==True) + { + TVX11Clipboard::waiting=0; + TVX11Clipboard::property=event.xselection.property; + } + SEMAPHORE_OFF; + return; + } + /* Not sure if needed, but documentation says it helps if the event + should be redirected to another window */ + if (XFilterEvent(&event,0)==True) + continue; + + switch (event.type) + { + case Expose: + { + if (windowSizeChanged) // Ignore them until the application gets + break; // notified about the new size + /*printf("Expose: %d %d %d %d\n",event.xexpose.x,event.xexpose.y, + event.xexpose.width,event.xexpose.height);*/ + int x=event.xexpose.x/fontW; + int y=event.xexpose.y/fontH; + unsigned src=y*maxX+x; + + newPW=event.xexpose.x+event.xexpose.width; + int x2=newPW/fontW; + if (newPW%fontW) x2++; + if (x2>=maxX) x2=maxX; + + newPW=event.xexpose.y+event.xexpose.height; + int y2=newPW/fontH; + if (newPW%fontH) y2++; + if (y2>=maxY) y2=maxY; + + int w=x2-x; + int h=y2-y; + + /*printf("x1,y1 %d,%d x2,y2 %d,%d w,h %d,%d\n",x,y,x2,y2,w,h);*/ + + while (h) + { + redrawBuf(x,y,w,src); + src+=maxX; + y++; h--; + } + XFlush(disp); + } + break; + + case FocusIn: + //printf("Focus in\n"); + if (xic) + XSetICFocus(xic); + EnableCursor(); + break; + + case FocusOut: + //printf("Focus out\n"); + if (xic) + XUnsetICFocus(xic); + if (hideCursorWhenNoFocus) + DisableCursor(); + break; + + case ConfigureNotify: + /* Currently masked + if (event.xresizerequest.window!=mainWin) + break;*/ + + lastW=windowSizeChanged ? newX : maxX; + lastH=windowSizeChanged ? newY : maxY; + newX=event.xconfigure.width /fontW; + newY=event.xconfigure.height/fontH; + + /* Minimal size */ + if (newX<40) newX=40; + if (newY<20) newY=20; + + /* If size changed indicate it */ + if ((newX!=(int)lastW) || (newY!=(int)lastH)) + windowSizeChanged=1; + + /* KDE 3.1 alpha maximize doesn't use cell sizes and our resize + confuses KDE. */ + if (dontResizeToCells) + break; + + /* Force the window to have a size in chars */ + newPW=fontW*newX; + newPH=fontH*newY; + + if ((unsigned)event.xconfigure.width==newPW && + (unsigned)event.xconfigure.height==newPH) + break; + + //printf("Nuevo: %d,%d (%d,%d)\n",newX,newY,lastW,lastH); + XResizeWindow(disp,mainWin,newPW,newPH); + //printf("Nuevo 2: %d,%d\n",newX,newY); + break; + } + } + SEMAPHORE_OFF; +} + +void TScreenX11::writeLine(int x, int y, int w, unsigned char *str, unsigned color) +{ + if (w<=0) + return; // Nothing to do + + SEMAPHORE_ON; + XSetBgFg(color); + x*=fontW; y*=fontH; + UnDrawCursor(); + XImage **f=(useSecondaryFont && (color & 8)) ? ximgSecFont : ximgFont; + while (w--) + { + XPutImage(disp,mainWin,gc,f[*str],0,0,x,y,fontW,fontH); + str++; + x+=fontW; + } + SEMAPHORE_OFF; +} + +void TScreenX11::redrawBuf(int x, int y, unsigned w, unsigned off) +{ + int len = 0; /* longitud a escribir */ + int letra = 0; + int color = 0; + int last = -1; + AllocLocalStr(tmp,w*sizeof(char)); + uchar *dst = (uchar *)tmp; + uchar *b=(uchar *)(screenBuffer+off); + + if (y>=maxY) + { + printf("Y=%d\n",y); + return; + } + while (w--) + { + letra=b[charPos]; + color=b[attrPos]; + + if (color!=last) + { + if (last>=0) + { + writeLine(x,y,len,(uchar *)tmp,last); // Print last same color block + dst=(uchar *)tmp; x+=len; len=0; + } + last=color; + } + *dst++=letra; b+=2; len++; + } + + writeLine(x,y,len,(uchar *)tmp,color); // Print last block +} + +TScreen *TV_XDriverCheck() +{ + TScreenX11 *drv=new TScreenX11(); + if (!TScreen::initialized) + { + delete drv; + return 0; + } + return drv; +} + +/***************************************************************************** + X11 clipboard routines + This clipboard implementation is heavily based on the + X Windows Copy-Paste mini HOWTO by Stelios Xathakis, +*****************************************************************************/ + +char *TVX11Clipboard::buffer=NULL; +unsigned TVX11Clipboard::length=0; +int TVX11Clipboard::waiting=0; +Atom TVX11Clipboard::property=0; + +const char *TVX11Clipboard::x11NameError[]= +{ + NULL, + __("No available selection"), + __("Unsupported data type"), + __("No data"), + __("X11 error"), + __("Another application holds the clipboard") +}; + +void TVX11Clipboard::Init() +{ + TVOSClipboard::copy=copy; + TVOSClipboard::paste=paste; + TVOSClipboard::destroy=destroy; + TVOSClipboard::available=2; // We have 2 clipboards + TVOSClipboard::name="X11"; + TVOSClipboard::errors=x11clipErrors; + TVOSClipboard::nameErrors=x11NameError; +} + +/**[txh]******************************************************************** + + Description: + Copies the content of the buffer to the X11 clipboard. The id value +selects which clipboard we will use. As current recommendations says +applications should use XA_CLIPBOARD that's id==0. For id==1 we use the +XA_PRIMARY mechanism, this is the one used for "selections".@* + The string doesn't have to be null terminated, we ever copy len+1 bytes +adding a 0 at the end. + + Return: !=0 if ok. + +***************************************************************************/ + +int TVX11Clipboard::copy(int id, const char *b, unsigned len) +{ + if (id>1) return 0; + Atom clip=id==0 ? XA_CLIPBOARD(TScreenX11::disp) : XA_PRIMARY; + + // First create a copy, in X11 the clipboard is held by the application + if (buffer) + delete[] buffer; + length=len; + buffer=new char[length+1]; + memcpy(buffer,b,len); + buffer[len]=0; + //printf("Copiando: `%s' %d\n",buffer,length); + SEMAPHORE_ON; + XSetSelectionOwner(TScreenX11::disp,clip,TScreenX11::mainWin,CurrentTime); + XFlush(TScreenX11::disp); + int ret=0; + if (XGetSelectionOwner(TScreenX11::disp,clip)==TScreenX11::mainWin) + ret=1; + else + TVOSClipboard::error=x11clipAnother; + SEMAPHORE_OFF; + // The rest is done by TScreenX11 + return ret; +} + +/**[txh]******************************************************************** + + Description: + Returns a newly allocated buffer containing the contents of the indicated +clipboard. @x{copy}.@* + The buffer should be deallocated with delete[]. The string is NULL +terminated because we ensure it.@* + The returned length doesn't include the EOL. + + Return: NULL if error, a new buffer if ok. + +***************************************************************************/ + +char *TVX11Clipboard::paste(int id, unsigned &lenRet) +{ + if (id>1) return NULL; + SEMAPHORE_ON; + Atom clip=id==0 ? XA_CLIPBOARD(TScreenX11::disp) : XA_PRIMARY; + + Window owner; + int format, result; + unsigned long len, bytes, dummy; + unsigned char *data; + + owner=XGetSelectionOwner(TScreenX11::disp,clip); + if (owner==None) + { + TVOSClipboard::error=x11clipNoSelection; + SEMAPHORE_OFF; + return NULL; + } + // What a hell should I use as property here? I use XA_STRING because it was + // used by the example. BTW the example failed with Eterm. + XConvertSelection(TScreenX11::disp,clip,XA_STRING,XA_STRING,TScreenX11::mainWin, + CurrentTime); + XFlush(TScreenX11::disp); + SEMAPHORE_OFF; + waiting=1; + while (waiting) + if (!IS_SECOND_THREAD_ON) + TScreenX11::ProcessGenericEvents(); + + if (property!=XA_STRING) + { + TVOSClipboard::error=x11clipWrongType; + return NULL; + } + // Check the size + SEMAPHORE_ON; + Atom type; + XGetWindowProperty(TScreenX11::disp,TScreenX11::mainWin,XA_STRING,0,0,0, + AnyPropertyType,&type,&format,&len,&bytes,&data); + if (bytes<=0) + { + TVOSClipboard::error=x11clipNoData; + SEMAPHORE_OFF; + return NULL; + } + result=XGetWindowProperty(TScreenX11::disp,TScreenX11::mainWin,XA_STRING, + 0,bytes,0,AnyPropertyType,&type,&format,&len, + &dummy,&data); + if (result!=Success) + { + XFree(data); + TVOSClipboard::error=x11clipX11Error; + SEMAPHORE_OFF; + return NULL; + } + char *ret=new char[bytes+1]; + memcpy(ret,data,bytes); + ret[bytes]=0; + XFree(data); + lenRet=bytes; + SEMAPHORE_OFF; + //printf("Recibiendo: `%s' %ld\n",ret,bytes); + + return ret; +} + +void TVX11Clipboard::destroy() +{ + if (buffer) + { + delete[] buffer; + buffer=0; + } +} + +/***************************************************************************** + Fonts routines +*****************************************************************************/ + +int TScreenX11::GetFontGeometry(unsigned &w, unsigned &h) +{ + w=fontW; + h=fontH; + return 1; +} + +int TScreenX11::GetFontGeometryRange(unsigned &wmin, unsigned &hmin, + unsigned &wmax, unsigned &hmax) +{ + wmin=foWmin; + hmin=foHmin; + wmax=foWmax; + hmax=foHmax; + return 1; +} + +int TScreenX11::SetFont(int changeP, TScreenFont256 *fontP, + int changeS, TScreenFont256 *fontS, + int fontCP, int appCP) +{ + if (!changeP && !changeS) return 1; + // Check for restore fonts + if (changeP && !fontP && ((!changeS && !useSecondaryFont) || (changeS && !fontS))) + fontP=defaultFont; + + // Solve the sizes + unsigned wP, hP, wS, hS; + if (changeP) + { + if (fontP) + { + wP=fontP->w; + hP=fontP->h; + } + else + { + wP=defaultFont->w; + hP=defaultFont->h; + } + } + else + { + wP=fontW; + hP=fontH; + } + if (changeS) + { + if (fontS) + { + wS=fontS->w; + hS=fontS->h; + } + else + {// Disabled + wS=wP; + hS=hP; + } + } + else + { + if (useSecondaryFont) + { + wS=fontW; + hS=fontH; + } + else + {// Disabled + wS=wP; + hS=hP; + } + } + if (wP!=wS || hP!=hS) return 0; + // Check if the size is in the range + if (wPfoWmax || hPfoHmax) + return 0; + + // Change the requested fonts + SEMAPHORE_ON; + if (changeP) + { + DestroyXImageFont(0); + if (fontP && fontP->data) + { + CreateXImageFont(0,fontP->data,wP,hP); + primaryFontChanged=1; + } + else + { + CreateXImageFont(0,defaultFont->data,wP,hP); + primaryFontChanged=0; + } + } + if (changeS) + { + DestroyXImageFont(1); + if (fontS) + CreateXImageFont(1,fontS->data,wP,hP); + } + // Change the code page + if (changeP && fontCP!=-1) + { + if (appCP==-1) + TVCodePage::SetScreenCodePage(fontCP); + else + TVCodePage::SetCodePage(appCP,fontCP,-1); + } + // Verify if we need to resize + if (wP!=fontW || hP!=fontH) + { + DoResize(wP,hP); + } + else + { + FullRedraw(); + } + SEMAPHORE_OFF; + return 1; +} + +void TScreenX11::RestoreFonts() +{ + SetFont(1,NULL,1,NULL,TVCodePage::ISOLatin1Linux,TVCodePage::ISOLatin1Linux); +} + +void TScreenX11::DoResize(unsigned w, unsigned h) +{ + SEMAPHORE_ON; + UnDrawCursor(); + if (w!=fontW || h!=fontH) + { + unsigned start=100*cShapeFrom/fontH; + unsigned end =100*cShapeTo/fontH; + fontW=w; + fontWb=(w+7)/8; + fontH=h; + fontSz=fontWb*h; + AdjustCursorImage(); + /* Change the cursor shape */ + SetCursorShape(start,end); + /* Inform the WM about this change*/ + sizeHints->width_inc =fontW; + sizeHints->height_inc=fontH; + sizeHints->min_width =fontW*40; + sizeHints->min_height=fontH*20; + XSetWMNormalHints(disp,mainWin,sizeHints); + } + /* Change the size */ + XResizeWindow(disp,mainWin,maxX*fontW,maxY*fontH); + /* Compute cursor position and draw it */ + SetCursorPos(cursorX,cursorY); + DrawCursor(); + SEMAPHORE_OFF; +} + +TScreenFont256 *TScreenX11::ChooseClosestFont(unsigned fW, unsigned fH) +{ + TScreenFont256 *nFont=NULL; + + if (fW==8 || fH==16) + nFont=&font8x16; + else if (fW==10 || fH==20) + nFont=&font10x20; + else + { + unsigned target=fW*fH; + int dif1=abs(8*16-target); + int dif2=abs(10*20-target); + if (dif1w; + nH=nFont->h; + if ((nW!=fontW || nH!=fontH) && useSecondaryFont) + { + if (frCB && (nsFont=frCB(1,nW,nH))) + releaseSFont=1; + } + } + + SEMAPHORE_ON; + if (nFont) + { + DestroyXImageFont(0); + CreateXImageFont(0,nFont->data,nW,nH); + if (resetFont) + primaryFontChanged=0; + if (releaseFont) + { + DeleteArray(nFont->data); + delete nFont; + } + } + if (useSecondaryFont) + { + DestroyXImageFont(1); + if (nsFont) + CreateXImageFont(1,nsFont->data,nW,nH); + } + // Should I check the size? + maxX=w; maxY=h; + + delete[] screenBuffer; + screenBuffer=new ushort[maxX*maxY]; + memset(screenBuffer,0,maxX*maxY*sizeof(ushort)); + + DoResize(nW,nH); + SEMAPHORE_OFF; + + return (nW==(unsigned)fW && nH==(unsigned)fH) ? 1 : 2; +} + +/* Busy indicator by Roman Valyushenko */ + +/* These are the bitmaps I created. They show a pointer with watch near. + Could be used to indicate some background computations. */ + +const int busyCursorWidth=28; +const int busyCursorHeight=20; + +Cursor TScreenX11::busyCursor, + TScreenX11::leftPtr; +char TScreenX11::busyCursorMap[]= +{ + 0xff, 0xff, 0xff, 0x1f, + 0xfd, 0xff, 0xff, 0x1f, + 0xf9, 0xff, 0xff, 0x1f, + 0xf1, 0xff, 0xff, 0x1f, + 0xe1, 0x7f, 0xc0, 0x1f, + 0xc1, 0x7f, 0xc0, 0x1f, + 0x81, 0x3f, 0x80, 0x1f, + 0x01, 0x9f, 0x3b, 0x1f, + 0x01, 0xce, 0x7b, 0x1e, + 0xc1, 0xef, 0xfb, 0x1e, + 0xc9, 0xef, 0xf1, 0x18, + 0x9d, 0xef, 0xf1, 0x18, + 0x9f, 0xef, 0xfe, 0x18, + 0x3f, 0x6f, 0xff, 0x1e, + 0x3f, 0xcf, 0x7f, 0x1e, + 0xff, 0x9f, 0x3f, 0x1f, + 0xff, 0x3f, 0x80, 0x1f, + 0xff, 0x7f, 0xc0, 0x1f, + 0xff, 0x7f, 0xc0, 0x1f, + 0xff, 0xff, 0xff, 0x1f +}; +char TScreenX11::busyCursorMask[]= +{ + 0xfc, 0xff, 0xff, 0x1f, + 0xf8, 0xff, 0xff, 0x1f, + 0xf0, 0xff, 0xff, 0x1f, + 0xe0, 0x3f, 0x80, 0x1f, + 0xc0, 0x3f, 0x80, 0x1f, + 0x80, 0x3f, 0x80, 0x1f, + 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x0e, 0x00, 0x1e, + 0x00, 0x04, 0x00, 0x1c, + 0x00, 0x04, 0x00, 0x10, + 0x80, 0x07, 0x00, 0x10, + 0x08, 0x07, 0x00, 0x10, + 0x0c, 0x07, 0x00, 0x10, + 0x1f, 0x06, 0x00, 0x10, + 0x1f, 0x06, 0x00, 0x1c, + 0x3f, 0x0f, 0x00, 0x1e, + 0xff, 0x1f, 0x00, 0x1f, + 0xff, 0x3f, 0x80, 0x1f, + 0xff, 0x3f, 0x80, 0x1f, + 0xff, 0x3f, 0x80, 0x1f +}; + +/* This is the function which creates cursors. On success it return + true, otherwise false */ +Boolean TScreenX11::createCursors() +{ + long useInternal=0; + optSearch("InternalBusyCursor",useInternal); + + if (useInternal) + { + Pixmap busyCursorPixmap, busyCursorPixmapMask; + + busyCursorPixmap=XCreatePixmapFromBitmapData(disp,mainWin,(char*)&busyCursorMap, + busyCursorWidth,busyCursorHeight, + BlackPixel(disp,screen), + WhitePixel(disp,screen),1); + if (busyCursorPixmap==None) + return False; + + busyCursorPixmapMask=XCreatePixmapFromBitmapData(disp,mainWin,(char*)&busyCursorMask, + busyCursorWidth,busyCursorHeight, + BlackPixel(disp,screen), + WhitePixel(disp,screen),1); + int ok=0; + if (busyCursorPixmapMask!=None) + { + XColor busyCursorFg, busyCursorBg; + Status status; + + status=XAllocNamedColor(disp,DefaultColormap(disp,DefaultScreen(disp)), + "black",&busyCursorFg,&busyCursorFg); + if (status) + { + status=XAllocNamedColor(disp,DefaultColormap(disp,DefaultScreen(disp)), + "white",&busyCursorBg,&busyCursorBg); + if (status) + { + busyCursor=XCreatePixmapCursor(disp,busyCursorPixmap,busyCursorPixmapMask, + &busyCursorFg,&busyCursorBg,1,1); + ok=1; + } + } + XFreePixmap(disp,busyCursorPixmapMask); + } + XFreePixmap(disp,busyCursorPixmap); + + if (!ok) + return False; + } + else + busyCursor=XCreateFontCursor(disp,XC_watch); + + leftPtr=XCreateFontCursor(disp,XC_left_ptr); + return True; /* Success */ +} + +/* This is the function to change the cursor. */ +Boolean TScreenX11::ShowBusyState(Boolean busyState) +{ + SEMAPHORE_ON; + if (busyState) + XDefineCursor(disp,mainWin,busyCursor); + else + XDefineCursor(disp,mainWin,leftPtr); + XFlush(disp); /* Show it right now */ + SEMAPHORE_OFF; + return defaultShowBusyState(busyState); +} + +void TScreenX11::Beep() +{ + SEMAPHORE_ON; + XBell(disp,50); + SEMAPHORE_OFF; +} + +/***************************************************************************** + Application Helpers +*****************************************************************************/ + +const char *TScreenX11::appHelperNameError[]= +{ + __("No error"), // 0 + __("Only one helper of this kind can be opened at the same time"), // 1 + __("Please install gqview application in order to display images"), // 2 + __("Please install xpdf application in order to display PDF files"), // 3 + __("Invalid application helper handler"), // 4 + __("Failed to open /dev/null"), // 5 + __("No more handlers") // 6 +}; +int TScreenX11::appHelperError=0; +TNSCollection *TScreenX11::appHelperHandlers=NULL; +struct helperHandler +{ + TScreen::AppHelper kind; + pid_t pid; +}; +static int allocatedHandlers; + +static +Boolean CheckInstalled(const char *command, const char *response, + Boolean installed) +{ + if (installed) + return installed; + // Redirect stderr and stdout to a file + char name[14]="/tmp/tvXXXXXX"; + int handler=mkstemp(name); + if (handler==-1) + return False; + unlink(name); + int h_errbak=dup(STDERR_FILENO); + int h_outbak=dup(STDOUT_FILENO); + dup2(handler,STDERR_FILENO); + dup2(handler,STDOUT_FILENO); + // Run the command + TScreen::System(command); + // Restore stderr and stdout + dup2(h_errbak,STDERR_FILENO); + dup2(h_outbak,STDOUT_FILENO); + close(h_errbak); + close(h_outbak); + // Read the result + lseek(handler,0,SEEK_SET); + char resp[80]; + read(handler,resp,80); + close(handler); + // Is that ok? + return Boolean(strstr(resp,response)!=NULL); +} + +TScreen::appHelperHandler TScreenX11::OpenHelperApp(TScreen::AppHelper kind) +{ + static Boolean gqviewInstalled=False; + static Boolean xpdfInstalled=False; + + if (kind==FreeHandler) + { + appHelperError=4; + return -1; + } + + if (kind==ImageViewer && appHelperHandlers) + {// Only one image viewer (gqview limitation) + ccIndex i, c=appHelperHandlers->getCount(); + for (i=0; iat(i); + if (p->kind==ImageViewer) + { + appHelperError=1; + return -1; + } + } + } + + // Ensure we have a collection + if (!appHelperHandlers) + { + appHelperHandlers=new TNSCollection(maxAppHelperHandlers,2); + allocatedHandlers=maxAppHelperHandlers; + } + if (!appHelperHandlers) + return -1; + + // Do we have available handlers? + ccIndex hNum=-1; + if (appHelperHandlers->getCount()>=allocatedHandlers) + { + ccIndex i, c=appHelperHandlers->getCount(); + for (i=0; iat(i); + if (p->kind==FreeHandler) + { + hNum=i; + break; + } + } + if (i==c) + { + appHelperError=6; + return -1; + } + } + + // Create/Recycle the structure + helperHandler *h; + + if (hNum==-1) + {// Create a struct for it + h=(helperHandler *)(new char[sizeof(helperHandler)]); // To match the delete[] + h->kind=FreeHandler; + // Insert it + hNum=appHelperHandlers->insert(h); + } + else + // Recycle + h=(helperHandler *)appHelperHandlers->at(hNum); + + // Open the remote server + int nullH=open("/dev/null",O_WRONLY|O_BINARY|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE); + if (nullH==-1) + { + appHelperError=5; + return -1; + } + switch (kind) + { + case ImageViewer: + gqviewInstalled=CheckInstalled("gqview -v","GQview",gqviewInstalled); + if (!gqviewInstalled) + { + appHelperError=2; + return -1; + } + break; + case PDFViewer: + xpdfInstalled=CheckInstalled("xpdf -v","xpdf version",xpdfInstalled); + if (!xpdfInstalled) + { + appHelperError=3; + return -1; + } + break; + case FreeHandler: + break; + } + close(nullH); + h->kind=kind; + h->pid=0; + + return hNum; +} + +Boolean TScreenX11::CloseHelperApp(appHelperHandler id) +{ + if (!appHelperHandlers || id<0 || id>=appHelperHandlers->getCount()) + { + appHelperError=4; + return False; + } + + char buf[80]; + int nullH=open("/dev/null",O_WRONLY|O_BINARY|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE); + if (nullH==-1) + { + appHelperError=5; + return -1; + } + + helperHandler *p=(helperHandler *)appHelperHandlers->at(id); + int status; + if (p->pid && waitpid(p->pid,&status,WNOHANG)==p->pid) + p->pid=0; + switch (p->kind) + { + case ImageViewer: + System("gqview -r -q",&p->pid,-1,nullH,nullH); + break; + case PDFViewer: + CLY_snprintf(buf,80,"xpdf -remote SETEdit_%d_%d -quit",(int)getpid(),id); + System(buf,&p->pid,-1,nullH,nullH); + break; + case FreeHandler: + appHelperError=4; + return False; + } + + close(nullH); + p->kind=FreeHandler; + p->pid=0; + + return True; +} + +Boolean TScreenX11::SendFileToHelper(appHelperHandler id, const char *file, + void *extra) +{ + if (!appHelperHandlers || id<0 || id>=appHelperHandlers->getCount()) + { + appHelperError=4; + return False; + } + + int len=160+strlen(file); + int page; + AllocLocalStr(buf,len); + int nullH=open("/dev/null",O_WRONLY|O_BINARY|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE); + if (nullH==-1) + { + appHelperError=5; + return -1; + } + + helperHandler *p=(helperHandler *)appHelperHandlers->at(id); + int status; + if (p->pid && waitpid(p->pid,&status,WNOHANG)==p->pid) + p->pid=0; + switch (p->kind) + { + case ImageViewer: + CLY_snprintf(buf,len,"gqview -r \"file:%s\"",file); + System(buf,&p->pid,-1,nullH,nullH); + break; + case PDFViewer: + page=0; + if (extra) + page=*((int *)extra); + CLY_snprintf(buf,len,"xpdf -remote SETEdit_%d_%d -raise \"%s\" %d", + (int)getpid(),id,file,page); + System(buf,&p->pid,-1,nullH,nullH); + break; + case FreeHandler: + appHelperError=4; + return False; + } + + close(nullH); + + return True; +} + +const char *TScreenX11::GetHelperAppError() +{ + return appHelperNameError[appHelperError]; +} + + +/***************************************************************************** + + Update thread stuff: + + Problem: In X11 (and most GUI systems) the contents of the window aren't + stored/cached. So when a window is not visible (exposed is the X11 term) its + contents aren't stored anywhere. When the window (or a portion) becomes + exposed X11 sends an expose event. If the application isn't collecting + expose events, because is blocked waiting for a child completion or + performing a long computation, the exposed portion of the window is filled + with a black rectangle (this color is selected during TScreenX11 creation). + This is very bad for applications like RHIDE where the debugger is blocked + until the debuggee is stoped. It means that you most probably won't be able + to see RHIDE's window content while the debuggee is running. Even when it + isn't critical is ugly. + The idea is to periodically collect the expose events even when the process + is blocked. + I (SET) implemented it using two different approaches: + + 1) POSIX threads. They seems to be poorly implemented in Linux (i.e. glibc + 2.2.5 and 2.3.1). This solution is elegant but unstable, at least for + SETEdit and RHIDE running in Debian GNU/Linux Woody and Sarge. + 2) setitimer and SIGALRM. This is really simple and seems to be more stable. + + I keep both so people can experiment with both, each approachs have its + advantes and disadvantages. + +*****************************************************************************/ + +#if USE_ALARM_FOR_THREAD + +/***************************************************************************** + + Update thread using the setitimer approach. + + This approach uses the timer alarm (SIGALRM for Linux and SIGPROF for +Solaris, looks like Solaris didn't implement it properly). + This mechanism is much more reliable than the POSIX thread mechanism, at +least for Linux. + The use of a signal ensures: + +1) The main "thread" can't take the CPU while the signal is executing. And as +the signal blocks itself by default it doesn't have to be reentrant. +2) A child process doesn't inherits the timers so there is no risk to +inherit problems. + +Advantages: +1) The mutex implementation is trivial. +2) We don't need pthread library. + +Disadvantages: +1) The program can't use this alarm for itself. +2) Implementations of the alarm mechanism should be POSIX compliant. + +*****************************************************************************/ + +// Used to print a mark every 250 updates +#define TIC 0 +// Prints some debug info when the mechanism is dis/enabled +#define DBG_ALM_STATE 0 + +int TVX11UpdateThread::running=0; +int TVX11UpdateThread::initialized=0; +const int refreshTime=10000; // 10 ms +static sig_atomic_t mutex; +static int updates=0; +static volatile int safeToUnHook; + +void TVX11UpdateThread::UpdateThread(int signum) +{ + if (!running) + { + safeToUnHook=1; + return; + } + // Here TIMER_ALARM signal is blocked and the process can take the CPU + if (!mutex) + {// No mutex, we can do our work. + TScreenX11::ProcessGenericEvents(); + } + if (TIC) + { + updates++; + if (updates>250) + { + printf("Tic (%d)\n",getpid()); + updates=0; + } + } + microAlarm(refreshTime); +} + +void TVX11UpdateThread::StartUpdateThread() +{ + long aux; + if (TScreen::optSearch("UseUpdateThread",aux) && aux==1) + { + if (DBG_ALM_STATE) + printf("Using setitimer for the update stuff (PID=%d)\n",getpid()); + mutex=0; + initialized=1; + running=1; + safeToUnHook=0; + // Trap the alarm signal + struct sigaction s; + s.sa_handler=UpdateThread; + sigemptyset(&s.sa_mask); + #if defined(SA_RESTART) + s.sa_flags=SA_RESTART; + #else + s.sa_flags=0; + #endif // SA_RESTART + sigaction(TIMER_ALARM,&s,NULL); + // Set the alarm + microAlarm(refreshTime); + } +} + +void TVX11UpdateThread::microAlarm(unsigned int usec) +{ + struct itimerval newV; + newV.it_interval.tv_usec=0; + newV.it_interval.tv_sec=0; + newV.it_value.tv_usec=(long int)usec; + newV.it_value.tv_sec=0; + setitimer(ITIMER_USED,&newV,0); +} + +void TVX11UpdateThread::SemaphoreOn() +{ + mutex++; + // We will never collide with the signal because the signal is atomic from + // our point of view. +} + +void TVX11UpdateThread::SemaphoreOff() +{ + --mutex; + if (mutex<0) + printf("Oh no!!! mutex<0\n"); +} + +int TVX11UpdateThread::CheckSecondThread() +{ + return (initialized && running); +} + +void TVX11UpdateThread::StopUpdateThread() +{ + if (IS_SECOND_THREAD_ON) + { + if (DBG_ALM_STATE) + printf("Stopping update thread for PID=%d\n",getpid()); + running=0; + while (!safeToUnHook); + // Un-Trap the alarm signal + struct sigaction s; + s.sa_handler=SIG_IGN; + sigemptyset(&s.sa_mask); + #if defined(SA_RESTART) + s.sa_flags=SA_RESTART; + #else + s.sa_flags=0; + #endif // SA_RESTART + sigaction(TIMER_ALARM,&s,NULL); + } +} +#elif HAVE_LINUX_PTHREAD +/************************************************************************** + + Update thread stuff + + This code is under test and for this reason must be enabled manually + defining the UseUpdateThread configuration variable. + + Some important details: [glibc 2.2.5 also 2.3.1] + + * Linux threads are implemented using processes (clone kernel syscall). + I think that they will never be really POSIX compliant if this mechanism + is used. One major flaw is that getpid() will return a different value + for each thread exposing the fake implementation. + + * Looks like exec can't be reliably called from a multithread program. It + works perfectly for small and medium examples but does all kind of nasty + things when called from big programs like SETEdit. Looking at the glibc + code you can see system() implementation knows it and checks if we have + "threads", in this case it first disables all async events. This is done + with a macro and I couldn't find any function in glibc to do the same + from my code. + + * According to POSIX when you do a fork the new process inherits all the + threads and calling exec terminates all threads. In this way fork/exec + work ok. In Linux implementation it doesn't happend. According to glibc + docs: + `pthread_kill_other_threads_np' is a non-portable LinuxThreads + extension. It causes all threads in the program to terminate + immediately, except the calling thread which proceeds normally. It + is intended to be called just before a thread calls one of the + `exec' functions, e.g. `execve'. + ... + According to POSIX 1003.1c, a successful `exec*' in one of the + threads should automatically terminate all other threads in the + program. This behavior is not yet implemented in LinuxThreads. + Calling `pthread_kill_other_threads_np' before `exec*' achieves + much of the same behavior, except that if `exec*' ultimately + fails, then all other threads are already killed. + But as threads aren't inherited you kill nothing or the parent threads :-( + If you call it and then try to create a new thread it is created but + your process dies with "Signal Real-time 0". + + * The first time you create a "thread" an auxiliar process is created. + Looks like this process is the one in charge to coordinate the other + processes that emulates threads. This should be transparent, but it + isn't. If you fork/create a process group/system and then you kill the + group then it kills your threads and the auxiliar process becomes a + Zombie. Calling exec from big programs looks like you have chances to + get a thread switch and then the exec tries to attach to the "thread" + process. This confusion kills the thread, lets the child sleeping and + the auxiliar process becomes a Zombie. + + I figure out that implementing POSIX threads is a complex task and that + I could be doing wrong things, but is also obvious that LinuxThreads as + implemented by glibc 2.2.5 is a nightmare. + +**************************************************************************/ + +// Linux implementation of POSIX threads + +// Here to avoid pulling the headers everywhere +static pthread_t th; +static pthread_mutex_t mutex; +int TVX11UpdateThread::running=0; +int TVX11UpdateThread::initialized=0; +timeval TVX11UpdateThread::refWatchDog, + TVX11UpdateThread::nowWatchDog; +int TVX11UpdateThread::watchDogVal=1; + +void *TVX11UpdateThread::UpdateThread(void *) +{ + // I tried it in the hope that could help to kill childs without affecting + // this thread, but isn't enough. + if (0) + { + sigset_t newMask; + sigemptyset(&newMask); + sigaddset(&newMask,SIGTERM); + pthread_sigmask(SIG_BLOCK,&newMask,NULL); + } + + running=1; + + while (running) + { + usleep(10); + watchDogVal=0; + TScreenX11::ProcessGenericEvents(); + } + return NULL; +} + +void TVX11UpdateThread::SemaphoreOn() +{ + if (initialized) + pthread_mutex_lock(&mutex); +} + +void TVX11UpdateThread::SemaphoreOff() +{ + if (initialized) + pthread_mutex_unlock(&mutex); +} + +int TVX11UpdateThread::CheckSecondThread() +{ + if (!initialized || !running) + return 0; + + gettimeofday(&nowWatchDog,0); + timeval aux=nowWatchDog; + SubstractRef(nowWatchDog,refWatchDog); + if (nowWatchDog.tv_sec>=1) + { + if (watchDogVal) + { + printf("Oops! looks like the update thread is dead\n"); + running=0; + return 0; + } + watchDogVal=1; + refWatchDog=aux; + } + return 1; +} + +void TVX11UpdateThread::StartUpdateThread() +{ + long aux; + if (TScreen::optSearch("UseUpdateThread",aux) && aux==1) + { + // This initialization needs Unix 98 compliance. + // Linux is ok and the Solaris 7 manpages says that's also ok. + pthread_mutexattr_t mt_attr; + pthread_mutexattr_init(&mt_attr); + pthread_mutexattr_settype(&mt_attr,PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&mutex,&mt_attr); + // Now we can use the mutex + initialized=1; + + gettimeofday(&refWatchDog,0); + if (pthread_create(&th,NULL,UpdateThread,NULL)==0) + printf("Update thread succesfuly created\n"); + else + perror("Error creating update thread"); + } +} + +void TVX11UpdateThread::StopUpdateThread() +{ + if (IS_SECOND_THREAD_ON) + { + void *ret; + running=0; + printf("Waiting for update thread completion\n"); + if (pthread_join(th,&ret)==0) + printf("Update thread finished OK\n"); + else + perror("Error waiting for update thread completion"); + } +} +#endif +// End of Linux implementation of POSIX threads + + +#else + +#include +#include +#include + +#endif // defined(TVOS_UNIX) && defined(HAVE_X11) + diff --git a/tvision/compat/beep.c b/tvision/compat/beep.c new file mode 100644 index 0000000..206b18f --- /dev/null +++ b/tvision/compat/beep.c @@ -0,0 +1,11 @@ +/* + Copyright (C) 2000 Salvador E. Tropea + Copyright (C) 2000 Anatoli Soltan + Covered by the GPL license. +*/ + +#ifndef BEEP_DEFINED +void CLY_Beep(void) +{ +} +#endif diff --git a/tvision/compat/compat.gpr b/tvision/compat/compat.gpr new file mode 100644 index 0000000..d15254a Binary files /dev/null and b/tvision/compat/compat.gpr differ diff --git a/tvision/compat/compat.imk b/tvision/compat/compat.imk new file mode 100644 index 0000000..9e9e989 --- /dev/null +++ b/tvision/compat/compat.imk @@ -0,0 +1,226 @@ +#!/usr/bin/make +# Automatically generated from RHIDE projects, don't edit +# + +../makes/obj/beep$(ExOBJ):: ../compat/beep.c \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/drivevalid$(ExOBJ):: ../compat/drivevalid.c \ + cl/needs.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/expandpath$(ExOBJ):: ../compat/expandpath.c \ + compatlayer.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/fexpand$(ExOBJ):: ../compat/fexpand.c \ + cl/needs.h \ + compatlayer.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/fileattrs$(ExOBJ):: ../compat/fileattrs.c \ + compatlayer.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/fileexists$(ExOBJ):: ../compat/fileexists.c \ + cl/unistd.h \ + compatlayer.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/filelength$(ExOBJ):: ../compat/filelength.c \ + cl/needs.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/fixpath$(ExOBJ):: ../compat/fixpath.c \ + cl/needs.h \ + cl/unistd.h \ + compatlayer.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/fnmatch$(ExOBJ):: ../compat/fnmatch.c \ + cl/needs.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/getcurdir$(ExOBJ):: ../compat/getcurdir.c \ + cl/needs.h \ + cl/unistd.h \ + compatlayer.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/getline$(ExOBJ):: ../compat/getline.c \ + cl/needs.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/getopt$(ExOBJ):: ../compat/getopt.c \ + cl/needs.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/getopt1$(ExOBJ):: ../compat/getopt1.c \ + cl/needs.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/getshell$(ExOBJ):: ../compat/getshell.c \ + compatlayer.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/glob$(ExOBJ):: ../compat/glob.c \ + cl/needs.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/globfree$(ExOBJ):: ../compat/globfree.c \ + cl/needs.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/iffilelen$(ExOBJ):: ../compat/iffilelen.cc \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_CC) + +../makes/obj/isdir$(ExOBJ):: ../compat/isdir.c \ + compatlayer.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/isrelpath$(ExOBJ):: ../compat/isrelpath.c \ + compatlayer.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/iswild$(ExOBJ):: ../compat/iswild.c \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/itoa$(ExOBJ):: ../compat/itoa.c \ + cl/needs.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/mkstemp$(ExOBJ):: ../compat/mkstemp.c \ + cl/needs.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/nl_langinfo$(ExOBJ):: ../compat/nl_langinfo.c \ + cl/needs.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/ntdirent$(ExOBJ):: ../compat/ntdirent.c \ + cl/needs.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/pathvalid$(ExOBJ):: ../compat/pathvalid.c \ + compatlayer.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/regex$(ExOBJ):: ../compat/regex.c \ + cl/needs.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/releasec$(ExOBJ):: ../compat/releasec.c \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/snprintf$(ExOBJ):: ../compat/snprintf.c \ + cl/needs.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/ssc_streams$(ExOBJ):: ../compat/ssc_streams.cc \ + cl/unistd.h \ + compatlayer.h \ + tv/configtv.h \ + tv/ssc_streams.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_CC) + +../makes/obj/strlwr$(ExOBJ):: ../compat/strlwr.c \ + cl/needs.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/strupr$(ExOBJ):: ../compat/strupr.c \ + cl/needs.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/ticks$(ExOBJ):: ../compat/ticks.c \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/unc$(ExOBJ):: ../compat/unc.c \ + cl/needs.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/unc_95$(ExOBJ):: ../compat/unc_95.c \ + cl/needs.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/unc_nt$(ExOBJ):: ../compat/unc_nt.c \ + cl/needs.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/validfilename$(ExOBJ):: ../compat/validfilename.c \ + compatlayer.h \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + +../makes/obj/yieldpro$(ExOBJ):: ../compat/yieldpro.c \ + tv/configtv.h \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_C) + diff --git a/tvision/compat/compat.umk b/tvision/compat/compat.umk new file mode 100644 index 0000000..2feedc3 --- /dev/null +++ b/tvision/compat/compat.umk @@ -0,0 +1,115 @@ +#!/usr/bin/make +# Automatically generated from RHIDE projects, don't edit +# + +../makes/obj/beep$(ExOBJ):: ../compat/beep.c + $(RHIDE_COMPILE_C) + +../makes/obj/drivevalid$(ExOBJ):: ../compat/drivevalid.c + $(RHIDE_COMPILE_C) + +../makes/obj/expandpath$(ExOBJ):: ../compat/expandpath.c + $(RHIDE_COMPILE_C) + +../makes/obj/fexpand$(ExOBJ):: ../compat/fexpand.c + $(RHIDE_COMPILE_C) + +../makes/obj/fileattrs$(ExOBJ):: ../compat/fileattrs.c + $(RHIDE_COMPILE_C) + +../makes/obj/fileexists$(ExOBJ):: ../compat/fileexists.c + $(RHIDE_COMPILE_C) + +../makes/obj/filelength$(ExOBJ):: ../compat/filelength.c + $(RHIDE_COMPILE_C) + +../makes/obj/fixpath$(ExOBJ):: ../compat/fixpath.c + $(RHIDE_COMPILE_C) + +../makes/obj/fnmatch$(ExOBJ):: ../compat/fnmatch.c + $(RHIDE_COMPILE_C) + +../makes/obj/getcurdir$(ExOBJ):: ../compat/getcurdir.c + $(RHIDE_COMPILE_C) + +../makes/obj/getline$(ExOBJ):: ../compat/getline.c + $(RHIDE_COMPILE_C) + +../makes/obj/getopt$(ExOBJ):: ../compat/getopt.c + $(RHIDE_COMPILE_C) + +../makes/obj/getopt1$(ExOBJ):: ../compat/getopt1.c + $(RHIDE_COMPILE_C) + +../makes/obj/getshell$(ExOBJ):: ../compat/getshell.c + $(RHIDE_COMPILE_C) + +../makes/obj/glob$(ExOBJ):: ../compat/glob.c + $(RHIDE_COMPILE_C) + +../makes/obj/globfree$(ExOBJ):: ../compat/globfree.c + $(RHIDE_COMPILE_C) + +../makes/obj/iffilelen$(ExOBJ):: ../compat/iffilelen.cc + $(RHIDE_COMPILE_CC) + +../makes/obj/isdir$(ExOBJ):: ../compat/isdir.c + $(RHIDE_COMPILE_C) + +../makes/obj/isrelpath$(ExOBJ):: ../compat/isrelpath.c + $(RHIDE_COMPILE_C) + +../makes/obj/iswild$(ExOBJ):: ../compat/iswild.c + $(RHIDE_COMPILE_C) + +../makes/obj/itoa$(ExOBJ):: ../compat/itoa.c + $(RHIDE_COMPILE_C) + +../makes/obj/mkstemp$(ExOBJ):: ../compat/mkstemp.c + $(RHIDE_COMPILE_C) + +../makes/obj/nl_langinfo$(ExOBJ):: ../compat/nl_langinfo.c + $(RHIDE_COMPILE_C) + +../makes/obj/ntdirent$(ExOBJ):: ../compat/ntdirent.c + $(RHIDE_COMPILE_C) + +../makes/obj/pathvalid$(ExOBJ):: ../compat/pathvalid.c + $(RHIDE_COMPILE_C) + +../makes/obj/regex$(ExOBJ):: ../compat/regex.c + $(RHIDE_COMPILE_C) + +../makes/obj/releasec$(ExOBJ):: ../compat/releasec.c + $(RHIDE_COMPILE_C) + +../makes/obj/snprintf$(ExOBJ):: ../compat/snprintf.c + $(RHIDE_COMPILE_C) + +../makes/obj/ssc_streams$(ExOBJ):: ../compat/ssc_streams.cc + $(RHIDE_COMPILE_CC) + +../makes/obj/strlwr$(ExOBJ):: ../compat/strlwr.c + $(RHIDE_COMPILE_C) + +../makes/obj/strupr$(ExOBJ):: ../compat/strupr.c + $(RHIDE_COMPILE_C) + +../makes/obj/ticks$(ExOBJ):: ../compat/ticks.c + $(RHIDE_COMPILE_C) + +../makes/obj/unc$(ExOBJ):: ../compat/unc.c + $(RHIDE_COMPILE_C) + +../makes/obj/unc_95$(ExOBJ):: ../compat/unc_95.c + $(RHIDE_COMPILE_C) + +../makes/obj/unc_nt$(ExOBJ):: ../compat/unc_nt.c + $(RHIDE_COMPILE_C) + +../makes/obj/validfilename$(ExOBJ):: ../compat/validfilename.c + $(RHIDE_COMPILE_C) + +../makes/obj/yieldpro$(ExOBJ):: ../compat/yieldpro.c + $(RHIDE_COMPILE_C) + diff --git a/tvision/compat/drivevalid.c b/tvision/compat/drivevalid.c new file mode 100644 index 0000000..9d03b51 --- /dev/null +++ b/tvision/compat/drivevalid.c @@ -0,0 +1,44 @@ +/* + Copyright (C) 1996-1998 Robert H”hne + Copyright (C) 2000 Anatoli Soltan + Copyright (C) 2000 Salvador E. Tropea + Covered by the GPL license. +*/ + +#include + +#ifdef TVCompf_djgpp +#define Uses_ctype +#include +#include + +int CLY_DriveValid( char drive ) +{ + __dpmi_regs r; + r.x.ax = 0x1C00; + r.x.dx = uctoupper(drive) - 'A' + 1; + __dpmi_int(0x21,&r); + if (r.h.al != 0xFF) return 1; + return 0; +} +#endif + +#ifdef TVOS_UNIX +int CLY_DriveValid( char drive ) +{ + return 0; +} +#endif + +#ifdef TVOS_Win32 +#define WIN32_LEAN_AND_MEAN +#include +#define Uses_ctype +#include + +int CLY_DriveValid( char drive ) +{ + DWORD drives = GetLogicalDrives(); + return 1 & (drives >> (uctoupper(drive) - 'A')); +} +#endif diff --git a/tvision/compat/expandpath.c b/tvision/compat/expandpath.c new file mode 100644 index 0000000..89a1d70 --- /dev/null +++ b/tvision/compat/expandpath.c @@ -0,0 +1,41 @@ +/* + Copyright (C) 1996-1998 Robert H”hne + Copyright (C) 2000 Salvador E. Tropea + Covered by the GPL license. +*/ + +#define Uses_string +#include + +/**[txh]******************************************************************** + + Description: + Extracts from path the directory part and filename part. If 'dir' and/or +'file' == NULL, it is not filled. The directory will have a trailing slash. + +***************************************************************************/ + +void CLY_ExpandPath(const char *path, char *dir, char *file) +{ + const char *tag = strrchr(path, DIRSEPARATOR); + + if (tag != NULL) + { + if (file) + strcpy(file, tag + 1); + if (dir) + { + strncpy(dir, path, tag - path + 1); + dir[tag - path + 1] = '\0'; + } + } + else + { + /* there is only the file name */ + if (file) + strcpy(file, path); + if (dir) + dir[0] = '\0'; + } +} + diff --git a/tvision/compat/fexpand.c b/tvision/compat/fexpand.c new file mode 100644 index 0000000..65489ae --- /dev/null +++ b/tvision/compat/fexpand.c @@ -0,0 +1,114 @@ +/* + Copyright (C) 1996-1998 Robert H”hne + Copyright (C) 2000 Vadim Beloborodov + Copyright (C) 2000 Salvador E. Tropea + Covered by the GPL license. +*/ + +#include + +#if defined(TVCompf_djgpp) || defined(TVComp_BCPP) || defined(TVOS_UNIX) || \ + defined(TVCompf_Cygwin) +#define Uses_fixpath +#define Uses_string +#define Uses_limits +#include + +void CLY_fexpand( char *rpath ) +{ + char path[PATH_MAX]; + _fixpath(rpath,path); + strcpy(rpath,path); +} +#define FEXPAND_DEFINED +#endif + + +#if defined(TVOS_Win32) && !defined(FEXPAND_DEFINED) +// Code provided by Vadim Beloborodov +// This should be unified with the NT version and use _fixpath. + +#define Uses_string +#define Uses_limits +#define Uses_stdlib +#define Uses_ctype +#define Uses_direct +#include + +static void squeeze( char *path ) +{ + char * + dest = path; + char * + src = path; + while( *src != 0 ) { + if (*src == '.') + if (src[1] == '.') { + src += 2; + if (dest > path) { + dest--; + while ((*--dest != '\\')&&(dest > path)) // back up to the previous '\' + ; + dest++; // move to the next position + } + } else if (src[1] == '\\') + src++; + else + *dest++ = *src++; + else + *dest++ = *src++; + } + *dest = 0; // zero terminator + dest = path; + src = path; + while( *src != 0 ) { + if ((*src == '\\')&&(src[1] == '\\')) + src++; + else + *dest++ = *src++; + } + *dest = 0; // zero terminator +} + +void CLY_fexpand( char *rpath ) +{ + char path[PATH_MAX]=""; + char drive[PATH_MAX]=""; + char dir[PATH_MAX]=""; + char file[PATH_MAX]=""; + char ext[PATH_MAX]=""; + char *p; + + _splitpath( rpath, drive, dir, file, ext ); + if( *drive == 0 ) { + drive[0] = _getdrive() - 1 + 'A'; + drive[1] = ':'; + drive[2] = '\0'; + } + drive[0] = toupper(drive[0]); + if( (*dir == 0) || (dir[0] != '\\' && dir[0] != '/') ) { + char curdir[PATH_MAX]; + int len; + _getdcwd( drive[0] - 'A' + 1, curdir, PATH_MAX ); + len = strlen(curdir); + if (curdir[len - 1] != '\\') { + curdir[len] = '\\'; + curdir[len + 1] = 0; + } + strcat( curdir, dir ); + if( *curdir != '\\' && *curdir != '/' ) { + *dir = '\\'; + strcpy( dir+1, curdir ); + } else + strcpy( dir, curdir ); + } + + p = dir; + while( (p = strchr( p, '/' )) != 0 ) + *p = '\\'; + squeeze( dir ); + _makepath( path, drive, dir, file, ext ); + strcpy( rpath, path ); +} +#endif + diff --git a/tvision/compat/fileattrs.c b/tvision/compat/fileattrs.c new file mode 100644 index 0000000..2993a01 --- /dev/null +++ b/tvision/compat/fileattrs.c @@ -0,0 +1,197 @@ +/**[txh]******************************************************************** + + Description: + This module provides some functions to know the file attributes and altere +some of them in an abstract way. Note that I wrote only the functions I need +for SETEdit and not a full set. + + Copyright (C) 2000-2001 by Salvador E. Tropea + Covered by the GPL license. + +***************************************************************************/ + +#define Uses_CLYFileAttrs +#define Uses_alloca +#include + + +#ifdef TVCompf_djgpp +/* + In DOS owr best choice is _chmod, it can give information as file hidden + or system file. +*/ +#include + +void CLY_GetFileAttributes(CLY_mode_t *mode, struct stat *statVal, + const char *fileName) +{ + *mode=_chmod(fileName,0,0); +} + +int CLY_SetFileAttributes(CLY_mode_t *newmode, const char *fileName) +{ + return _chmod(fileName,1,*newmode)==-1 ? 0 : 1; +} + +void CLY_FileAttrReadOnly(CLY_mode_t *mode) +{ + *mode|=1; +} + +void CLY_FileAttrReadWrite(CLY_mode_t *mode) +{ + *mode&=0xFE; +} + +int CLY_FileAttrIsRO(CLY_mode_t *mode) +{ + return (*mode) & 1; +} + +void CLY_FileAttrModified(CLY_mode_t *mode) +{ + *mode|=0x20; +} + +void CLY_GetDefaultFileAttr(CLY_mode_t *mode) +{ + *mode=0x20; +} +#define FILE_ATTRS_DEFINED +#endif // TVCompf_djgpp + + + +#if (defined(TVOS_UNIX) || defined(TVCompf_Cygwin)) && \ + !defined(FILE_ATTRS_DEFINED) +/* + In UNIX the best way is just use chmod which is POSIX and should be +enough. +*/ +#include + +void CLY_GetFileAttributes(CLY_mode_t *mode, struct stat *statVal, + const char *fileName) +{ + int ngroups,val; + gid_t *groups; + uid_t user; + + mode->mode =statVal->st_mode; + mode->user =statVal->st_uid; + mode->group=statVal->st_gid; + + // Compute the write mask: + user=getuid(); + + // Is our file? (or we are the superuser) + if (user==0 || mode->user==user) + { + mode->writemask=S_IWUSR; + return; + } + + // Are we from their group? + ngroups=getgroups(0,NULL); + groups=(gid_t *)alloca(ngroups*sizeof(gid_t)); + val=getgroups(ngroups,groups); + if (val>=0) + { + int i; + for (i=0; igroup) + { + if (mode->mode & S_IWGRP) + mode->writemask=S_IWGRP; + else + mode->writemask=S_IWOTH; + return; + } + } + + // Ok, the `others' apply + mode->writemask=S_IWOTH; +} + +int CLY_SetFileAttributes(CLY_mode_t *newmode, const char *fileName) +{ + return !(chmod(fileName,newmode->mode) || + chown(fileName,newmode->user,newmode->group)); +} + +void CLY_FileAttrReadOnly(CLY_mode_t *mode) +{ + mode->mode&= ~mode->writemask; +} + +void CLY_FileAttrReadWrite(CLY_mode_t *mode) +{ + mode->mode|=mode->writemask; +} + +int CLY_FileAttrIsRO(CLY_mode_t *mode) +{ + return (mode->mode & mode->writemask)==0; +} + +void CLY_FileAttrModified(CLY_mode_t *mode) +{ +} + +void CLY_GetDefaultFileAttr(CLY_mode_t *mode) +{ // 644, umask will kill the denied ones if that's needed + mode->mode=S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR; + mode->user=getuid(); + mode->group=getgid(); + mode->writemask=S_IWUSR; +} +#define FILE_ATTRS_DEFINED +#endif + + + +#if defined(TVOS_Win32) && !defined(FILE_ATTRS_DEFINED) +/* + In Win32 systems there are an API call for it. +*/ +#define WIN32_LEAN_AND_MEAN +#include + +void CLY_GetFileAttributes(CLY_mode_t *mode, struct stat *statVal, + const char *fileName) +{ + *mode=statVal->st_mode; // Just to avoid unused warning + *mode=GetFileAttributes(fileName); +} + +int CLY_SetFileAttributes(CLY_mode_t *newmode, const char *fileName) +{ + return SetFileAttributes(fileName,*newmode); +} + +void CLY_FileAttrReadOnly(CLY_mode_t *mode) +{ + *mode|=FILE_ATTRIBUTE_READONLY; +} + +void CLY_FileAttrReadWrite(CLY_mode_t *mode) +{ + *mode&=~FILE_ATTRIBUTE_READONLY; +} + +int CLY_FileAttrIsRO(CLY_mode_t *mode) +{ + return (*mode & FILE_ATTRIBUTE_READONLY); +} + +void CLY_FileAttrModified(CLY_mode_t *mode) +{ + *mode|=FILE_ATTRIBUTE_ARCHIVE; +} + +void CLY_GetDefaultFileAttr(CLY_mode_t *mode) +{ + *mode=(CLY_mode_t)FILE_ATTRIBUTE_ARCHIVE; +} +#define FILE_ATTRS_DEFINED +#endif diff --git a/tvision/compat/fileexists.c b/tvision/compat/fileexists.c new file mode 100644 index 0000000..d57bb05 --- /dev/null +++ b/tvision/compat/fileexists.c @@ -0,0 +1,13 @@ +/* + Copyright (C) 1996-1998 Robert H”hne + Copyright (C) 2000-2001 Salvador E. Tropea + Covered by the GPL license. +*/ + +#define Uses_access +#include + +int CLY_FileExists(const char *fname) +{ + return (access(fname,R_OK)==0); +} diff --git a/tvision/compat/filelength.c b/tvision/compat/filelength.c new file mode 100644 index 0000000..8643b95 --- /dev/null +++ b/tvision/compat/filelength.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 1996-1998 Robert H”hne + Copyright (C) 2000 Salvador E. Tropea + Covered by the GPL license. +*/ +#include + +#ifdef NEEDS_FILELENGTH +#include + +long CLY_filelength(int fhandle) +{ + long oldval; + long retval; + + oldval=lseek(fhandle,0,SEEK_CUR); + if (oldval==-1L) return -1L; + retval=lseek(fhandle,0,SEEK_END); + if (retval==-1L) return -1L; + if (lseek(fhandle,oldval,SEEK_SET)==-1L) return -1L; + return retval; +} +#endif diff --git a/tvision/compat/fixpath.c b/tvision/compat/fixpath.c new file mode 100644 index 0000000..f121fc9 --- /dev/null +++ b/tvision/compat/fixpath.c @@ -0,0 +1,305 @@ +/**[txh]******************************************************************** + + Description: + This file contains a replacement for djgpp's _fixpath function. Currently +I have two versions. Both are based in djgpp's code. One is for Linux +(adapted by Robert) and the other is for NT adapted by Anatoli Soltan. + +***************************************************************************/ + +#include + +#if defined(TVOS_Win32) && !defined(TVCompf_Cygwin) +/* BC++/Win32, MingW32 and MSVC */ +/* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* Modified for Win32 by Anatoli Soltan */ + +#include +#define Uses_string +#define Uses_getcurdir +#ifndef TVComp_BCPP + #define Uses_direct +#endif +#ifdef TVComp_Watcom + #define Uses_stdio + #define Uses_dir +#endif +#include + +#ifdef TVComp_BCPP + +#include + +static int __fp_getdisk(void) +{ + return getdisk(); +} + +#elif defined(TVComp_MSC) || defined(TVCompf_MinGW) || defined(TVComp_Watcom) + +static int __fp_getdisk(void) +{ + return _getdrive() - 1; +} + +#else +#error "No support for this compiler" +#endif + +// getcurdir is provided by the compatibility layer ;-) +static char* __fp_getcurdir(char* out, int drive) +{ + if (!getcurdir(drive + 1, out)) + out += strlen(out); + return out; +} + +#define is_slash(c) CLY_IsValidDirSep(c) +#define is_term(c) (CLY_IsValidDirSep(c) || c=='\0') + +/* Takes as input an arbitrary path. Fixes up the path by: + 1. Removing consecutive slashes + 2. Removing trailing slashes + 3. Making the path absolute if it wasn't already + 4. Removing "." in the path + 5. Removing ".." entries in the path (and the directory above them) + 6. Adding a drive specification if one wasn't there + 7. Converting all slashes to '/' + */ +void +_fixpath(const char *in, char *out) +{ + int drive_number = 0; + const char *ip = in; + char *op = out; + int unc = CLY_IsUNC(in); /* is a UNC pathname */ + + /* Add drive specification to output string */ + if (((*ip >= 'a' && *ip <= 'z') || + (*ip >= 'A' && *ip <= 'Z')) + && (*(ip + 1) == ':')) + { + if (*ip >= 'a' && *ip <= 'z') + { + drive_number = *ip - 'a'; + *op++ = *ip++; + } + else + { + drive_number = *ip - 'A'; + *op++ = (char)(drive_number + 'a'); + ++ip; + } + *op++ = *ip++; + } + else if (!unc) + { + drive_number = __fp_getdisk(); + *op++ = (char)(drive_number + 'a'); + *op++ = ':'; + } + + /* Convert relative path to absolute */ + if (!is_slash(*ip)) + { + *op++ = '/'; + op = __fp_getcurdir(op, drive_number); + } + + /* Handle UNC path */ + if (unc) + { + *op++ = *ip++; + } + +#if defined(TVOSf_QNX4) + /* Skip the first slashes, which are a node number part */ + /* Full QNX4 pathname is //node/dirpath/filename */ + if ((ip==in) && (is_slash(*ip)) && (is_slash(*(ip+1)))) + { + *op=*ip; + ip++; + op++; + } +#endif // TVOSf_QNX4 + + /* Step through the input path */ + while (*ip) + { + /* Skip input slashes */ + if (is_slash(*ip)) + { + ip++; + continue; + } + + /* Skip "." and output nothing */ + if (*ip == '.' && is_term(*(ip + 1))) + { + ip++; + continue; + } + + /* Skip ".." and remove previous output directory */ + if (*ip == '.' && *(ip + 1) == '.' && is_term(*(ip + 2))) + { + ip += 2; + /* Don't back up over drive spec */ + if (op > out + 2) + { + /* This requires "/" to follow drive spec */ + --op; + while (!is_slash(*op)) --op; + } + continue; + } + + /* Copy path component from in to out */ + *op++ = '/'; + while (!is_term(*ip)) *op++ = *ip++; + } + + /* If root directory, insert trailing slash */ + if (op == out + 2) *op++ = '/'; + + /* Null terminate the output */ + *op = '\0'; + + /* Convert backslashes to slashes */ + for (op = out; *op; op++) + if (*op == '\\') *op = '/'; +} +/* vi: set ts=8 sw=2 : */ +#define FIXPATH_DEFINED +#endif /* BC++/Win32, MingW32 and MSVC */ + + + + + + + +#if defined(NEEDS_FIXPATH) && !defined(FIXPATH_DEFINED) +/* DJGPP, Linux and CygWin */ +/* + Robert: + Here now the very usefull function _fixpath() from DJGPP's + libc 'fixpath.c' + I have modified it to be used on unix systems (like linux). +*/ + +/* Copyright (C) 2002 Salvador E. Tropea */ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#define Uses_unistd +#define Uses_string +#define Uses_limits +#define Uses_getcurdir +#define Uses_stdlib +#include + +inline static int +is_slash(int c) +{ + return c == DIRSEPARATOR; +} + +inline static int +is_term(int c) +{ + return c == DIRSEPARATOR || c == '\0'; +} + +/* Takes as input an arbitrary path. Fixes up the path by: + 1. Removing consecutive slashes + 2. Removing trailing slashes + 3. Making the path absolute if it wasn't already + 4. Removing "." in the path + 5. Removing ".." entries in the path (and the directory above them) + */ +void _fixpath(const char *in, char *out) +{ + const char *ip = in; + char *op = out; + + + /* Convert ~ to the HOME environment variable */ + if (*ip == '~' && (is_slash(ip[1]) || !ip[1])) + { + const char *home = getenv("HOME"); + if (home) + { + strcpy(op,home); + op += strlen(op); + ip++; + if (!*ip) return; + } + } + + /* Convert relative path to absolute */ + if (!is_slash(*ip)) + { + getcurdir(0,op); + op += strlen(op); + } + +#if defined(TVOSf_QNX4) + /* Skip the first slashes, which are a node number part */ + /* Full QNX4 pathname is //node/dirpath/filename */ + if ((ip==in) && (is_slash(*ip)) && (is_slash(*(ip+1)))) + { + *op=*ip; + ip++; + op++; + } +#endif // TVOSf_QNX4 + + /* Step through the input path */ + while (*ip) + { + /* Skip input slashes */ + if (is_slash(*ip)) + { + ip++; + continue; + } + + /* Skip "." and output nothing */ + if (*ip == '.' && is_term(*(ip + 1))) + { + ip++; + continue; + } + + /* Skip ".." and remove previous output directory */ + if (*ip == '.' && *(ip + 1) == '.' && is_term(*(ip + 2))) + { + ip += 2; + /* Don't back up over root '/' */ + if (op > out ) + /* This requires "/" to follow drive spec */ + while (!is_slash(*--op)); + continue; + } + + /* Copy path component from in to out */ + *op++ = '/'; + while (!is_term(*ip)) *op++ = *ip++; + } + + /* If root directory, insert trailing slash */ + if (op == out) *op++ = '/'; + + /* Null terminate the output */ + *op = '\0'; + +} + +/* + End of modified code from DJGPP's libc 'fixpath.c' +*/ +#endif /* DJGPP, Linux and CygWin */ + diff --git a/tvision/compat/fnmatch.c b/tvision/compat/fnmatch.c new file mode 100644 index 0000000..df4dcd8 --- /dev/null +++ b/tvision/compat/fnmatch.c @@ -0,0 +1,150 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* Modified for Win32 by Anatoli Soltan */ +#include + +#ifdef NEEDS_FNMATCH +#include +#include +#define Uses_fnmatch +#include + +#define EOS '\0' + +static const char *rangematch(const char *pattern, char test, int nocase); + +#define isslash(c) ((c) == '\\' || (c) == '/') + +static const char * +find_slash(const char *s) +{ + while (*s) + { + if (isslash(*s)) + return s; + s++; + } + return 0; +} + +static const char * +rangematch(const char *pattern, char test, int nocase) +{ + char c, c2; + int negate, ok; + + if (!!(negate = (*pattern == '!'))) + ++pattern; + + for (ok = 0; (c = *pattern++) != ']';) + { + if (c == 0) + return 0; /* illegal pattern */ + if (*pattern == '-' && (c2 = pattern[1]) != 0 && c2 != ']') + { + if (c <= test && test <= c2) + ok = 1; + if (nocase && toupper(c) <= toupper(test) && toupper(test) <= toupper(c2)) + ok = 1; + pattern += 2; + } + else if (c == test) + ok = 1; + else if (nocase && (toupper(c) == toupper(test))) + ok = 1; + } + return ok == negate ? NULL : pattern; +} + +int +fnmatch(const char *pattern, const char *string, int flags) +{ + char c; + char test; + + for (;;) + switch ((c = *pattern++)) + { + case 0: + return *string == 0 ? 0 : FNM_NOMATCH; + + case '?': + if ((test = *string++) == 0 || + (isslash(test) && (flags & FNM_PATHNAME))) + return(FNM_NOMATCH); + break; + + case '*': + c = *pattern; + /* collapse multiple stars */ + while (c == '*') + c = *++pattern; + + /* optimize for pattern with * at end or before / */ + if (c == 0) + { + if (flags & FNM_PATHNAME) + return find_slash(string) ? FNM_NOMATCH : 0; + else + return 0; + } + else if (isslash(c) && flags & FNM_PATHNAME) + { + if ((string = find_slash(string)) == NULL) + return FNM_NOMATCH; + break; + } + + /* general case, use recursion */ + while ((test = *string) != 0) + { + if (fnmatch(pattern, string, flags) == 0) + return(0); + if (isslash(test) && flags & FNM_PATHNAME) + break; + ++string; + } + return FNM_NOMATCH; + + case '[': + if ((test = *string++) == 0 || + (isslash(test) && flags & FNM_PATHNAME)) + return FNM_NOMATCH; + if ((pattern = rangematch(pattern, test, flags & FNM_NOCASE)) == NULL) + return FNM_NOMATCH; + break; + + case '\\': + if (!(flags & FNM_NOESCAPE) && pattern[1] && strchr("*?[\\", pattern[1])) + { + if ((c = *pattern++) == 0) + { + c = '\\'; + --pattern; + } + if (c != *string++) + return FNM_NOMATCH; + break; + } + /* FALLTHROUGH */ + + default: + if (isslash(c) && isslash(*string)) + { + string++; + break; + } + if (flags & FNM_NOCASE) + { + if (toupper(c) != toupper(*string++)) + return FNM_NOMATCH; + } + else + { + if (c != *string++) + return FNM_NOMATCH; + } + break; + } +} +#endif // NEEDS_FNMATCH diff --git a/tvision/compat/getcurdir.c b/tvision/compat/getcurdir.c new file mode 100644 index 0000000..6af56ec --- /dev/null +++ b/tvision/compat/getcurdir.c @@ -0,0 +1,68 @@ +/* + Copyright (C) 1996-1998 Robert H”hne + Copyright (C) 2000 Vadim Beloborodov + Copyright (C) 2000 Anatoli Soltan + Copyright (C) 2000-2005 Salvador E. Tropea + Covered by the GPL license. +*/ + +#include + +#define Uses_limits +#define Uses_string +#define Uses_unistd +#include + +#ifdef NEEDS_GETCURDIR + +#ifdef TVCompf_djgpp +// DOS version by Robert +#include + +int CLY_getcurdir(int drive, char *buffer) +{ + if (!drive) getwd(buffer); + else + { + int d = getdisk(); + setdisk(drive-1); + getwd(buffer); + setdisk(d); + } + strcpy(buffer,buffer+3); + return 0; +} +#endif // DJGPP + +#if defined(TVOS_Win32) && !defined(TVComp_BCPP) && !defined(TVCompf_Cygwin) +// MSVC/MingW/OW Windows version by Vadim and Anatoli +#include + +int CLY_getcurdir(int drive, char *buffer) +{ + _getdcwd(drive, buffer,PATH_MAX); + strcpy(buffer,buffer+3); + return 0; +} +#endif // MSVC/MingW/OW + +#if defined(TVOS_UNIX) || defined(TVCompf_Cygwin) +// Linux and CygWin version + +int CLY_getcurdir(int drive, char *buffer) +{ + getcwd(buffer, PATH_MAX); + return 0; +} +#endif + +#endif // NEEDS_GETCURDIR + +void CLY_GetCurDirSlash(char *dir) +{ + getcwd(dir,PATH_MAX); + if (dir[strlen(dir)-1]!=DIRSEPARATOR) + strcat(dir,DIRSEPARATOR_); +} + + diff --git a/tvision/compat/getline.c b/tvision/compat/getline.c new file mode 100644 index 0000000..f3a535d --- /dev/null +++ b/tvision/compat/getline.c @@ -0,0 +1,189 @@ +/**[txh]******************************************************************** + + Description: + getline.c -- Replacement for GNU C library function getline. + +***************************************************************************/ +#include + +#ifdef NEEDS_GETLINE +/* getline.c -- Replacement for GNU C library function getline + +Copyright (C) 1993 Free Software Foundation, Inc. + +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. */ + +/* Written by Jan Brittenson, bson@gnu.ai.mit.edu. */ +/* Small modifications by Salvador E. Tropea */ + +#define NDEBUG + +/* Already included */ +#include +#include +#include +#include +#include +/*#include "getline.h"*/ +/** Header **/ +#define GETLINE_NO_LIMIT -1 + +#if defined(TVCompf_MinGW) + #if defined(_SSIZE_T_) && !defined(_NO_OLDNAMES) + #define MinGW_SSIZE_T 0 + #else + #define MinGW_SSIZE_T 1 + #endif +#endif + +#if defined(TVComp_BCPP) || MinGW_SSIZE_T || defined(TVComp_MSC) || defined(TVComp_Watcom) +typedef long ssize_t; +#endif + +ssize_t CLY_getline(char **_lineptr, size_t *_n, FILE *_stream); +ssize_t CLY_getline_safe(char **_lineptr, size_t *_n, FILE *_stream, int limit); +ssize_t CLY_getstr(char **_lineptr, size_t *_n, FILE *_stream, + char _terminator, int _offset, int limit); +/** End of Header **/ + +/* Always add at least this many bytes when extending the buffer. */ +#define MIN_CHUNK 64 + +/* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR + + OFFSET (and null-terminate it). If LIMIT is non-negative, then + read no more than LIMIT chars. + + *LINEPTR is a pointer returned from malloc (or NULL), pointing to + *N characters of space. It is realloc'd as necessary. + + Return the number of characters read (not including the null + terminator), or -1 on error or EOF. On a -1 return, the caller + should check feof(), if not then errno has been set to indicate the + error. */ + +ssize_t CLY_getstr(char **lineptr, size_t *n, FILE *stream, char terminator, + int offset, int limit) +{ + int nchars_avail; /* Allocated but unused chars in *LINEPTR. */ + char *read_pos; /* Where we're reading into *LINEPTR. */ + ssize_t ret; + + if (!lineptr || !n || !stream) + { + errno=EINVAL; + return -1; + } + + if (!*lineptr) + { + *n=MIN_CHUNK; + *lineptr=(char *)malloc(*n); + if (!*lineptr) + { + errno=ENOMEM; + return -1; + } + } + + nchars_avail=*n-offset; + read_pos=*lineptr+offset; + + for (;;) + { + int save_errno; + register int c; + + if (limit==0) + break; + else + { + c=getc(stream); + /* If limit is negative, then we shouldn't pay attention to + it, so decrement only if positive. */ + if (limit>0) + limit--; + } + save_errno=errno; + + /* We always want at least one char left in the buffer, since we + always (unless we get an error while reading the first char) + NUL-terminate the line buffer. */ + + assert((*lineptr+*n)==(read_pos+nchars_avail)); + if (nchars_avail<2) + { + if (*n>MIN_CHUNK) + *n*=2; + else + *n+=MIN_CHUNK; + + nchars_avail=*n+*lineptr-read_pos; + *lineptr=(char *)realloc(*lineptr,*n); + if (!*lineptr) + { + errno=ENOMEM; + return -1; + } + read_pos=*n-nchars_avail+*lineptr; + assert((*lineptr+*n)==(read_pos+nchars_avail)); + } + + if (ferror(stream)) + { + /* Might like to return partial line, but there is no + place for us to store errno. And we don't want to just + lose errno. */ + errno = save_errno; + return -1; + } + + if (c==EOF) + { + /* Return partial line, if any. */ + if (read_pos==*lineptr) + return -1; + else + break; + } + + /* SET: Why in the hell a low level function should do it? */ + #if 0 /*_WIN32*/ + /* Text mode translation, CR/LF pairs into LF */ + if (terminator=='\n' && c=='\r') + continue; + #endif + + *read_pos++=c; + nchars_avail--; + + if (c==terminator) + /* Return the line. */ + break; + } + + /* Done - NUL terminate and return the number of chars read. */ + *read_pos='\0'; + + ret=read_pos-(*lineptr+offset); + return ret; +} + +ssize_t CLY_getline(char **lineptr, size_t *n, FILE *stream) +{ + return CLY_getstr(lineptr,n,stream,'\n',0,GETLINE_NO_LIMIT); +} + +ssize_t CLY_getline_safe(char **lineptr, size_t *n, FILE *stream, int limit) +{ + return CLY_getstr(lineptr,n,stream,'\n',0,limit); +} +#endif // NEEDS_GETLINE + diff --git a/tvision/compat/getopt.c b/tvision/compat/getopt.c new file mode 100644 index 0000000..a53c8b7 --- /dev/null +++ b/tvision/compat/getopt.c @@ -0,0 +1,754 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 + Free Software Foundation, Inc. + Copyright (C) 2000, 01, 2002 + Salvador E. Tropea. + + 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, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +#include + +#ifdef NEEDS_GETOPT + +/* NOTE!!! AIX requires this to be the first thing in the file. + Do not put ANYTHING before it! */ +#if !defined (TVComp_GCC) && defined (_AIX) + #pragma alloca +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef TVComp_GCC + #define alloca __builtin_alloca +#else /* not TVComp_GCC */ + #if defined (HAVE_ALLOCA_H) || (defined(sparc) && (defined(sun) || (!defined(USG) && !defined(SVR4) && !defined(__svr4__)))) + #include + #else + #ifdef TVComp_BCPP + #include + #else + #ifdef TVComp_MSC + #include + #define alloca _alloca + #else + #ifdef TVComp_Watcom + void *alloca (); + #else + #ifndef _AIX + char *alloca (); + #endif + #endif /* TVComp_Watcom */ + #endif /* MSVC */ + #endif /* TURBOC */ + #endif /* alloca.h */ +#endif /* not TVComp_GCC */ + +#if !__STDC__ && !defined(const) && IN_GCC +#define const +#endif + +/* This tells Alpha OSF/1 not to define a getopt prototype in . */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ + #undef alloca + /* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ + #include +#else /* Not GNU C library. */ + #ifndef TVComp_Watcom + #define __alloca alloca + #endif +#endif /* GNU C library. */ + +/* SET: more headers needed, __alloca isn't valid */ +#if defined(TVCompf_djgpp) || defined(TVOS_Win32) || defined(TVOSf_Solaris) || defined(TVOSf_QNX4) + #include +#endif + +#if defined(TVComp_BCPP) || defined(TVComp_Watcom) + #include /* alloca */ +#endif + +/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a + long-named option. Because this is not POSIX.2 compliant, it is + being phased out. */ +/* #define GETOPT_COMPAT */ + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *CLY_optarg = 0; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* XXX 1003.2 says this must be 1 before any call. */ +int CLY_optind = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int CLY_opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int CLY_optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return EOF with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +/* SET: I don't understand why hello.c doesn't make it */ +#if defined(__GNU_LIBRARY__) || defined(TVCompf_djgpp) || defined(TVOS_Win32) || defined(TVOSf_Solaris) || defined(TVOSf_QNX4) +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +#include +#define my_index strchr +#define my_bcopy(src, dst, n) memcpy ((dst), (src), (n)) +#else + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +char *getenv (); + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +static void +my_bcopy (from, to, size) + const char *from; + char *to; + int size; +{ + int i; + for (i = 0; i < size; i++) + to[i] = from[i]; +} +#endif /* GNU C library. */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +static void +exchange (char **argv) +{ + int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *); + char **temp = (char **) __alloca (nonopts_size); + + /* Interchange the two blocks of data in ARGV. */ + + my_bcopy ((char *) &argv[first_nonopt], (char *) temp, nonopts_size); + my_bcopy ((char *) &argv[last_nonopt], (char *) &argv[first_nonopt], + (CLY_optind - last_nonopt) * sizeof (char *)); + my_bcopy ((char *) temp, + (char *) &argv[first_nonopt + CLY_optind - last_nonopt], + nonopts_size); + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (CLY_optind - last_nonopt); + last_nonopt = CLY_optind; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns `EOF'. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +CLY_getopt_internal(int argc, char *const *argv, const char *optstring, + const struct CLY_option *longopts, int *longind, int long_only) +{ + int option_index; + + CLY_optarg = 0; + + /* Initialize the internal data when the first call is made. + Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + if (CLY_optind == 0) + { + first_nonopt = last_nonopt = CLY_optind = 1; + + nextchar = NULL; + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (getenv ("POSIXLY_CORRECT") != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + } + + if (nextchar == NULL || *nextchar == '\0') + { + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != CLY_optind) + exchange ((char **) argv); + else if (last_nonopt != CLY_optind) + first_nonopt = CLY_optind; + + /* Now skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (CLY_optind < argc + && (argv[CLY_optind][0] != '-' || argv[CLY_optind][1] == '\0') +#ifdef GETOPT_COMPAT + && (longopts == NULL + || argv[CLY_optind][0] != '+' || argv[CLY_optind][1] == '\0') +#endif /* GETOPT_COMPAT */ + ) + CLY_optind++; + last_nonopt = CLY_optind; + } + + /* Special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (CLY_optind != argc && !strcmp (argv[CLY_optind], "--")) + { + CLY_optind++; + + if (first_nonopt != last_nonopt && last_nonopt != CLY_optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = CLY_optind; + last_nonopt = argc; + + CLY_optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (CLY_optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + CLY_optind = first_nonopt; + return EOF; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if ((argv[CLY_optind][0] != '-' || argv[CLY_optind][1] == '\0') +#ifdef GETOPT_COMPAT + && (longopts == NULL + || argv[CLY_optind][0] != '+' || argv[CLY_optind][1] == '\0') +#endif /* GETOPT_COMPAT */ + ) + { + if (ordering == REQUIRE_ORDER) + return EOF; + CLY_optarg = argv[CLY_optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Start decoding its characters. */ + + nextchar = (argv[CLY_optind] + 1 + + (longopts != NULL && argv[CLY_optind][1] == '-')); + } + + if (longopts != NULL + && ((argv[CLY_optind][0] == '-' + && (argv[CLY_optind][1] == '-' || long_only)) +#ifdef GETOPT_COMPAT + || argv[CLY_optind][0] == '+' +#endif /* GETOPT_COMPAT */ + )) + { + const struct CLY_option *p; + char *s = nextchar; + int exact = 0; + int ambig = 0; + const struct CLY_option *pfound = NULL; + /* SET: might be used no initialized? */ + int indfound=0; + + while (*s && *s != '=') + s++; + + /* Test all options for either exact match or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; + p++, option_index++) + if (!strncmp (p->name, nextchar, s - nextchar)) + { + if ((size_t)(s - nextchar) == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (CLY_opterr) + fprintf (stderr, "%s: option `%s' is ambiguous\n", + argv[0], argv[CLY_optind]); + nextchar += strlen (nextchar); + CLY_optind++; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + CLY_optind++; + if (*s) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + CLY_optarg = s + 1; + else + { + if (CLY_opterr) + { + if (argv[CLY_optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + "%s: option `--%s' doesn't allow an argument\n", + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + "%s: option `%c%s' doesn't allow an argument\n", + argv[0], argv[CLY_optind - 1][0], pfound->name); + } + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (CLY_optind < argc) + CLY_optarg = argv[CLY_optind++]; + else + { + if (CLY_opterr) + fprintf (stderr, "%s: option `%s' requires an argument\n", + argv[0], argv[CLY_optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[CLY_optind][1] == '-' +#ifdef GETOPT_COMPAT + || argv[CLY_optind][0] == '+' +#endif /* GETOPT_COMPAT */ + || my_index (optstring, *nextchar) == NULL) + { + if (CLY_opterr) + { + if (argv[CLY_optind][1] == '-') + /* --option */ + fprintf (stderr, "%s: unrecognized option `--%s'\n", + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, "%s: unrecognized option `%c%s'\n", + argv[0], argv[CLY_optind][0], nextchar); + } + nextchar = (char *) ""; + CLY_optind++; + return '?'; + } + } + + /* Look at and handle the next option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++CLY_optind; + + if (temp == NULL || c == ':') + { + if (CLY_opterr) + { +#if 0 + if (c < 040 || c >= 0177) + fprintf (stderr, "%s: unrecognized option, character code 0%o\n", + argv[0], c); + else + fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c); +#else + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); +#endif + } + CLY_optopt = c; + return '?'; + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + CLY_optarg = nextchar; + CLY_optind++; + } + else + CLY_optarg = 0; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + CLY_optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + CLY_optind++; + } + else if (CLY_optind == argc) + { + if (CLY_opterr) + { +#if 0 + fprintf (stderr, "%s: option `-%c' requires an argument\n", + argv[0], c); +#else + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: option requires an argument -- %c\n", + argv[0], c); +#endif + } + CLY_optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + CLY_optarg = argv[CLY_optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +CLY_getopt(int argc, char *const *argv, const char *optstring) +{ + return CLY_getopt_internal (argc, argv, optstring, + (const struct CLY_option *) 0, + (int *) 0, + 0); +} + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main (int argc, char **argv) +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = CLY_optind ? CLY_optind : 1; + + c = CLY_getopt (argc, argv, "abc:d:0123456789"); + if (c == EOF) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", CLY_optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (CLY_optind < argc) + { + printf ("non-option ARGV-elements: "); + while (CLY_optind < argc) + printf ("%s ", argv[CLY_optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ +#endif /* NEEDS_GETOPT */ diff --git a/tvision/compat/getopt1.c b/tvision/compat/getopt1.c new file mode 100644 index 0000000..52a20f6 --- /dev/null +++ b/tvision/compat/getopt1.c @@ -0,0 +1,174 @@ +/* getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 + Free Software Foundation, Inc. + Copyright (C) 2000, 01, 2002 + Salvador E. Tropea. + + 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, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include + +#ifdef NEEDS_GETOPT + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#if !__STDC__ && !defined(const) && IN_GCC +#define const +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#if defined(__GNU_LIBRARY__) || defined(TVOS_Win32) +#include +#else +char *getenv (); +#endif + +#ifndef NULL +#define NULL 0 +#endif + +int +CLY_getopt_long(int argc, char *const *argv, const char *options, + const struct CLY_option *long_options, int *opt_index) +{ + return CLY_getopt_internal (argc, argv, options, long_options, opt_index, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +CLY_getopt_long_only(int argc, char *const *argv, const char *options, + const struct CLY_option *long_options, int *opt_index) +{ + return CLY_getopt_internal (argc, argv, options, long_options, opt_index, 1); +} + + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#ifdef TEST + +#include + +int +main (int argc, char **argv) +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = CLY_optind ? CLY_optind : 1; + int option_index = 0; + static struct CLY_option long_options[] = + { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "abc:d:0123456789", + long_options, &option_index); + if (c == EOF) + break; + + switch (c) + { + case 0: + printf ("option %s", long_options[option_index].name); + if (CLY_optarg) + printf (" with arg %s", CLY_optarg); + printf ("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", CLY_optarg); + break; + + case 'd': + printf ("option d with value `%s'\n", CLY_optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (CLY_optind < argc) + { + printf ("non-option ARGV-elements: "); + while (CLY_optind < argc) + printf ("%s ", argv[CLY_optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ +#endif /* NEEDS_GETOPT */ + diff --git a/tvision/compat/getshell.c b/tvision/compat/getshell.c new file mode 100644 index 0000000..e8954be --- /dev/null +++ b/tvision/compat/getshell.c @@ -0,0 +1,20 @@ +/* + Copyright (C) 2001,2002 Salvador E. Tropea + Covered by the GPL license. +*/ +#define Uses_stdlib +#include + +#if (defined(TVOS_DOS) || defined(TVOS_Win32)) && !defined(TVCompf_Cygwin) +CLY_EXPORT char *CLY_GetShellName(void) +{ + return getenv("COMSPEC"); +} +#endif + +#if defined(TVOS_UNIX) || defined(TVCompf_Cygwin) +char *CLY_GetShellName(void) +{ + return getenv("SHELL"); +} +#endif diff --git a/tvision/compat/glob.c b/tvision/compat/glob.c new file mode 100644 index 0000000..eea9c9c --- /dev/null +++ b/tvision/compat/glob.c @@ -0,0 +1,422 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* Modified for Win32 by Anatoli Soltan */ + +#include + +#ifdef NEEDS_GLOB +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include +#include +#ifndef TVComp_MSC + #include +#endif + +#define Uses_glob +#define Uses_unistd +#define Uses_fnmatch +#define Uses_alloca +#include + +typedef struct Save { + struct Save *prev; + char *entry; +} Save; + +static Save *save_list; +static int save_count; +static int flags; +static int (*errfunc)(const char *epath, int eerno); +static char *pathbuf; +static int wildcard_nesting; +static char use_lfn; +static char preserve_case; +static char slash; + +static int glob2(const char *pattern, char *epathbuf, int lower, int caseless); +static int glob_dirs(const char *rest, char *epathbuf, int first, int lower, int caseless); +static int add(const char *path); +static int str_compare(const void *va, const void *vb); + +static int _preserve_fncase(void) +{ + return 1; +} + +static int +add(const char *path) +{ + Save *sp; + for (sp=save_list; sp; sp=sp->prev) + if (stricmp(sp->entry, path) == 0) + return 0; + sp = (Save *)malloc(sizeof(Save)); + if (sp == 0) + return 1; + sp->entry = (char *)malloc(strlen(path)+1); + if (sp->entry == 0) + { + free(sp); + return 1; + } +/* printf("add: `%s'\n", path); */ + strcpy(sp->entry, path); + sp->prev = save_list; + save_list = sp; + save_count++; + return 0; +} + +static int +glob_dirs(const char *rest, char *epathbuf, int first, /* rest is ptr to null or ptr after slash, bp after slash */ + int lower, int caseless) +{ +// struct ffblk ff; + HANDLE hf; + WIN32_FIND_DATA wfd; + BOOL done; + +/* printf("glob_dirs[%d]: rest=`%s' %c epathbuf=`%s' %c pathbuf=`%s'\n", + wildcard_nesting, rest, *rest, epathbuf, *epathbuf, pathbuf); */ + + if (first) + { + if (*rest) + { + if (glob2(rest, epathbuf, lower, caseless) == GLOB_NOSPACE) + return GLOB_NOSPACE; + } + else + { + char sl = epathbuf[-1]; + *epathbuf = 0; +/* printf("end, checking `%s'\n", pathbuf); */ + if (epathbuf == pathbuf) + { + epathbuf[0] = '.'; + epathbuf[1] = 0; + } + else + epathbuf[-1] = 0; + if (CLY_FileExists(pathbuf)) + if (add(pathbuf)) + return GLOB_NOSPACE; + epathbuf[-1] = sl; + } + } + + strcpy(epathbuf, "*.*"); + hf = FindFirstFile(pathbuf, &wfd); + done = (hf == INVALID_HANDLE_VALUE); + while (!done) + { + if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + && (strcmp(wfd.cFileName, ".") && strcmp(wfd.cFileName, ".."))) + { + char *tp; + + strcpy(epathbuf, wfd.cFileName); + tp = epathbuf + strlen(epathbuf); + *tp++ = slash; + *tp = 0; + + wildcard_nesting++; + if (*rest) + { + if (glob2(rest, tp, lower, caseless) == GLOB_NOSPACE) + return GLOB_NOSPACE; + } + else + { + if (!(flags & GLOB_MARK)) + tp[-1] = 0; + if (add(pathbuf)) + return GLOB_NOSPACE; + tp[-1] = slash; + } + *tp = 0; + if (glob_dirs(rest, tp, 0, lower, caseless) == GLOB_NOSPACE) + return GLOB_NOSPACE; + wildcard_nesting--; + } + done = !FindNextFile(hf, &wfd); + } + FindClose(hf); + return 0; +} + +static int +glob2(const char *pattern, char *epathbuf, /* both point *after* the slash */ + int lower, int caseless) +{ + const char *pp, *pslash; + char *bp; + HANDLE hf; + WIN32_FIND_DATA wfd; + char *my_pattern; + int done; + + if (strcmp(pattern, "...") == 0) + { + return glob_dirs(pattern+3, epathbuf, 1, lower, caseless); + } + if (strncmp(pattern, "...", 3) == 0 && (pattern[3] == '\\' || pattern[3] == '/')) + { + slash = pattern[3]; + return glob_dirs(pattern+4, epathbuf, 1, lower, caseless); + } + + *epathbuf = 0; + /* copy as many non-wildcard segments as possible */ + pp = pattern; + bp = epathbuf; + pslash = bp-1; + while (1) + { + if (*pp == ':' || *pp == '\\' || *pp == '/') + { + pslash = bp; + if (strcmp(pp+1, "...") == 0 + || (strncmp(pp+1, "...", 3) == 0 && (pp[4] == '/' || pp[4] == '\\'))) + { + if (*pp != ':') + slash = *pp; +/* printf("glob2: dots at `%s'\n", pp); */ + *bp++ = *pp++; + break; + } + } + + else if (*pp == '*' || *pp == '?' || *pp == '[') + { + if (pslash > pathbuf) + strncpy(epathbuf, pattern, pslash - pathbuf); + pp = pattern + (pslash - epathbuf) + 1; + bp = epathbuf + (pslash - epathbuf) + 1; + break; + } + + else if (*pp == 0) + { + break; + } + + /* Upper-case or mixed-case patterns force case-sensitive + matches in `fnmatch' for LFN filesystems. They also + suppress downcasing 8+3 filenames (on all filesystems). */ + else if (!preserve_case) + { + if (*pp >= 'A' && *pp <= 'Z') + { + if (use_lfn) + caseless = 0; + lower = 0; + } + else if (*pp >= 'a' && *pp <= 'z') + lower = 1; + } + + *bp++ = *pp++; + } + *bp = 0; + + if (*pp == 0) /* end of pattern? */ + { + if (CLY_FileExists(pathbuf)) + { + if (flags & GLOB_MARK) + { + HANDLE _hf; + WIN32_FIND_DATA _wfd; + _hf = FindFirstFile(pathbuf, &_wfd); + //findfirst(pathbuf, &_ff, FA_RDONLY|FA_SYSTEM|FA_DIREC|FA_ARCH); + if (_hf != INVALID_HANDLE_VALUE && _wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + char *_pathbuf = pathbuf + strlen(pathbuf); + *_pathbuf++ = '/'; + *_pathbuf = 0; + } + FindClose(_hf); + } + if (add(pathbuf)) + return GLOB_NOSPACE; + } + return 0; + } +/* printf("glob2: initial segment is `%s'\n", pathbuf); */ + if (wildcard_nesting) + { + char s = bp[-1]; + bp[-1] = 0; + if (!CLY_FileExists(pathbuf)) + return 0; + bp[-1] = s; + } + + for (pslash = pp; *pslash && *pslash != '\\' && *pslash != '/'; pslash++) + if (!preserve_case) + { + if (*pslash >= 'A' && *pslash <= 'Z') + { + if (use_lfn) + caseless = 0; + lower = 0; + } + else if (*pslash >= 'a' && *pslash <= 'z') + lower = 1; + } + + if (*pslash) + slash = *pslash; + my_pattern = (char *)alloca(pslash - pp + 1); + if (my_pattern == 0) + return GLOB_NOSPACE; + strncpy(my_pattern, pp, pslash - pp); + my_pattern[pslash-pp] = 0; + +/* printf("glob2: `%s' `%s'\n", pathbuf, my_pattern); */ + + if (strcmp(my_pattern, "...") == 0) + { + if (glob_dirs(*pslash ? pslash+1 : pslash, bp, 1, lower, caseless) == GLOB_NOSPACE) + return GLOB_NOSPACE; + return 0; + } + + strcpy(bp, "*.*"); + + hf = FindFirstFile(pathbuf, &wfd); + done = (hf == INVALID_HANDLE_VALUE); + //done = findfirst(pathbuf, &ff, FA_RDONLY|FA_SYSTEM|FA_DIREC|FA_ARCH); + while (!done) + { + if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 + || (strcmp(wfd.cFileName, ".") && strcmp(wfd.cFileName, ".."))) + { + if (fnmatch(my_pattern, wfd.cFileName, + FNM_NOESCAPE|FNM_PATHNAME|(caseless ? FNM_NOCASE : 0)) == 0) + { + strcpy(bp, wfd.cFileName); + if (*pslash) + { + char *tp = bp + strlen(bp); + *tp++ = *pslash; + *tp = 0; +/* printf("nest: `%s' `%s'\n", pslash+1, pathbuf); */ + wildcard_nesting++; + if (glob2(pslash+1, tp, lower, caseless) == GLOB_NOSPACE) + return GLOB_NOSPACE; + wildcard_nesting--; + } + else + { +/* printf("ffmatch: `%s' matching `%s', add `%s'\n", + wfd.cFileName, my_pattern, pathbuf); */ + if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && (flags & GLOB_MARK)) + { + bp[strlen(bp)+1] = 0; + bp[strlen(bp)] = slash; + } + if (add(pathbuf)) + return GLOB_NOSPACE; + } + } + } + done = !FindNextFile(hf, &wfd); + } + + return 0; +} + +static int +str_compare(const void *va, const void *vb) +{ + return strcmp(*(const char * const *)va, *(const char * const *)vb); +} + +int +glob(const char *_pattern, int _flags, int (*_errfunc)(const char *_epath, int _eerrno), glob_t *_pglob) +{ + char path_buffer[2000]; + int l_ofs, l_ptr; + + pathbuf = path_buffer+1; + flags = _flags; + errfunc = _errfunc; + wildcard_nesting = 0; + save_count = 0; + save_list = 0; + preserve_case = (char)_preserve_fncase(); + slash = '/'; + + if (!(_flags & GLOB_APPEND)) + { + _pglob->gl_pathc = 0; + _pglob->gl_pathv = NULL; + if (!(flags & GLOB_DOOFFS)) + _pglob->gl_offs = 0; + } + if (glob2(_pattern, pathbuf, preserve_case ? 0 : 1, /*preserve_case ? 0 :*/ 1) == GLOB_NOSPACE) + { + return GLOB_NOSPACE; + } + + if (save_count == 0) + { + if (flags & GLOB_NOCHECK) + { + if (add(_pattern)) + return GLOB_NOSPACE; + } + else + return GLOB_NOMATCH; + } + + if (flags & GLOB_DOOFFS) + l_ofs = _pglob->gl_offs; + else + l_ofs = 0; + + if (flags & GLOB_APPEND) + { + _pglob->gl_pathv = (char **)realloc(_pglob->gl_pathv, (l_ofs + _pglob->gl_pathc + save_count + 1) * sizeof(char *)); + if (_pglob->gl_pathv == 0) + return GLOB_NOSPACE; + l_ptr = l_ofs + _pglob->gl_pathc; + } + else + { + _pglob->gl_pathv = (char* *)malloc((l_ofs + save_count + 1) * sizeof(char *)); + if (_pglob->gl_pathv == 0) + return GLOB_NOSPACE; + l_ptr = l_ofs; + if (l_ofs) + memset(_pglob->gl_pathv, 0, l_ofs * sizeof(char *)); + } + + l_ptr += save_count; + _pglob->gl_pathv[l_ptr] = 0; + while (save_list) + { + Save *s = save_list; + l_ptr --; + _pglob->gl_pathv[l_ptr] = save_list->entry; + save_list = save_list->prev; + free(s); + } + if (!(flags & GLOB_NOSORT)) + qsort(_pglob->gl_pathv + l_ptr, save_count, sizeof(char *), str_compare); + + _pglob->gl_pathc = l_ptr + save_count; + + return 0; +} +#endif // NEEDS_GLOB + diff --git a/tvision/compat/globfree.c b/tvision/compat/globfree.c new file mode 100644 index 0000000..ee034e1 --- /dev/null +++ b/tvision/compat/globfree.c @@ -0,0 +1,20 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +#ifdef NEEDS_GLOB +#define Uses_stdlib +#define Uses_glob +#define Uses_free +#include + +void globfree(glob_t *_pglob) +{ + size_t i; + if (!_pglob->gl_pathv) + return; + for (i=0; i<_pglob->gl_pathc; i++) + if (_pglob->gl_pathv[i]) + free(_pglob->gl_pathv[i]); + free(_pglob->gl_pathv); +} +#endif // NEEDS_GLOB diff --git a/tvision/compat/iffilelen.cc b/tvision/compat/iffilelen.cc new file mode 100644 index 0000000..7976774 --- /dev/null +++ b/tvision/compat/iffilelen.cc @@ -0,0 +1,46 @@ +/* + Copyright (c) 2001 by Salvador E. Tropea + Covered by the GPL license. + Note: I included CLY_IfStreamGetLine here. I know it could be confusing but + adding a new file isn't good. +*/ +#include +#ifndef HAVE_SSC + +#define Uses_filelength +#define Uses_fstream +#include + +#include + +UsingNamespaceStd + +#if CLY_ISOCpp98 +long CLY_ifsFileLength(ifstream &f) +{ + std::streampos pos=f.tellg(); + long ret=f.seekg(0,CLY_IOSEnd).tellg(); + f.seekg(pos,CLY_IOSBeg); + return ret; +} +#else +CLY_EXPORT long CLY_ifsFileLength(ifstream &f) +{ + return filelength(f.rdbuf()->fd()); +} +#endif + +#ifdef NEEDS_IFSTREAMGETLINE +CLY_EXPORT int CLY_IfStreamGetLine(ifstream &is, char *buffer, unsigned len) +{ + if (is.get(buffer,len)) + { + char c; + is.get(c); // grab trailing newline + return 1; + } + return 0; +} +#endif // NEEDS_IFSTREAMGETLINE + +#endif diff --git a/tvision/compat/isdir.c b/tvision/compat/isdir.c new file mode 100644 index 0000000..8eae6a5 --- /dev/null +++ b/tvision/compat/isdir.c @@ -0,0 +1,19 @@ +/* + Copyright (C) 1996-1998 Robert H”hne + Copyright (C) 2000 Salvador E. Tropea + Covered by the GPL license. +*/ + +#define Uses_sys_stat +#include + +int CLY_IsDir(const char *str) +{ + struct stat s; + + if (CLY_IsUNCShare(str)) + return 1; + if (stat(str,&s)==0 && S_ISDIR(s.st_mode)) + return 1; + return 0; +} diff --git a/tvision/compat/isrelpath.c b/tvision/compat/isrelpath.c new file mode 100644 index 0000000..79fa4e9 --- /dev/null +++ b/tvision/compat/isrelpath.c @@ -0,0 +1,33 @@ +/* + Copyright (C) 1996-1998 Robert H”hne + Copyright (C) 2000-2002 Salvador E. Tropea + Covered by the GPL license. +*/ + +#define Uses_ctype +#define Uses_stdlib +#include + +#if defined(TVOS_DOS) || defined(TVOS_Win32) + #define StartsWithDrive(path) (ucisalpha(path[0]) && path[1]==':') +#else + #define StartsWithDrive(path) (0) +#endif + +#if defined(TVOS_Win32) && !defined(TVCompf_Cygwin) + #define IsHomeSymbol(path) (0) +#else +inline static int +is_slash(int c) +{ + return CLY_IsValidDirSep(c); +} + #define IsHomeSymbol(path) (path[0]=='~' && (!path[1] || CLY_IsValidDirSep(path[1]))\ + && getenv("HOME")) +#endif + +int CLY_IsRelativePath(const char *path) +{ + return + !(path[0] && (CLY_IsValidDirSep(path[0]) || StartsWithDrive(path) || IsHomeSymbol(path))); +} diff --git a/tvision/compat/iswild.c b/tvision/compat/iswild.c new file mode 100644 index 0000000..1684eab --- /dev/null +++ b/tvision/compat/iswild.c @@ -0,0 +1,12 @@ +/* + Copyright (C) 1996-1998 Robert H”hne + Copyright (C) 2000 Salvador E. Tropea + Covered by the GPL license. +*/ + +#include + +int CLY_IsWild(const char *f) +{ + return strpbrk(f,"?*")!=0; +} diff --git a/tvision/compat/itoa.c b/tvision/compat/itoa.c new file mode 100644 index 0000000..f3737e5 --- /dev/null +++ b/tvision/compat/itoa.c @@ -0,0 +1,48 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#ifdef NEEDS_ITOA +#include +#include + +char *itoa(int value, char *string, int radix) +{ + char tmp[32+1]; // int is 32 bits, we assume it + char *tp = tmp; + int i; + unsigned v; + int sign; + char *sp; + + if (radix > 36 || radix <= 1) + { + errno = EDOM; + return 0; + } + + sign = (radix == 10 && value < 0); + if (sign) + v = -value; + else + v = (unsigned)value; + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + if (string == 0) + string = (char *)malloc((tp-tmp)+sign+1); + sp = string; + + if (sign) + *sp++ = '-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} +#endif // NEEDS_ITOA diff --git a/tvision/compat/mkstemp.c b/tvision/compat/mkstemp.c new file mode 100644 index 0000000..a8340f9 --- /dev/null +++ b/tvision/compat/mkstemp.c @@ -0,0 +1,48 @@ +/* Copyright (C) 2000-2005 Salvador E. Tropea */ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +#ifdef NEEDS_MKSTEMP +#include +#include +#include +#include +#include + +#ifdef TVComp_Watcom + #include + #define mktemp(a) _mktemp(a) +#endif + +#if _MSC_VER >= 1400 + #define mktemp(a) _mktemp(a) + #define open(a,b,c) _open(a,b,c) +#endif + +int mkstemp (char *_template) +{ + char tmp_name[FILENAME_MAX]; + int fd = -1; + + /* Make sure we create a non-exisiting file, even + if race conditions exist with other processes. */ + do { + strcpy(tmp_name, _template); + errno = 0; + } while (mktemp (tmp_name) != NULL + /* SAA: changed file mode from 0 to 0666 because on WinNT it creted files + * with read-only attribute set. Fix me if it causes problems on other + * platforms. + */ + && (fd = open(tmp_name, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0666)) == -1 + && errno == EEXIST); + + if (fd == -1) + errno = ENOENT; + else + strcpy(_template, tmp_name); + + return fd; +} +#endif diff --git a/tvision/compat/nl_langinfo.c b/tvision/compat/nl_langinfo.c new file mode 100644 index 0000000..234abad --- /dev/null +++ b/tvision/compat/nl_langinfo.c @@ -0,0 +1,71 @@ +/* + Copyright (C) 2001-2005 Salvador E. Tropea + Covered by the GPL license. +*/ + +#include + +#ifdef NEEDS_NL_LANGINFO + +#define Uses_CLY_nl_langinfo +#define Uses_string +#define Uses_stdlib +#define Uses_stdio // OW needs it +#include +#include + +char *CLY_nl_langinfo(nl_item item) +{ + static char *OldLocale=0; + static struct lconv *locales; + char *ret=""; + char *NewLocale; + + /* Is that really needed? */ + /* Get the locales and retain it */ + if (!OldLocale) + { + OldLocale=strdup(setlocale(LC_ALL,NULL)); + locales=localeconv(); + } + else + { + NewLocale=setlocale(LC_ALL,NULL); + if (strcmp(NewLocale,OldLocale)) + { + free(OldLocale); + OldLocale=strdup(NewLocale); + locales=localeconv(); + } + } + + switch (item) + { + #define C(a,b) case a: ret=locales->b; break; + C(CURRENCY_SYMBOL,currency_symbol) + C(DECIMAL_POINT,decimal_point) + C(GROUPING,grouping) + C(INT_CURR_SYMBOL,int_curr_symbol) + C(MON_DECIMAL_POINT,mon_decimal_point) + C(MON_GROUPING,mon_grouping) + C(NEGATIVE_SIGN,negative_sign) + C(POSITIVE_SIGN,positive_sign) + C(THOUSANDS_SEP,thousands_sep) + #undef C + #define C(a,b) case a: ret=&locales->b; break; + C(FRAC_DIGITS ,frac_digits) + C(INT_FRAC_DIGITS,int_frac_digits) + C(N_CS_PRECEDES ,n_cs_precedes) + C(N_SEP_BY_SPACE ,n_sep_by_space) + C(P_SIGN_POSN ,p_sign_posn) + C(N_SIGN_POSN ,n_sign_posn) + C(P_CS_PRECEDES ,p_cs_precedes) + C(P_SEP_BY_SPACE ,p_sep_by_space) + #undef C + } + + return ret; +} + +#endif // NEEDS_NL_LANGINFO + diff --git a/tvision/compat/ntdirent.c b/tvision/compat/ntdirent.c new file mode 100644 index 0000000..c8820a7 --- /dev/null +++ b/tvision/compat/ntdirent.c @@ -0,0 +1,161 @@ +/* vi: set ts=8 sw=4 : */ +/********************************************************************\ +*File : ntdirent.c +* +*Subject: +* Win32 implementation of Unix directory functions +* +*Authors: +* SAA Anatoli Soltan +* +*HISTORY: +* Feb 18 1997 SAA implemented opendir, readdir, closedir +* Sep 14 1999 SAA changed _alloca to alloca to make mingw32 work +* Mar 15 2000 SAA check for alloca definition to make it work +* on BCB +*********************************************************************/ +#include + +#ifdef NEEDS_OPENDIR + +#include +#include +#include +#include +#include +#include +#include + +#ifndef TVComp_GCC + #ifndef alloca + #define alloca _alloca + #endif +#else + #if (__MINGW32_MAJOR_VERSION>=2) && !defined(alloca) + #define alloca __builtin_alloca + #endif +#endif + +#ifndef S_IFDIR +#ifdef _S_IFDIR +#define S_IFDIR _S_IFDIR +#endif +#endif + +struct _DIR +{ + long _sig; /* structure's signature */ + long _findh; /* find handle */ + struct dirent _dirent; /* storage for readdir */ + struct _finddata_t _data; /* buffer for _findnext */ + int _status; /* status of previos _findnext */ +}; + +#define _DIR_SIGNATURE 0xDEDEEDED + + +DIR* opendir(const char* name) +{ + size_t len; + char* path; + DIR* dir = NULL; + struct stat dirstat; + + /* name is NULL */ + if (!name) { + errno = ENOENT; + return NULL; + } + + path = (char*)name; + while (isspace(*path)) path++; + + /* name is empty string */ + if (!*path) { + errno = ENOENT; + return NULL; + } + + /* add "*" mask to the dir name */ + len = strlen(name); + path = (char *)alloca(len + 5); + strcpy(path, name); + if (path[len-1] == '/' || path[len-1] == '\\') + strcpy(path + len, "*"); + else + strcpy(path + len, "\\*"); + + /* name is not exist */ + if (stat(name, &dirstat)) + return NULL; + + /* name is not a directory */ + if (!(dirstat.st_mode & S_IFDIR)) { + errno = ENOTDIR; + return NULL; + } + + /* alloc DIR structure */ + dir = (DIR*)malloc(sizeof(DIR)); + if (!dir) { + errno = ENOMEM; + return NULL; + } + + /* initialize DIR structure */ + dir->_sig = _DIR_SIGNATURE; + /* do first find */ + dir->_findh = _findfirst(path, &dir->_data); + if (dir->_findh == -1) + dir->_status = 0; + else + dir->_status = 1; + + return dir; +} + + +struct dirent* readdir(DIR* dir) +{ + int e; + /* bad DIR pointer */ + if (!dir || dir->_sig != (int)_DIR_SIGNATURE) { + errno = EBADF; + return NULL; + } + + /* previos _findfirst or _findnext failed */ + if (!dir->_status) { + return NULL; + } + + /* copy previosly found name */ + strcpy(dir->_dirent.d_name, dir->_data.name); + + /* do next find */ + e = errno; + if (_findnext(dir->_findh, &dir->_data)) { + errno = e; + dir->_status = 0; + } + + return &dir->_dirent; +} + + +int closedir(DIR* dir) +{ + /* bad DIR pointer */ + if (!dir || dir->_sig != (int)_DIR_SIGNATURE) { + errno = EBADF; + return -1; + } + + /* close find handle */ + if (dir->_findh != -1) + _findclose(dir->_findh); + free(dir); + + return 0; +} +#endif /* NEEDS_OPENDIR */ diff --git a/tvision/compat/obj/delete.me b/tvision/compat/obj/delete.me new file mode 100644 index 0000000..13340a4 --- /dev/null +++ b/tvision/compat/obj/delete.me @@ -0,0 +1,2 @@ +Delete this file, is here just to include this directory in the package. +I know that's need for some un/compressors and is needed by my scripts too. diff --git a/tvision/compat/pathvalid.c b/tvision/compat/pathvalid.c new file mode 100644 index 0000000..e610d68 --- /dev/null +++ b/tvision/compat/pathvalid.c @@ -0,0 +1,62 @@ +/* + Copyright (C) 1996-1998 Robert H”hne + Copyright (C) 2000 Anatoli Soltan + Copyright (C) 2000 Salvador E. Tropea + Covered by the GPL license. +*/ + +#define Uses_string +#define Uses_limits +#include + +// CheckOnlyDrive(dir) and CheckDriveValid(a) +#if CLY_HaveDriveLetters +#define CheckOnlyDrive(dir) if (!unc && strlen(dir)<=3)\ + return CLY_DriveValid(dir[0]) +#define CheckDriveValid(a) if (!unc && !CLY_DriveValid(dir[0]))\ + return 0; +#define DeclareUNCVar int unc=0 +#endif +// By default is a nop +#ifndef CheckOnlyDrive +#define CheckOnlyDrive(dir) +#endif +#ifndef CheckDriveValid +#define CheckDriveValid(a) +#endif +#ifndef DeclareUNCVar +#define DeclareUNCVar +#endif + +// CheckUNC(path) +#ifdef TVComp_BCPP +#define CheckUNC(path) \ + unc = CLY_IsUNC(path); \ + if (unc && CLY_IsUNCShare(path)) \ + return 1 +#endif +// By default is a nop +#ifndef CheckUNC +#define CheckUNC(path) +#endif + +int CLY_PathValid(const char *path) +{ + char dir[PATH_MAX]; + char name[PATH_MAX]; + DeclareUNCVar; + + // Set UNC variable and return if that's an UNC path + CheckUNC(path); + CLY_ExpandPath(path, dir, name); + // return True if that's just a valid drive letter + CheckOnlyDrive(dir); + // Force it to look like a directory + if (*dir && dir[strlen(dir)-1]==DIRSEPARATOR) + strcat(dir,"."); + else + strcat(dir,DIRSEPARATOR_"."); + // return False if the drive letter is invalid + CheckDriveValid(dir[0]); + return CLY_IsDir(dir); +} diff --git a/tvision/compat/regex.c b/tvision/compat/regex.c new file mode 100644 index 0000000..e1c77ed --- /dev/null +++ b/tvision/compat/regex.c @@ -0,0 +1,4973 @@ +/* Extended regular expression matching and search library, + version 0.12. + (Implements POSIX draft P10003.2/D11.2, except for + internationalization features.) + + Copyright (C) 1993 Free Software Foundation, Inc. + + 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, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include + +#ifdef NEEDS_REGEX +/* AIX requires this to be the first thing in the file. */ +#if defined (_AIX) && !defined (REGEX_MALLOC) + #pragma alloca +#endif + +#if defined(TVCompf_MinGW) || defined(TVComp_BCPP) || defined(TVComp_MSC) +#define STDC_HEADERS 1 +#endif + +#define _GNU_SOURCE + +/* We need this for `regex.h', and perhaps for the Emacs include files. */ +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* The `emacs' switch turns on certain matching commands + that make sense only in Emacs. */ +#ifdef emacs + +#include "lisp.h" +#include "buffer.h" +#include "syntax.h" + +/* Emacs uses `NULL' as a predicate. */ +#undef NULL + +#else /* not emacs */ + +/* We used to test for `BSTRING' here, but only GCC and Emacs define + `BSTRING', as far as I know, and neither of them use this code. */ +#if HAVE_STRING_H || STDC_HEADERS +#include +#ifndef bcmp +#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n)) +#endif +#ifndef bcopy +#define bcopy(s, d, n) memcpy ((d), (s), (n)) +#endif +#ifndef bzero +#define bzero(s, n) memset ((s), 0, (n)) +#endif +#else +#include +#endif + +#ifdef STDC_HEADERS +#include +#else +char *malloc (); +char *realloc (); +#endif + +#ifdef TVComp_BCPP +#pragma option push -w-dpu -w-pro -w-csu +#include +#endif + +static void init_syntax_once (); + +/* Define the syntax stuff for \<, \>, etc. */ + +/* This must be nonzero for the wordchar and notwordchar pattern + commands in re_match_2. */ +#ifndef Sword +#define Sword 1 +#endif + +#ifdef SYNTAX_TABLE + +extern char *re_syntax_table; + +#else /* not SYNTAX_TABLE */ + +/* How many characters in the character set. */ +#define CHAR_SET_SIZE 256 + +static char re_syntax_table[CHAR_SET_SIZE]; + +static void +init_syntax_once () +{ + register int c; + static int done = 0; + + if (done) + return; + + bzero (re_syntax_table, sizeof re_syntax_table); + + for (c = 'a'; c <= 'z'; c++) + re_syntax_table[c] = Sword; + + for (c = 'A'; c <= 'Z'; c++) + re_syntax_table[c] = Sword; + + for (c = '0'; c <= '9'; c++) + re_syntax_table[c] = Sword; + + re_syntax_table['_'] = Sword; + + done = 1; +} + +#endif /* not SYNTAX_TABLE */ + +#define SYNTAX(c) re_syntax_table[c] + +#endif /* not emacs */ + +/* Get the interface, including the syntax bits. */ +#include + +/* isalpha etc. are used for the character classes. */ +#include + +#ifndef isascii +#define isascii(c) 1 +#endif + +#ifdef isblank +#define ISBLANK(c) (isascii (c) && isblank (c)) +#else +#define ISBLANK(c) ((c) == ' ' || (c) == '\t') +#endif +#ifdef isgraph +#define ISGRAPH(c) (isascii (c) && isgraph (c)) +#else +#define ISGRAPH(c) (isascii (c) && isprint (c) && !isspace (c)) +#endif + +#define ISPRINT(c) (isascii (c) && isprint (c)) +#define ISDIGIT(c) (isascii (c) && isdigit (c)) +#define ISALNUM(c) (isascii (c) && isalnum (c)) +#define ISALPHA(c) (isascii (c) && isalpha (c)) +#define ISCNTRL(c) (isascii (c) && iscntrl (c)) +#define ISLOWER(c) (isascii (c) && islower (c)) +#define ISPUNCT(c) (isascii (c) && ispunct (c)) +#define ISSPACE(c) (isascii (c) && isspace (c)) +#define ISUPPER(c) (isascii (c) && isupper (c)) +#define ISXDIGIT(c) (isascii (c) && isxdigit (c)) + +#ifndef NULL +#define NULL 0 +#endif + +/* We remove any previous definition of `SIGN_EXTEND_CHAR', + since ours (we hope) works properly with all combinations of + machines, compilers, `char' and `unsigned char' argument types. + (Per Bothner suggested the basic approach.) */ +#undef SIGN_EXTEND_CHAR +#if __STDC__ +#define SIGN_EXTEND_CHAR(c) ((signed char) (c)) +#else /* not __STDC__ */ +/* As in Harbison and Steele. */ +#define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) +#endif + +/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we + use `alloca' instead of `malloc'. This is because using malloc in + re_search* or re_match* could cause memory leaks when C-g is used in + Emacs; also, malloc is slower and causes storage fragmentation. On + the other hand, malloc is more portable, and easier to debug. + + Because we sometimes use alloca, some routines have to be macros, + not functions -- `alloca'-allocated space disappears at the end of the + function it is called in. */ + +#if (__MINGW32_MAJOR_VERSION>=2) && !defined(alloca) + #define alloca __builtin_alloca +#endif + +#ifdef REGEX_MALLOC + +#define REGEX_ALLOCATE malloc +#define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize) + +#else /* not REGEX_MALLOC */ + +/* Emacs already defines alloca, sometimes. */ +#ifndef alloca + +/* Make alloca work the best possible way. */ +#ifdef TVComp_GCC +#define alloca __builtin_alloca +#else /* not TVComp_GCC */ +#if HAVE_ALLOCA_H +#include +#else /* not TVComp_GCC or HAVE_ALLOCA_H */ +#ifndef _AIX /* Already did AIX, up at the top. */ + #if defined(TVComp_MSC) + #include + #ifndef alloca + #define alloca(a) _alloca(a) + #endif // alloca + #else + char *alloca(); + #endif +#endif /* not _AIX */ +#endif /* not HAVE_ALLOCA_H */ +#endif /* not TVComp_GCC */ + +#endif /* not alloca */ + +#define REGEX_ALLOCATE alloca + +/* Assumes a `char *destination' variable. */ +#define REGEX_REALLOCATE(source, osize, nsize) \ + (destination = (char *) alloca (nsize), \ + bcopy (source, destination, osize), \ + destination) + +#endif /* not REGEX_MALLOC */ + + +/* True if `size1' is non-NULL and PTR is pointing anywhere inside + `string1' or just past its end. This works if PTR is NULL, which is + a good thing. */ +#define FIRST_STRING_P(ptr) \ + (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) + +/* (Re)Allocate N items of type T using malloc, or fail. */ +#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) +#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) +#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) + +#define BYTEWIDTH 8 /* In bits. */ + +#define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +typedef char boolean; +#define false 0 +#define true 1 + +/* These are the command codes that appear in compiled regular + expressions. Some opcodes are followed by argument bytes. A + command code can specify any interpretation whatsoever for its + arguments. Zero bytes may appear in the compiled regular expression. + + The value of `exactn' is needed in search.c (search_buffer) in Emacs. + So regex.h defines a symbol `RE_EXACTN_VALUE' to be 1; the value of + `exactn' we use here must also be 1. */ + +typedef enum +{ + no_op = 0, + + /* Followed by one byte giving n, then by n literal bytes. */ + exactn = 1, + + /* Matches any (more or less) character. */ + anychar, + + /* Matches any one char belonging to specified set. First + following byte is number of bitmap bytes. Then come bytes + for a bitmap saying which chars are in. Bits in each byte + are ordered low-bit-first. A character is in the set if its + bit is 1. A character too large to have a bit in the map is + automatically not in the set. */ + charset, + + /* Same parameters as charset, but match any character that is + not one of those specified. */ + charset_not, + + /* Start remembering the text that is matched, for storing in a + register. Followed by one byte with the register number, in + the range 0 to one less than the pattern buffer's re_nsub + field. Then followed by one byte with the number of groups + inner to this one. (This last has to be part of the + start_memory only because we need it in the on_failure_jump + of re_match_2.) */ + start_memory, + + /* Stop remembering the text that is matched and store it in a + memory register. Followed by one byte with the register + number, in the range 0 to one less than `re_nsub' in the + pattern buffer, and one byte with the number of inner groups, + just like `start_memory'. (We need the number of inner + groups here because we don't have any easy way of finding the + corresponding start_memory when we're at a stop_memory.) */ + stop_memory, + + /* Match a duplicate of something remembered. Followed by one + byte containing the register number. */ + duplicate, + + /* Fail unless at beginning of line. */ + begline, + + /* Fail unless at end of line. */ + endline, + + /* Succeeds if at beginning of buffer (if emacs) or at beginning + of string to be matched (if not). */ + begbuf, + + /* Analogously, for end of buffer/string. */ + endbuf, + + /* Followed by two byte relative address to which to jump. */ + jump, + + /* Same as jump, but marks the end of an alternative. */ + jump_past_alt, + + /* Followed by two-byte relative address of place to resume at + in case of failure. */ + on_failure_jump, + + /* Like on_failure_jump, but pushes a placeholder instead of the + current string position when executed. */ + on_failure_keep_string_jump, + + /* Throw away latest failure point and then jump to following + two-byte relative address. */ + pop_failure_jump, + + /* Change to pop_failure_jump if know won't have to backtrack to + match; otherwise change to jump. This is used to jump + back to the beginning of a repeat. If what follows this jump + clearly won't match what the repeat does, such that we can be + sure that there is no use backtracking out of repetitions + already matched, then we change it to a pop_failure_jump. + Followed by two-byte address. */ + maybe_pop_jump, + + /* Jump to following two-byte address, and push a dummy failure + point. This failure point will be thrown away if an attempt + is made to use it for a failure. A `+' construct makes this + before the first repeat. Also used as an intermediary kind + of jump when compiling an alternative. */ + dummy_failure_jump, + + /* Push a dummy failure point and continue. Used at the end of + alternatives. */ + push_dummy_failure, + + /* Followed by two-byte relative address and two-byte number n. + After matching N times, jump to the address upon failure. */ + succeed_n, + + /* Followed by two-byte relative address, and two-byte number n. + Jump to the address N times, then fail. */ + jump_n, + + /* Set the following two-byte relative address to the + subsequent two-byte number. The address *includes* the two + bytes of number. */ + set_number_at, + + wordchar, /* Matches any word-constituent character. */ + notwordchar, /* Matches any char that is not a word-constituent. */ + + wordbeg, /* Succeeds if at word beginning. */ + wordend, /* Succeeds if at word end. */ + + wordbound, /* Succeeds if at a word boundary. */ + notwordbound /* Succeeds if not at a word boundary. */ + +#ifdef emacs + ,before_dot, /* Succeeds if before point. */ + at_dot, /* Succeeds if at point. */ + after_dot, /* Succeeds if after point. */ + + /* Matches any character whose syntax is specified. Followed by + a byte which contains a syntax code, e.g., Sword. */ + syntaxspec, + + /* Matches any character whose syntax is not that specified. */ + notsyntaxspec +#endif /* emacs */ +} re_opcode_t; + +/* Common operations on the compiled pattern. */ + +/* Store NUMBER in two contiguous bytes starting at DESTINATION. */ + +#define STORE_NUMBER(destination, number) \ + do { \ + (destination)[0] = (number) & 0377; \ + (destination)[1] = (number) >> 8; \ + } while (0) + +/* Same as STORE_NUMBER, except increment DESTINATION to + the byte after where the number is stored. Therefore, DESTINATION + must be an lvalue. */ + +#define STORE_NUMBER_AND_INCR(destination, number) \ + do { \ + STORE_NUMBER (destination, number); \ + (destination) += 2; \ + } while (0) + +/* Put into DESTINATION a number stored in two contiguous bytes starting + at SOURCE. */ + +#define EXTRACT_NUMBER(destination, source) \ + do { \ + (destination) = *(source) & 0377; \ + (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \ + } while (0) + +#ifdef DEBUG +static void +extract_number (dest, source) + int *dest; + unsigned char *source; +{ + int temp = SIGN_EXTEND_CHAR (*(source + 1)); + *dest = *source & 0377; + *dest += temp << 8; +} + +#ifndef EXTRACT_MACROS /* To debug the macros. */ +#undef EXTRACT_NUMBER +#define EXTRACT_NUMBER(dest, src) extract_number (&dest, src) +#endif /* not EXTRACT_MACROS */ + +#endif /* DEBUG */ + +/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. + SOURCE must be an lvalue. */ + +#define EXTRACT_NUMBER_AND_INCR(destination, source) \ + do { \ + EXTRACT_NUMBER (destination, source); \ + (source) += 2; \ + } while (0) + +#ifdef DEBUG +static void +extract_number_and_incr (destination, source) + int *destination; + unsigned char **source; +{ + extract_number (destination, *source); + *source += 2; +} + +#ifndef EXTRACT_MACROS +#undef EXTRACT_NUMBER_AND_INCR +#define EXTRACT_NUMBER_AND_INCR(dest, src) \ + extract_number_and_incr (&dest, &src) +#endif /* not EXTRACT_MACROS */ + +#endif /* DEBUG */ + +/* If DEBUG is defined, Regex prints many voluminous messages about what + it is doing (if the variable `debug' is nonzero). If linked with the + main program in `iregex.c', you can enter patterns and strings + interactively. And if linked with the main program in `main.c' and + the other test files, you can run the already-written tests. */ + +#ifdef DEBUG + +/* We use standard I/O for debugging. */ +#include + +/* It is useful to test things that ``must'' be true when debugging. */ +#include + +static int debug = 0; + +#define DEBUG_STATEMENT(e) e +#define DEBUG_PRINT1(x) if (debug) printf (x) +#define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2) +#define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3) +#define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4) +#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ + if (debug) print_partial_compiled_pattern (s, e) +#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ + if (debug) print_double_string (w, s1, sz1, s2, sz2) + + +extern void printchar (); + +/* Print the fastmap in human-readable form. */ + +void +print_fastmap (fastmap) + char *fastmap; +{ + unsigned was_a_range = 0; + unsigned i = 0; + + while (i < (1 << BYTEWIDTH)) + { + if (fastmap[i++]) + { + was_a_range = 0; + printchar (i - 1); + while (i < (1 << BYTEWIDTH) && fastmap[i]) + { + was_a_range = 1; + i++; + } + if (was_a_range) + { + printf ("-"); + printchar (i - 1); + } + } + } + putchar ('\n'); +} + + +/* Print a compiled pattern string in human-readable form, starting at + the START pointer into it and ending just before the pointer END. */ + +void +print_partial_compiled_pattern (start, end) + unsigned char *start; + unsigned char *end; +{ + int mcnt, mcnt2; + unsigned char *p = start; + unsigned char *pend = end; + + if (start == NULL) + { + printf ("(null)\n"); + return; + } + + /* Loop over pattern commands. */ + while (p < pend) + { + switch ((re_opcode_t) *p++) + { + case no_op: + printf ("/no_op"); + break; + + case exactn: + mcnt = *p++; + printf ("/exactn/%d", mcnt); + do + { + putchar ('/'); + printchar (*p++); + } + while (--mcnt); + break; + + case start_memory: + mcnt = *p++; + printf ("/start_memory/%d/%d", mcnt, *p++); + break; + + case stop_memory: + mcnt = *p++; + printf ("/stop_memory/%d/%d", mcnt, *p++); + break; + + case duplicate: + printf ("/duplicate/%d", *p++); + break; + + case anychar: + printf ("/anychar"); + break; + + case charset: + case charset_not: + { + register int c; + + printf ("/charset%s", + (re_opcode_t) *(p - 1) == charset_not ? "_not" : ""); + + assert (p + *p < pend); + + for (c = 0; c < *p; c++) + { + unsigned bit; + unsigned char map_byte = p[1 + c]; + + putchar ('/'); + + for (bit = 0; bit < BYTEWIDTH; bit++) + if (map_byte & (1 << bit)) + printchar (c * BYTEWIDTH + bit); + } + p += 1 + *p; + break; + } + + case begline: + printf ("/begline"); + break; + + case endline: + printf ("/endline"); + break; + + case on_failure_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/on_failure_jump/0/%d", mcnt); + break; + + case on_failure_keep_string_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/on_failure_keep_string_jump/0/%d", mcnt); + break; + + case dummy_failure_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/dummy_failure_jump/0/%d", mcnt); + break; + + case push_dummy_failure: + printf ("/push_dummy_failure"); + break; + + case maybe_pop_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/maybe_pop_jump/0/%d", mcnt); + break; + + case pop_failure_jump: + extract_number_and_incr (&mcnt, &p); + printf ("/pop_failure_jump/0/%d", mcnt); + break; + + case jump_past_alt: + extract_number_and_incr (&mcnt, &p); + printf ("/jump_past_alt/0/%d", mcnt); + break; + + case jump: + extract_number_and_incr (&mcnt, &p); + printf ("/jump/0/%d", mcnt); + break; + + case succeed_n: + extract_number_and_incr (&mcnt, &p); + extract_number_and_incr (&mcnt2, &p); + printf ("/succeed_n/0/%d/0/%d", mcnt, mcnt2); + break; + + case jump_n: + extract_number_and_incr (&mcnt, &p); + extract_number_and_incr (&mcnt2, &p); + printf ("/jump_n/0/%d/0/%d", mcnt, mcnt2); + break; + + case set_number_at: + extract_number_and_incr (&mcnt, &p); + extract_number_and_incr (&mcnt2, &p); + printf ("/set_number_at/0/%d/0/%d", mcnt, mcnt2); + break; + + case wordbound: + printf ("/wordbound"); + break; + + case notwordbound: + printf ("/notwordbound"); + break; + + case wordbeg: + printf ("/wordbeg"); + break; + + case wordend: + printf ("/wordend"); + +#ifdef emacs + case before_dot: + printf ("/before_dot"); + break; + + case at_dot: + printf ("/at_dot"); + break; + + case after_dot: + printf ("/after_dot"); + break; + + case syntaxspec: + printf ("/syntaxspec"); + mcnt = *p++; + printf ("/%d", mcnt); + break; + + case notsyntaxspec: + printf ("/notsyntaxspec"); + mcnt = *p++; + printf ("/%d", mcnt); + break; +#endif /* emacs */ + + case wordchar: + printf ("/wordchar"); + break; + + case notwordchar: + printf ("/notwordchar"); + break; + + case begbuf: + printf ("/begbuf"); + break; + + case endbuf: + printf ("/endbuf"); + break; + + default: + printf ("?%d", *(p-1)); + } + } + printf ("/\n"); +} + + +void +print_compiled_pattern (bufp) + struct re_pattern_buffer *bufp; +{ + unsigned char *buffer = bufp->buffer; + + print_partial_compiled_pattern (buffer, buffer + bufp->used); + printf ("%d bytes used/%d bytes allocated.\n", bufp->used, bufp->allocated); + + if (bufp->fastmap_accurate && bufp->fastmap) + { + printf ("fastmap: "); + print_fastmap (bufp->fastmap); + } + + printf ("re_nsub: %d\t", bufp->re_nsub); + printf ("regs_alloc: %d\t", bufp->regs_allocated); + printf ("can_be_null: %d\t", bufp->can_be_null); + printf ("newline_anchor: %d\n", bufp->newline_anchor); + printf ("no_sub: %d\t", bufp->no_sub); + printf ("not_bol: %d\t", bufp->not_bol); + printf ("not_eol: %d\t", bufp->not_eol); + printf ("syntax: %d\n", bufp->syntax); + /* Perhaps we should print the translate table? */ +} + + +void +print_double_string (where, string1, size1, string2, size2) + const char *where; + const char *string1; + const char *string2; + int size1; + int size2; +{ + unsigned this_char; + + if (where == NULL) + printf ("(null)"); + else + { + if (FIRST_STRING_P (where)) + { + for (this_char = where - string1; this_char < size1; this_char++) + printchar (string1[this_char]); + + where = string2; + } + + for (this_char = where - string2; this_char < size2; this_char++) + printchar (string2[this_char]); + } +} + +#else /* not DEBUG */ + +#undef assert +#define assert(e) + +#define DEBUG_STATEMENT(e) +#define DEBUG_PRINT1(x) +#define DEBUG_PRINT2(x1, x2) +#define DEBUG_PRINT3(x1, x2, x3) +#define DEBUG_PRINT4(x1, x2, x3, x4) +#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) +#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) + +#endif /* not DEBUG */ + +/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can + also be assigned to arbitrarily: each pattern buffer stores its own + syntax, so it can be changed between regex compilations. */ +reg_syntax_t re_syntax_options = RE_SYNTAX_EMACS; + + +/* Specify the precise syntax of regexps for compilation. This provides + for compatibility for various utilities which historically have + different, incompatible syntaxes. + + The argument SYNTAX is a bit mask comprised of the various bits + defined in regex.h. We return the old syntax. */ + +reg_syntax_t +re_set_syntax ( reg_syntax_t syntax ) +{ + reg_syntax_t ret = re_syntax_options; + + re_syntax_options = syntax; + return ret; +} + +/* This table gives an error message for each of the error codes listed + in regex.h. Obviously the order here has to be same as there. */ + +static const char *re_error_msg[] = + { NULL, /* REG_NOERROR */ + "No match", /* REG_NOMATCH */ + "Invalid regular expression", /* REG_BADPAT */ + "Invalid collation character", /* REG_ECOLLATE */ + "Invalid character class name", /* REG_ECTYPE */ + "Trailing backslash", /* REG_EESCAPE */ + "Invalid back reference", /* REG_ESUBREG */ + "Unmatched [ or [^", /* REG_EBRACK */ + "Unmatched ( or \\(", /* REG_EPAREN */ + "Unmatched \\{", /* REG_EBRACE */ + "Invalid content of \\{\\}", /* REG_BADBR */ + "Invalid range end", /* REG_ERANGE */ + "Memory exhausted", /* REG_ESPACE */ + "Invalid preceding regular expression", /* REG_BADRPT */ + "Premature end of regular expression", /* REG_EEND */ + "Regular expression too big", /* REG_ESIZE */ + "Unmatched ) or \\)", /* REG_ERPAREN */ + }; + +/* Subroutine declarations and macros for regex_compile. */ + +//static void store_op1 (); +static void +store_op1 ( re_opcode_t op, unsigned char *loc, int arg ); + +//static void store_op2 (); +static void +store_op2 ( re_opcode_t op, unsigned char *loc, int arg1, int arg2 ); + +//static void insert_op1 (); +static void +insert_op1 ( re_opcode_t op, unsigned char *loc, int arg, + unsigned char *end ); + +//static void insert_op2 (); +static void +insert_op2 ( re_opcode_t op, unsigned char *loc, int arg1, int arg2, + unsigned char *end ); + +//static boolean at_begline_loc_p (); +static boolean +at_begline_loc_p ( const char *pattern, const char *p, + reg_syntax_t syntax ); + +//static boolean at_endline_loc_p (); +static boolean +at_endline_loc_p (const char *p, const char *pend, int syntax ); + +//static reg_errcode_t compile_range (); +static reg_errcode_t +compile_range ( const char **p_ptr, const char *pend, + char *translate, reg_syntax_t syntax, unsigned char *b ); + + +/* Fetch the next character in the uncompiled pattern---translating it + if necessary. Also cast from a signed character in the constant + string passed to us by the user to an unsigned char that we can use + as an array index (in, e.g., `translate'). */ +#define PATFETCH(c) \ + do {if (p == pend) return REG_EEND; \ + c = (unsigned char) *p++; \ + if (translate) c = translate[c]; \ + } while (0) + +/* Fetch the next character in the uncompiled pattern, with no + translation. */ +#define PATFETCH_RAW(c) \ + do {if (p == pend) return REG_EEND; \ + c = (unsigned char) *p++; \ + } while (0) + +/* Go backwards one character in the pattern. */ +#define PATUNFETCH p-- + + +/* If `translate' is non-null, return translate[D], else just D. We + cast the subscript to translate because some data is declared as + `char *', to avoid warnings when a string constant is passed. But + when we use a character as a subscript we must make it unsigned. */ +#define TRANSLATE(d) (translate ? translate[(unsigned char) (d)] : (d)) + + +/* Macros for outputting the compiled pattern into `buffer'. */ + +/* If the buffer isn't allocated when it comes in, use this. */ +#define INIT_BUF_SIZE 32 + +/* Make sure we have at least N more bytes of space in buffer. */ +#define GET_BUFFER_SPACE(n) \ + while (b - bufp->buffer + (n) > bufp->allocated) \ + EXTEND_BUFFER () + +/* Make sure we have one more byte of buffer space and then add C to it. */ +#define BUF_PUSH(c) \ + do { \ + GET_BUFFER_SPACE (1); \ + *b++ = (unsigned char) (c); \ + } while (0) + + +/* Ensure we have two more bytes of buffer space and then append C1 and C2. */ +#define BUF_PUSH_2(c1, c2) \ + do { \ + GET_BUFFER_SPACE (2); \ + *b++ = (unsigned char) (c1); \ + *b++ = (unsigned char) (c2); \ + } while (0) + + +/* As with BUF_PUSH_2, except for three bytes. */ +#define BUF_PUSH_3(c1, c2, c3) \ + do { \ + GET_BUFFER_SPACE (3); \ + *b++ = (unsigned char) (c1); \ + *b++ = (unsigned char) (c2); \ + *b++ = (unsigned char) (c3); \ + } while (0) + + +/* Store a jump with opcode OP at LOC to location TO. We store a + relative address offset by the three bytes the jump itself occupies. */ +#define STORE_JUMP(op, loc, to) \ + store_op1 (op, loc, (to) - (loc) - 3) + +/* Likewise, for a two-argument jump. */ +#define STORE_JUMP2(op, loc, to, arg) \ + store_op2 (op, loc, (to) - (loc) - 3, arg) + +/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */ +#define INSERT_JUMP(op, loc, to) \ + insert_op1 (op, loc, (to) - (loc) - 3, b) + +/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */ +#define INSERT_JUMP2(op, loc, to, arg) \ + insert_op2 (op, loc, (to) - (loc) - 3, arg, b) + + +/* This is not an arbitrary limit: the arguments which represent offsets + into the pattern are two bytes long. So if 2^16 bytes turns out to + be too small, many things would have to change. */ +#define MAX_BUF_SIZE (1L << 16) + + +/* Extend the buffer by twice its current size via realloc and + reset the pointers that pointed into the old block to point to the + correct places in the new one. If extending the buffer results in it + being larger than MAX_BUF_SIZE, then flag memory exhausted. */ +#define EXTEND_BUFFER() \ + do { \ + unsigned char *old_buffer = bufp->buffer; \ + if (bufp->allocated == MAX_BUF_SIZE) \ + return REG_ESIZE; \ + bufp->allocated <<= 1; \ + if (bufp->allocated > MAX_BUF_SIZE) \ + bufp->allocated = MAX_BUF_SIZE; \ + bufp->buffer = (unsigned char *) realloc (bufp->buffer, bufp->allocated);\ + if (bufp->buffer == NULL) \ + return REG_ESPACE; \ + /* If the buffer moved, move all the pointers into it. */ \ + if (old_buffer != bufp->buffer) \ + { \ + b = (b - old_buffer) + bufp->buffer; \ + begalt = (begalt - old_buffer) + bufp->buffer; \ + if (fixup_alt_jump) \ + fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\ + if (laststart) \ + laststart = (laststart - old_buffer) + bufp->buffer; \ + if (pending_exact) \ + pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ + } \ + } while (0) + + +/* Since we have one byte reserved for the register number argument to + {start,stop}_memory, the maximum number of groups we can report + things about is what fits in that byte. */ +#define MAX_REGNUM 255 + +/* But patterns can have more than `MAX_REGNUM' registers. We just + ignore the excess. */ +typedef unsigned regnum_t; + + +/* Macros for the compile stack. */ + +/* Since offsets can go either forwards or backwards, this type needs to + be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */ +typedef int pattern_offset_t; + +typedef struct +{ + pattern_offset_t begalt_offset; + pattern_offset_t fixup_alt_jump; + pattern_offset_t inner_group_offset; + pattern_offset_t laststart_offset; + regnum_t regnum; +} compile_stack_elt_t; + + +typedef struct +{ + compile_stack_elt_t *stack; + unsigned size; + unsigned avail; /* Offset of next open position. */ +} compile_stack_type; + +//static boolean group_in_compile_stack (); +static boolean +group_in_compile_stack ( compile_stack_type compile_stack, regnum_t regnum ); + +#define INIT_COMPILE_STACK_SIZE 32 + +#define COMPILE_STACK_EMPTY (compile_stack.avail == 0) +#define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size) + +/* The next available element. */ +#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail]) + + +/* Set the bit for character C in a list. */ +#define SET_LIST_BIT(c) \ + (b[((unsigned char) (c)) / BYTEWIDTH] \ + |= 1 << (((unsigned char) c) % BYTEWIDTH)) + + +/* Get the next unsigned number in the uncompiled pattern. */ +#define GET_UNSIGNED_NUMBER(num) \ + { if (p != pend) \ + { \ + PATFETCH (c); \ + while (ISDIGIT (c)) \ + { \ + if (num < 0) \ + num = 0; \ + num = num * 10 + c - '0'; \ + if (p == pend) \ + break; \ + PATFETCH (c); \ + } \ + } \ + } + +#define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ + +#define IS_CHAR_CLASS(string) \ + (STREQ (string, "alpha") || STREQ (string, "upper") \ + || STREQ (string, "lower") || STREQ (string, "digit") \ + || STREQ (string, "alnum") || STREQ (string, "xdigit") \ + || STREQ (string, "space") || STREQ (string, "print") \ + || STREQ (string, "punct") || STREQ (string, "graph") \ + || STREQ (string, "cntrl") || STREQ (string, "blank")) + +/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX. + Returns one of error codes defined in `regex.h', or zero for success. + + Assumes the `allocated' (and perhaps `buffer') and `translate' + fields are set in BUFP on entry. + + If it succeeds, results are put in BUFP (if it returns an error, the + contents of BUFP are undefined): + `buffer' is the compiled pattern; + `syntax' is set to SYNTAX; + `used' is set to the length of the compiled pattern; + `fastmap_accurate' is zero; + `re_nsub' is the number of subexpressions in PATTERN; + `not_bol' and `not_eol' are zero; + + The `fastmap' and `newline_anchor' fields are neither + examined nor set. */ + +static reg_errcode_t +regex_compile ( const char *pattern, + int size, + reg_syntax_t syntax, + struct re_pattern_buffer *bufp ) +{ + /* We fetch characters from PATTERN here. Even though PATTERN is + `char *' (i.e., signed), we declare these variables as unsigned, so + they can be reliably used as array indices. */ + register unsigned char c, c1; + + /* A random tempory spot in PATTERN. */ + const char *p1; + + /* Points to the end of the buffer, where we should append. */ + register unsigned char *b; + + /* Keeps track of unclosed groups. */ + compile_stack_type compile_stack; + + /* Points to the current (ending) position in the pattern. */ + const char *p = pattern; + const char *pend = pattern + size; + + /* How to translate the characters in the pattern. */ + char *translate = bufp->translate; + + /* Address of the count-byte of the most recently inserted `exactn' + command. This makes it possible to tell if a new exact-match + character can be added to that command or if the character requires + a new `exactn' command. */ + unsigned char *pending_exact = 0; + + /* Address of start of the most recently finished expression. + This tells, e.g., postfix * where to find the start of its + operand. Reset at the beginning of groups and alternatives. */ + unsigned char *laststart = 0; + + /* Address of beginning of regexp, or inside of last group. */ + unsigned char *begalt; + + /* Place in the uncompiled pattern (i.e., the {) to + which to go back if the interval is invalid. */ + const char *beg_interval; + + /* Address of the place where a forward jump should go to the end of + the containing expression. Each alternative of an `or' -- except the + last -- ends with a forward jump of this sort. */ + unsigned char *fixup_alt_jump = 0; + + /* Counts open-groups as they are encountered. Remembered for the + matching close-group on the compile stack, so the same register + number is put in the stop_memory as the start_memory. */ + regnum_t regnum = 0; + +#ifdef DEBUG + DEBUG_PRINT1 ("\nCompiling pattern: "); + if (debug) + { + unsigned debug_count; + + for (debug_count = 0; debug_count < size; debug_count++) + printchar (pattern[debug_count]); + putchar ('\n'); + } +#endif /* DEBUG */ + + /* Initialize the compile stack. */ + compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t); + if (compile_stack.stack == NULL) + return REG_ESPACE; + + compile_stack.size = INIT_COMPILE_STACK_SIZE; + compile_stack.avail = 0; + + /* Initialize the pattern buffer. */ + bufp->syntax = syntax; + bufp->fastmap_accurate = 0; + bufp->not_bol = bufp->not_eol = 0; + + /* Set `used' to zero, so that if we return an error, the pattern + printer (for debugging) will think there's no pattern. We reset it + at the end. */ + bufp->used = 0; + + /* Always count groups, whether or not bufp->no_sub is set. */ + bufp->re_nsub = 0; + +#if !defined (emacs) && !defined (SYNTAX_TABLE) + /* Initialize the syntax table. */ + init_syntax_once (); +#endif + + if (bufp->allocated == 0) + { + if (bufp->buffer) + { /* If zero allocated, but buffer is non-null, try to realloc + enough space. This loses if buffer's address is bogus, but + that is the user's responsibility. */ + RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char); + } + else + { /* Caller did not allocate a buffer. Do it for them. */ + bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char); + } + if (!bufp->buffer) return REG_ESPACE; + + bufp->allocated = INIT_BUF_SIZE; + } + + begalt = b = bufp->buffer; + + /* Loop through the uncompiled pattern until we're at the end. */ + while (p != pend) + { + PATFETCH (c); + + switch (c) + { + case '^': + { + if ( /* If at start of pattern, it's an operator. */ + p == pattern + 1 + /* If context independent, it's an operator. */ + || syntax & RE_CONTEXT_INDEP_ANCHORS + /* Otherwise, depends on what's come before. */ + || at_begline_loc_p (pattern, p, syntax)) + BUF_PUSH (begline); + else + goto normal_char; + } + break; + + + case '$': + { + if ( /* If at end of pattern, it's an operator. */ + p == pend + /* If context independent, it's an operator. */ + || syntax & RE_CONTEXT_INDEP_ANCHORS + /* Otherwise, depends on what's next. */ + || at_endline_loc_p (p, pend, syntax)) + BUF_PUSH (endline); + else + goto normal_char; + } + break; + + + case '+': + case '?': + if ((syntax & RE_BK_PLUS_QM) + || (syntax & RE_LIMITED_OPS)) + goto normal_char; + handle_plus: + case '*': + /* If there is no previous pattern... */ + if (!laststart) + { + if (syntax & RE_CONTEXT_INVALID_OPS) + return REG_BADRPT; + else if (!(syntax & RE_CONTEXT_INDEP_OPS)) + goto normal_char; + } + + { + /* Are we optimizing this jump? */ + boolean keep_string_p = false; + + /* 1 means zero (many) matches is allowed. */ + char zero_times_ok = 0, many_times_ok = 0; + + /* If there is a sequence of repetition chars, collapse it + down to just one (the right one). We can't combine + interval operators with these because of, e.g., `a{2}*', + which should only match an even number of `a's. */ + + for (;;) + { + zero_times_ok |= c != '+'; + many_times_ok |= c != '?'; + + if (p == pend) + break; + + PATFETCH (c); + + if (c == '*' + || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?'))) + ; + + else if (syntax & RE_BK_PLUS_QM && c == '\\') + { + if (p == pend) return REG_EESCAPE; + + PATFETCH (c1); + if (!(c1 == '+' || c1 == '?')) + { + PATUNFETCH; + PATUNFETCH; + break; + } + + c = c1; + } + else + { + PATUNFETCH; + break; + } + + /* If we get here, we found another repeat character. */ + } + + /* Star, etc. applied to an empty pattern is equivalent + to an empty pattern. */ + if (!laststart) + break; + + /* Now we know whether or not zero matches is allowed + and also whether or not two or more matches is allowed. */ + if (many_times_ok) + { /* More than one repetition is allowed, so put in at the + end a backward relative jump from `b' to before the next + jump we're going to put in below (which jumps from + laststart to after this jump). + + But if we are at the `*' in the exact sequence `.*\n', + insert an unconditional jump backwards to the ., + instead of the beginning of the loop. This way we only + push a failure point once, instead of every time + through the loop. */ + assert (p - 1 > pattern); + + /* Allocate the space for the jump. */ + GET_BUFFER_SPACE (3); + + /* We know we are not at the first character of the pattern, + because laststart was nonzero. And we've already + incremented `p', by the way, to be the character after + the `*'. Do we have to do something analogous here + for null bytes, because of RE_DOT_NOT_NULL? */ + if (TRANSLATE (*(p - 2)) == TRANSLATE ('.') + && zero_times_ok + && p < pend && TRANSLATE (*p) == TRANSLATE ('\n') + && !(syntax & RE_DOT_NEWLINE)) + { /* We have .*\n. */ + STORE_JUMP (jump, b, laststart); + keep_string_p = true; + } + else + /* Anything else. */ + STORE_JUMP (maybe_pop_jump, b, laststart - 3); + + /* We've added more stuff to the buffer. */ + b += 3; + } + + /* On failure, jump from laststart to b + 3, which will be the + end of the buffer after this jump is inserted. */ + GET_BUFFER_SPACE (3); + INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump + : on_failure_jump, + laststart, b + 3); + pending_exact = 0; + b += 3; + + if (!zero_times_ok) + { + /* At least one repetition is required, so insert a + `dummy_failure_jump' before the initial + `on_failure_jump' instruction of the loop. This + effects a skip over that instruction the first time + we hit that loop. */ + GET_BUFFER_SPACE (3); + INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6); + b += 3; + } + } + break; + + + case '.': + laststart = b; + BUF_PUSH (anychar); + break; + + + case '[': + { + boolean had_char_class = false; + + if (p == pend) return REG_EBRACK; + + /* Ensure that we have enough space to push a charset: the + opcode, the length count, and the bitset; 34 bytes in all. */ + GET_BUFFER_SPACE (34); + + laststart = b; + + /* We test `*p == '^' twice, instead of using an if + statement, so we only need one BUF_PUSH. */ + BUF_PUSH (*p == '^' ? charset_not : charset); + if (*p == '^') + p++; + + /* Remember the first position in the bracket expression. */ + p1 = p; + + /* Push the number of bytes in the bitmap. */ + BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH); + + /* Clear the whole map. */ + bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH); + + /* charset_not matches newline according to a syntax bit. */ + if ((re_opcode_t) b[-2] == charset_not + && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) + SET_LIST_BIT ('\n'); + + /* Read in characters and ranges, setting map bits. */ + for (;;) + { + if (p == pend) return REG_EBRACK; + + PATFETCH (c); + + /* \ might escape characters inside [...] and [^...]. */ + if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') + { + if (p == pend) return REG_EESCAPE; + + PATFETCH (c1); + SET_LIST_BIT (c1); + continue; + } + + /* Could be the end of the bracket expression. If it's + not (i.e., when the bracket expression is `[]' so + far), the ']' character bit gets set way below. */ + if (c == ']' && p != p1 + 1) + break; + + /* Look ahead to see if it's a range when the last thing + was a character class. */ + if (had_char_class && c == '-' && *p != ']') + return REG_ERANGE; + + /* Look ahead to see if it's a range when the last thing + was a character: if this is a hyphen not at the + beginning or the end of a list, then it's the range + operator. */ + if (c == '-' + && !(p - 2 >= pattern && p[-2] == '[') + && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') + && *p != ']') + { + reg_errcode_t ret + = compile_range (&p, pend, translate, syntax, b); + if (ret != REG_NOERROR) return ret; + } + + else if (p[0] == '-' && p[1] != ']') + { /* This handles ranges made up of characters only. */ + reg_errcode_t ret; + + /* Move past the `-'. */ + PATFETCH (c1); + + ret = compile_range (&p, pend, translate, syntax, b); + if (ret != REG_NOERROR) return ret; + } + + /* See if we're at the beginning of a possible character + class. */ + + else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') + { /* Leave room for the null. */ + char str[CHAR_CLASS_MAX_LENGTH + 1]; + + PATFETCH (c); + c1 = 0; + + /* If pattern is `[[:'. */ + if (p == pend) return REG_EBRACK; + + for (;;) + { + PATFETCH (c); + if (c == ':' || c == ']' || p == pend + || c1 == CHAR_CLASS_MAX_LENGTH) + break; + str[c1++] = c; + } + str[c1] = '\0'; + + /* If isn't a word bracketed by `[:' and:`]': + undo the ending character, the letters, and leave + the leading `:' and `[' (but set bits for them). */ + if (c == ':' && *p == ']') + { + int ch; + boolean is_alnum = STREQ (str, "alnum"); + boolean is_alpha = STREQ (str, "alpha"); + boolean is_blank = STREQ (str, "blank"); + boolean is_cntrl = STREQ (str, "cntrl"); + boolean is_digit = STREQ (str, "digit"); + boolean is_graph = STREQ (str, "graph"); + boolean is_lower = STREQ (str, "lower"); + boolean is_print = STREQ (str, "print"); + boolean is_punct = STREQ (str, "punct"); + boolean is_space = STREQ (str, "space"); + boolean is_upper = STREQ (str, "upper"); + boolean is_xdigit = STREQ (str, "xdigit"); + + if (!IS_CHAR_CLASS (str)) return REG_ECTYPE; + + /* Throw away the ] at the end of the character + class. */ + PATFETCH (c); + + if (p == pend) return REG_EBRACK; + + for (ch = 0; ch < 1 << BYTEWIDTH; ch++) + { + if ( (is_alnum && ISALNUM (ch)) + || (is_alpha && ISALPHA (ch)) + || (is_blank && ISBLANK (ch)) + || (is_cntrl && ISCNTRL (ch)) + || (is_digit && ISDIGIT (ch)) + || (is_graph && ISGRAPH (ch)) + || (is_lower && ISLOWER (ch)) + || (is_print && ISPRINT (ch)) + || (is_punct && ISPUNCT (ch)) + || (is_space && ISSPACE (ch)) + || (is_upper && ISUPPER (ch)) + || (is_xdigit && ISXDIGIT (ch))) + SET_LIST_BIT (ch); + } + had_char_class = true; + } + else + { + c1++; + while (c1--) + PATUNFETCH; + SET_LIST_BIT ('['); + SET_LIST_BIT (':'); + had_char_class = false; + } + } + else + { + had_char_class = false; + SET_LIST_BIT (c); + } + } + + /* Discard any (non)matching list bytes that are all 0 at the + end of the map. Decrease the map-length byte too. */ + while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) + b[-1]--; + b += b[-1]; + } + break; + + + case '(': + if (syntax & RE_NO_BK_PARENS) + goto handle_open; + else + goto normal_char; + + + case ')': + if (syntax & RE_NO_BK_PARENS) + goto handle_close; + else + goto normal_char; + + + case '\n': + if (syntax & RE_NEWLINE_ALT) + goto handle_alt; + else + goto normal_char; + + + case '|': + if (syntax & RE_NO_BK_VBAR) + goto handle_alt; + else + goto normal_char; + + + case '{': + if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES) + goto handle_interval; + else + goto normal_char; + + + case '\\': + if (p == pend) return REG_EESCAPE; + + /* Do not translate the character after the \, so that we can + distinguish, e.g., \B from \b, even if we normally would + translate, e.g., B to b. */ + PATFETCH_RAW (c); + + switch (c) + { + case '(': + if (syntax & RE_NO_BK_PARENS) + goto normal_backslash; + + handle_open: + bufp->re_nsub++; + regnum++; + + if (COMPILE_STACK_FULL) + { + RETALLOC (compile_stack.stack, compile_stack.size << 1, + compile_stack_elt_t); + if (compile_stack.stack == NULL) return REG_ESPACE; + + compile_stack.size <<= 1; + } + + /* These are the values to restore when we hit end of this + group. They are all relative offsets, so that if the + whole pattern moves because of realloc, they will still + be valid. */ + COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer; + COMPILE_STACK_TOP.fixup_alt_jump + = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0; + COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer; + COMPILE_STACK_TOP.regnum = regnum; + + /* We will eventually replace the 0 with the number of + groups inner to this one. But do not push a + start_memory for groups beyond the last one we can + represent in the compiled pattern. */ + if (regnum <= MAX_REGNUM) + { + COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2; + BUF_PUSH_3 (start_memory, regnum, 0); + } + + compile_stack.avail++; + + fixup_alt_jump = 0; + laststart = 0; + begalt = b; + /* If we've reached MAX_REGNUM groups, then this open + won't actually generate any code, so we'll have to + clear pending_exact explicitly. */ + pending_exact = 0; + break; + + + case ')': + if (syntax & RE_NO_BK_PARENS) goto normal_backslash; + + if (COMPILE_STACK_EMPTY) + { + if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) + goto normal_backslash; + else + return REG_ERPAREN; + } + + handle_close: + if (fixup_alt_jump) + { /* Push a dummy failure point at the end of the + alternative for a possible future + `pop_failure_jump' to pop. See comments at + `push_dummy_failure' in `re_match_2'. */ + BUF_PUSH (push_dummy_failure); + + /* We allocated space for this jump when we assigned + to `fixup_alt_jump', in the `handle_alt' case below. */ + STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1); + } + + /* See similar code for backslashed left paren above. */ + if (COMPILE_STACK_EMPTY) + { + if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) + goto normal_char; + else + return REG_ERPAREN; + } + + /* Since we just checked for an empty stack above, this + ``can't happen''. */ + assert (compile_stack.avail != 0); + { + /* We don't just want to restore into `regnum', because + later groups should continue to be numbered higher, + as in `(ab)c(de)' -- the second group is #2. */ + regnum_t this_group_regnum; + + compile_stack.avail--; + begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset; + fixup_alt_jump + = COMPILE_STACK_TOP.fixup_alt_jump + ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1 + : 0; + laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset; + this_group_regnum = COMPILE_STACK_TOP.regnum; + /* If we've reached MAX_REGNUM groups, then this open + won't actually generate any code, so we'll have to + clear pending_exact explicitly. */ + pending_exact = 0; + + /* We're at the end of the group, so now we know how many + groups were inside this one. */ + if (this_group_regnum <= MAX_REGNUM) + { + unsigned char *inner_group_loc + = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset; + + *inner_group_loc = regnum - this_group_regnum; + BUF_PUSH_3 (stop_memory, this_group_regnum, + regnum - this_group_regnum); + } + } + break; + + + case '|': /* `\|'. */ + if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR) + goto normal_backslash; + handle_alt: + if (syntax & RE_LIMITED_OPS) + goto normal_char; + + /* Insert before the previous alternative a jump which + jumps to this alternative if the former fails. */ + GET_BUFFER_SPACE (3); + INSERT_JUMP (on_failure_jump, begalt, b + 6); + pending_exact = 0; + b += 3; + + /* The alternative before this one has a jump after it + which gets executed if it gets matched. Adjust that + jump so it will jump to this alternative's analogous + jump (put in below, which in turn will jump to the next + (if any) alternative's such jump, etc.). The last such + jump jumps to the correct final destination. A picture: + _____ _____ + | | | | + | v | v + a | b | c + + If we are at `b', then fixup_alt_jump right now points to a + three-byte space after `a'. We'll put in the jump, set + fixup_alt_jump to right after `b', and leave behind three + bytes which we'll fill in when we get to after `c'. */ + + if (fixup_alt_jump) + STORE_JUMP (jump_past_alt, fixup_alt_jump, b); + + /* Mark and leave space for a jump after this alternative, + to be filled in later either by next alternative or + when know we're at the end of a series of alternatives. */ + fixup_alt_jump = b; + GET_BUFFER_SPACE (3); + b += 3; + + laststart = 0; + begalt = b; + break; + + + case '{': + /* If \{ is a literal. */ + if (!(syntax & RE_INTERVALS) + /* If we're at `\{' and it's not the open-interval + operator. */ + || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) + || (p - 2 == pattern && p == pend)) + goto normal_backslash; + + handle_interval: + { + /* If got here, then the syntax allows intervals. */ + + /* At least (most) this many matches must be made. */ + int lower_bound = -1, upper_bound = -1; + + beg_interval = p - 1; + + if (p == pend) + { + if (syntax & RE_NO_BK_BRACES) + goto unfetch_interval; + else + return REG_EBRACE; + } + + GET_UNSIGNED_NUMBER (lower_bound); + + if (c == ',') + { + GET_UNSIGNED_NUMBER (upper_bound); + if (upper_bound < 0) upper_bound = RE_DUP_MAX; + } + else + /* Interval such as `{1}' => match exactly once. */ + upper_bound = lower_bound; + + if (lower_bound < 0 || upper_bound > RE_DUP_MAX + || lower_bound > upper_bound) + { + if (syntax & RE_NO_BK_BRACES) + goto unfetch_interval; + else + return REG_BADBR; + } + + if (!(syntax & RE_NO_BK_BRACES)) + { + if (c != '\\') return REG_EBRACE; + + PATFETCH (c); + } + + if (c != '}') + { + if (syntax & RE_NO_BK_BRACES) + goto unfetch_interval; + else + return REG_BADBR; + } + + /* We just parsed a valid interval. */ + + /* If it's invalid to have no preceding re. */ + if (!laststart) + { + if (syntax & RE_CONTEXT_INVALID_OPS) + return REG_BADRPT; + else if (syntax & RE_CONTEXT_INDEP_OPS) + laststart = b; + else + goto unfetch_interval; + } + + /* If the upper bound is zero, don't want to succeed at + all; jump from `laststart' to `b + 3', which will be + the end of the buffer after we insert the jump. */ + if (upper_bound == 0) + { + GET_BUFFER_SPACE (3); + INSERT_JUMP (jump, laststart, b + 3); + b += 3; + } + + /* Otherwise, we have a nontrivial interval. When + we're all done, the pattern will look like: + set_number_at + set_number_at + succeed_n + + jump_n + (The upper bound and `jump_n' are omitted if + `upper_bound' is 1, though.) */ + else + { /* If the upper bound is > 1, we need to insert + more at the end of the loop. */ + unsigned nbytes = 10 + (upper_bound > 1) * 10; + + GET_BUFFER_SPACE (nbytes); + + /* Initialize lower bound of the `succeed_n', even + though it will be set during matching by its + attendant `set_number_at' (inserted next), + because `re_compile_fastmap' needs to know. + Jump to the `jump_n' we might insert below. */ + INSERT_JUMP2 (succeed_n, laststart, + b + 5 + (upper_bound > 1) * 5, + lower_bound); + b += 5; + + /* Code to initialize the lower bound. Insert + before the `succeed_n'. The `5' is the last two + bytes of this `set_number_at', plus 3 bytes of + the following `succeed_n'. */ + insert_op2 (set_number_at, laststart, 5, lower_bound, b); + b += 5; + + if (upper_bound > 1) + { /* More than one repetition is allowed, so + append a backward jump to the `succeed_n' + that starts this interval. + + When we've reached this during matching, + we'll have matched the interval once, so + jump back only `upper_bound - 1' times. */ + STORE_JUMP2 (jump_n, b, laststart + 5, + upper_bound - 1); + b += 5; + + /* The location we want to set is the second + parameter of the `jump_n'; that is `b-2' as + an absolute address. `laststart' will be + the `set_number_at' we're about to insert; + `laststart+3' the number to set, the source + for the relative address. But we are + inserting into the middle of the pattern -- + so everything is getting moved up by 5. + Conclusion: (b - 2) - (laststart + 3) + 5, + i.e., b - laststart. + + We insert this at the beginning of the loop + so that if we fail during matching, we'll + reinitialize the bounds. */ + insert_op2 (set_number_at, laststart, b - laststart, + upper_bound - 1, b); + b += 5; + } + } + pending_exact = 0; + beg_interval = NULL; + } + break; + + unfetch_interval: + /* If an invalid interval, match the characters as literals. */ + assert (beg_interval); + p = beg_interval; + beg_interval = NULL; + + /* normal_char and normal_backslash need `c'. */ + PATFETCH (c); + + if (!(syntax & RE_NO_BK_BRACES)) + { + if (p > pattern && p[-1] == '\\') + goto normal_backslash; + } + goto normal_char; + +#ifdef emacs + /* There is no way to specify the before_dot and after_dot + operators. rms says this is ok. --karl */ + case '=': + BUF_PUSH (at_dot); + break; + + case 's': + laststart = b; + PATFETCH (c); + BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]); + break; + + case 'S': + laststart = b; + PATFETCH (c); + BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]); + break; +#endif /* emacs */ + + + case 'w': + laststart = b; + BUF_PUSH (wordchar); + break; + + + case 'W': + laststart = b; + BUF_PUSH (notwordchar); + break; + + + case '<': + BUF_PUSH (wordbeg); + break; + + case '>': + BUF_PUSH (wordend); + break; + + case 'b': + BUF_PUSH (wordbound); + break; + + case 'B': + BUF_PUSH (notwordbound); + break; + + case '`': + BUF_PUSH (begbuf); + break; + + case '\'': + BUF_PUSH (endbuf); + break; + + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + if (syntax & RE_NO_BK_REFS) + goto normal_char; + + c1 = c - '0'; + + if (c1 > regnum) + return REG_ESUBREG; + + /* Can't back reference to a subexpression if inside of it. */ + if (group_in_compile_stack (compile_stack, c1)) + goto normal_char; + + laststart = b; + BUF_PUSH_2 (duplicate, c1); + break; + + + case '+': + case '?': + if (syntax & RE_BK_PLUS_QM) + goto handle_plus; + else + goto normal_backslash; + + default: + normal_backslash: + /* You might think it would be useful for \ to mean + not to translate; but if we don't translate it + it will never match anything. */ + c = TRANSLATE (c); + goto normal_char; + } + break; + + + default: + /* Expects the character in `c'. */ + normal_char: + /* If no exactn currently being built. */ + if (!pending_exact + + /* If last exactn not at current position. */ + || pending_exact + *pending_exact + 1 != b + + /* We have only one byte following the exactn for the count. */ + || *pending_exact == (1 << BYTEWIDTH) - 1 + + /* If followed by a repetition operator. */ + || *p == '*' || *p == '^' + || ((syntax & RE_BK_PLUS_QM) + ? *p == '\\' && (p[1] == '+' || p[1] == '?') + : (*p == '+' || *p == '?')) + || ((syntax & RE_INTERVALS) + && ((syntax & RE_NO_BK_BRACES) + ? *p == '{' + : (p[0] == '\\' && p[1] == '{')))) + { + /* Start building a new exactn. */ + + laststart = b; + + BUF_PUSH_2 (exactn, 0); + pending_exact = b - 1; + } + + BUF_PUSH (c); + (*pending_exact)++; + break; + } /* switch (c) */ + } /* while p != pend */ + + + /* Through the pattern now. */ + + if (fixup_alt_jump) + STORE_JUMP (jump_past_alt, fixup_alt_jump, b); + + if (!COMPILE_STACK_EMPTY) + return REG_EPAREN; + + free (compile_stack.stack); + + /* We have succeeded; set the length of the buffer. */ + bufp->used = b - bufp->buffer; + +#ifdef DEBUG + if (debug) + { + DEBUG_PRINT1 ("\nCompiled pattern: "); + print_compiled_pattern (bufp); + } +#endif /* DEBUG */ + + return REG_NOERROR; +} /* regex_compile */ + +/* Subroutines for `regex_compile'. */ + +/* Store OP at LOC followed by two-byte integer parameter ARG. */ + +static void +store_op1 ( re_opcode_t op, unsigned char *loc, int arg ) +{ + *loc = (unsigned char) op; + STORE_NUMBER (loc + 1, arg); +} + + +/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */ + +static void +store_op2 ( re_opcode_t op, unsigned char *loc, int arg1, int arg2 ) +{ + *loc = (unsigned char) op; + STORE_NUMBER (loc + 1, arg1); + STORE_NUMBER (loc + 3, arg2); +} + + +/* Copy the bytes from LOC to END to open up three bytes of space at LOC + for OP followed by two-byte integer parameter ARG. */ + +static void +insert_op1 ( re_opcode_t op, unsigned char *loc, int arg, + unsigned char *end ) +{ + register unsigned char *pfrom = end; + register unsigned char *pto = end + 3; + + while (pfrom != loc) + *--pto = *--pfrom; + + store_op1 (op, loc, arg); +} + + +/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */ + +static void +insert_op2 ( re_opcode_t op, unsigned char *loc, int arg1, int arg2, + unsigned char *end ) +{ + register unsigned char *pfrom = end; + register unsigned char *pto = end + 5; + + while (pfrom != loc) + *--pto = *--pfrom; + + store_op2 (op, loc, arg1, arg2); +} + + +/* P points to just after a ^ in PATTERN. Return true if that ^ comes + after an alternative or a begin-subexpression. We assume there is at + least one character before the ^. */ + +static boolean +at_begline_loc_p ( const char *pattern, const char *p, + reg_syntax_t syntax ) +{ + const char *prev = p - 2; + boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\'; + + return + /* After a subexpression? */ + (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash)) + /* After an alternative? */ + || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash)); +} + + +/* The dual of at_begline_loc_p. This one is for $. We assume there is + at least one character after the $, i.e., `P < PEND'. */ + +static boolean +at_endline_loc_p (const char *p, const char *pend, + int syntax ) +{ + const char *next = p; + boolean next_backslash = *next == '\\'; + const char *next_next = p + 1 < pend ? p + 1 : NULL; + + return + /* Before a subexpression? */ + (syntax & RE_NO_BK_PARENS ? *next == ')' + : next_backslash && next_next && *next_next == ')') + /* Before an alternative? */ + || (syntax & RE_NO_BK_VBAR ? *next == '|' + : next_backslash && next_next && *next_next == '|'); +} + + +/* Returns true if REGNUM is in one of COMPILE_STACK's elements and + false if it's not. */ + +static boolean +group_in_compile_stack ( compile_stack_type compile_stack, regnum_t regnum ) +{ + int this_element; + + for (this_element = compile_stack.avail - 1; + this_element >= 0; + this_element--) + if (compile_stack.stack[this_element].regnum == regnum) + return true; + + return false; +} + + +/* Read the ending character of a range (in a bracket expression) from the + uncompiled pattern *P_PTR (which ends at PEND). We assume the + starting character is in `P[-2]'. (`P[-1]' is the character `-'.) + Then we set the translation of all bits between the starting and + ending characters (inclusive) in the compiled pattern B. + + Return an error code. + + We use these short variable names so we can use the same macros as + `regex_compile' itself. */ + +static reg_errcode_t +compile_range ( const char **p_ptr, const char *pend, + char *translate, reg_syntax_t syntax, unsigned char *b ) +{ + unsigned this_char; + + const char *p = *p_ptr; + int range_start, range_end; + + if (p == pend) + return REG_ERANGE; + + /* Even though the pattern is a signed `char *', we need to fetch + with unsigned char *'s; if the high bit of the pattern character + is set, the range endpoints will be negative if we fetch using a + signed char *. + + We also want to fetch the endpoints without translating them; the + appropriate translation is done in the bit-setting loop below. */ + range_start = ((unsigned char *) p)[-2]; + range_end = ((unsigned char *) p)[0]; + + /* Have to increment the pointer into the pattern string, so the + caller isn't still at the ending character. */ + (*p_ptr)++; + + /* If the start is after the end, the range is empty. */ + if (range_start > range_end) + return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR; + + /* Here we see why `this_char' has to be larger than an `unsigned + char' -- the range is inclusive, so if `range_end' == 0xff + (assuming 8-bit characters), we would otherwise go into an infinite + loop, since all characters <= 0xff. */ + for (this_char = range_start; this_char <= range_end; this_char++) + { + SET_LIST_BIT (TRANSLATE (this_char)); + } + + return REG_NOERROR; +} + +/* Failure stack declarations and macros; both re_compile_fastmap and + re_match_2 use a failure stack. These have to be macros because of + REGEX_ALLOCATE. */ + + +/* Number of failure points for which to initially allocate space + when matching. If this number is exceeded, we allocate more + space, so it is not a hard limit. */ +#ifndef INIT_FAILURE_ALLOC +#define INIT_FAILURE_ALLOC 5 +#endif + +/* Roughly the maximum number of failure points on the stack. Would be + exactly that if always used MAX_FAILURE_SPACE each time we failed. + This is a variable only so users of regex can assign to it; we never + change it ourselves. */ +int re_max_failures = 2000; + +typedef const unsigned char *fail_stack_elt_t; + +typedef struct +{ + fail_stack_elt_t *stack; + unsigned size; + unsigned avail; /* Offset of next open position. */ +} fail_stack_type; + +#define FAIL_STACK_EMPTY() (fail_stack.avail == 0) +#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) +#define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) +#define FAIL_STACK_TOP() (fail_stack.stack[fail_stack.avail]) + + +/* Initialize `fail_stack'. Do `return -2' if the alloc fails. */ + +#define INIT_FAIL_STACK() \ + do { \ + fail_stack.stack = (fail_stack_elt_t *) \ + REGEX_ALLOCATE (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \ + \ + if (fail_stack.stack == NULL) \ + return -2; \ + \ + fail_stack.size = INIT_FAILURE_ALLOC; \ + fail_stack.avail = 0; \ + } while (0) + + +/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items. + + Return 1 if succeeds, and 0 if either ran out of memory + allocating space for it or it was already too large. + + REGEX_REALLOCATE requires `destination' be declared. */ + +#define DOUBLE_FAIL_STACK(fail_stack) \ + ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS \ + ? 0 \ + : ((fail_stack).stack = (fail_stack_elt_t *) \ + REGEX_REALLOCATE ((fail_stack).stack, \ + (fail_stack).size * sizeof (fail_stack_elt_t), \ + ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \ + \ + (fail_stack).stack == NULL \ + ? 0 \ + : ((fail_stack).size <<= 1, \ + 1))) + + +/* Push PATTERN_OP on FAIL_STACK. + + Return 1 if was able to do so and 0 if ran out of memory allocating + space to do so. */ +#define PUSH_PATTERN_OP(pattern_op, fail_stack) \ + ((FAIL_STACK_FULL () \ + && !DOUBLE_FAIL_STACK (fail_stack)) \ + ? 0 \ + : ((fail_stack).stack[(fail_stack).avail++] = pattern_op, \ + 1)) + +/* This pushes an item onto the failure stack. Must be a four-byte + value. Assumes the variable `fail_stack'. Probably should only + be called from within `PUSH_FAILURE_POINT'. */ +#define PUSH_FAILURE_ITEM(item) \ + fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) item + +/* The complement operation. Assumes `fail_stack' is nonempty. */ +#define POP_FAILURE_ITEM() fail_stack.stack[--fail_stack.avail] + +/* Used to omit pushing failure point id's when we're not debugging. */ +#ifdef DEBUG +#define DEBUG_PUSH PUSH_FAILURE_ITEM +#define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_ITEM () +#else +#define DEBUG_PUSH(item) +#define DEBUG_POP(item_addr) +#endif + + +/* Push the information about the state we will need + if we ever fail back to it. + + Requires variables fail_stack, regstart, regend, reg_info, and + num_regs be declared. DOUBLE_FAIL_STACK requires `destination' be + declared. + + Does `return FAILURE_CODE' if runs out of memory. */ + +#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ + do { \ + char *destination; \ + /* Must be int, so when we don't save any registers, the arithmetic \ + of 0 + -1 isn't done as unsigned. */ \ + int this_reg; \ + \ + DEBUG_STATEMENT (failure_id++); \ + DEBUG_STATEMENT (nfailure_points_pushed++); \ + DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ + DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\ + DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ + \ + DEBUG_PRINT2 (" slots needed: %d\n", NUM_FAILURE_ITEMS); \ + DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \ + \ + /* Ensure we have enough space allocated for what we will push. */ \ + while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \ + { \ + if (!DOUBLE_FAIL_STACK (fail_stack)) \ + return failure_code; \ + \ + DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \ + (fail_stack).size); \ + DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ + } \ + \ + /* Push the info, starting with the registers. */ \ + DEBUG_PRINT1 ("\n"); \ + \ + for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \ + this_reg++) \ + { \ + DEBUG_PRINT2 (" Pushing reg: %d\n", this_reg); \ + DEBUG_STATEMENT (num_regs_pushed++); \ + \ + DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ + PUSH_FAILURE_ITEM (regstart[this_reg]); \ + \ + DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ + PUSH_FAILURE_ITEM (regend[this_reg]); \ + \ + DEBUG_PRINT2 (" info: 0x%x\n ", reg_info[this_reg]); \ + DEBUG_PRINT2 (" match_null=%d", \ + REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \ + DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \ + DEBUG_PRINT2 (" matched_something=%d", \ + MATCHED_SOMETHING (reg_info[this_reg])); \ + DEBUG_PRINT2 (" ever_matched=%d", \ + EVER_MATCHED_SOMETHING (reg_info[this_reg])); \ + DEBUG_PRINT1 ("\n"); \ + PUSH_FAILURE_ITEM (reg_info[this_reg].word); \ + } \ + \ + DEBUG_PRINT2 (" Pushing low active reg: %d\n", lowest_active_reg);\ + PUSH_FAILURE_ITEM (lowest_active_reg); \ + \ + DEBUG_PRINT2 (" Pushing high active reg: %d\n", highest_active_reg);\ + PUSH_FAILURE_ITEM (highest_active_reg); \ + \ + DEBUG_PRINT2 (" Pushing pattern 0x%x: ", pattern_place); \ + DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \ + PUSH_FAILURE_ITEM (pattern_place); \ + \ + DEBUG_PRINT2 (" Pushing string 0x%x: `", string_place); \ + DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \ + size2); \ + DEBUG_PRINT1 ("'\n"); \ + PUSH_FAILURE_ITEM (string_place); \ + \ + DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \ + DEBUG_PUSH (failure_id); \ + } while (0) + +/* This is the number of items that are pushed and popped on the stack + for each register. */ +#define NUM_REG_ITEMS 3 + +/* Individual items aside from the registers. */ +#ifdef DEBUG +#define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ +#else +#define NUM_NONREG_ITEMS 4 +#endif + +/* We push at most this many items on the stack. */ +#define MAX_FAILURE_ITEMS ((num_regs - 1) * NUM_REG_ITEMS + NUM_NONREG_ITEMS) + +/* We actually push this many items. */ +#define NUM_FAILURE_ITEMS \ + ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS \ + + NUM_NONREG_ITEMS) + +/* How many items can still be added to the stack without overflowing it. */ +#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) + + +/* Pops what PUSH_FAIL_STACK pushes. + + We restore into the parameters, all of which should be lvalues: + STR -- the saved data position. + PAT -- the saved pattern position. + LOW_REG, HIGH_REG -- the highest and lowest active registers. + REGSTART, REGEND -- arrays of string positions. + REG_INFO -- array of information about each subexpression. + + Also assumes the variables `fail_stack' and (if debugging), `bufp', + `pend', `string1', `size1', `string2', and `size2'. */ + +#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ +{ \ + DEBUG_STATEMENT (fail_stack_elt_t failure_id;) \ + int this_reg; \ + const unsigned char *string_temp; \ + \ + assert (!FAIL_STACK_EMPTY ()); \ + \ + /* Remove failure points and point to how many regs pushed. */ \ + DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \ + DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \ + DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \ + \ + assert (fail_stack.avail >= NUM_NONREG_ITEMS); \ + \ + DEBUG_POP (&failure_id); \ + DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \ + \ + /* If the saved string location is NULL, it came from an \ + on_failure_keep_string_jump opcode, and we want to throw away the \ + saved NULL, thus retaining our current position in the string. */ \ + string_temp = POP_FAILURE_ITEM (); \ + if (string_temp != NULL) \ + str = (const char *) string_temp; \ + \ + DEBUG_PRINT2 (" Popping string 0x%x: `", str); \ + DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ + DEBUG_PRINT1 ("'\n"); \ + \ + pat = (unsigned char *) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" Popping pattern 0x%x: ", pat); \ + DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ + \ + /* Restore register info. */ \ + high_reg = (unsigned) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" Popping high active reg: %d\n", high_reg); \ + \ + low_reg = (unsigned) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" Popping low active reg: %d\n", low_reg); \ + \ + for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \ + { \ + DEBUG_PRINT2 (" Popping reg: %d\n", this_reg); \ + \ + reg_info[this_reg].word = POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" info: 0x%x\n", reg_info[this_reg]); \ + \ + regend[this_reg] = (const char *) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ + \ + regstart[this_reg] = (const char *) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ + } \ + \ + DEBUG_STATEMENT (nfailure_points_popped++); \ +} /* POP_FAILURE_POINT */ + +/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in + BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible + characters can start a string that matches the pattern. This fastmap + is used by re_search to skip quickly over impossible starting points. + + The caller must supply the address of a (1 << BYTEWIDTH)-byte data + area as BUFP->fastmap. + + We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in + the pattern buffer. + + Returns 0 if we succeed, -2 if an internal error. */ + +int +re_compile_fastmap ( struct re_pattern_buffer *bufp ) +{ + int j, k; + fail_stack_type fail_stack; +#ifndef REGEX_MALLOC + char *destination; +#endif + /* We don't push any register information onto the failure stack. */ + unsigned num_regs = 0; + + register char *fastmap = bufp->fastmap; + unsigned char *pattern = bufp->buffer; + unsigned long size = bufp->used; + const unsigned char *p = pattern; + register unsigned char *pend = pattern + size; + + /* Assume that each path through the pattern can be null until + proven otherwise. We set this false at the bottom of switch + statement, to which we get only if a particular path doesn't + match the empty string. */ + boolean path_can_be_null = true; + + /* We aren't doing a `succeed_n' to begin with. */ + boolean succeed_n_p = false; + + assert (fastmap != NULL && p != NULL); + + INIT_FAIL_STACK (); + bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */ + bufp->fastmap_accurate = 1; /* It will be when we're done. */ + bufp->can_be_null = 0; + + while (p != pend || !FAIL_STACK_EMPTY ()) + { + if (p == pend) + { + bufp->can_be_null |= path_can_be_null; + + /* Reset for next path. */ + path_can_be_null = true; + + p = fail_stack.stack[--fail_stack.avail]; + } + + /* We should never be about to go beyond the end of the pattern. */ + assert (p < pend); + +#ifdef SWITCH_ENUM_BUG + switch ((int) ((re_opcode_t) *p++)) +#else + switch ((re_opcode_t) *p++) +#endif + { + + /* I guess the idea here is to simply not bother with a fastmap + if a backreference is used, since it's too hard to figure out + the fastmap for the corresponding group. Setting + `can_be_null' stops `re_search_2' from using the fastmap, so + that is all we do. */ + case duplicate: + bufp->can_be_null = 1; + return 0; + + + /* Following are the cases which match a character. These end + with `break'. */ + + case exactn: + fastmap[p[1]] = 1; + break; + + + case charset: + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) + fastmap[j] = 1; + break; + + + case charset_not: + /* Chars beyond end of map must be allowed. */ + for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) + fastmap[j] = 1; + + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) + fastmap[j] = 1; + break; + + + case wordchar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) == Sword) + fastmap[j] = 1; + break; + + + case notwordchar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) != Sword) + fastmap[j] = 1; + break; + + + case anychar: + /* `.' matches anything ... */ + for (j = 0; j < (1 << BYTEWIDTH); j++) + fastmap[j] = 1; + + /* ... except perhaps newline. */ + if (!(bufp->syntax & RE_DOT_NEWLINE)) + fastmap['\n'] = 0; + + /* Return if we have already set `can_be_null'; if we have, + then the fastmap is irrelevant. Something's wrong here. */ + else if (bufp->can_be_null) + return 0; + + /* Otherwise, have to check alternative paths. */ + break; + + +#ifdef emacs + case syntaxspec: + k = *p++; + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) == (enum syntaxcode) k) + fastmap[j] = 1; + break; + + + case notsyntaxspec: + k = *p++; + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) != (enum syntaxcode) k) + fastmap[j] = 1; + break; + + + /* All cases after this match the empty string. These end with + `continue'. */ + + + case before_dot: + case at_dot: + case after_dot: + continue; +#endif /* not emacs */ + + + case no_op: + case begline: + case endline: + case begbuf: + case endbuf: + case wordbound: + case notwordbound: + case wordbeg: + case wordend: + case push_dummy_failure: + continue; + + + case jump_n: + case pop_failure_jump: + case maybe_pop_jump: + case jump: + case jump_past_alt: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (j, p); + p += j; + if (j > 0) + continue; + + /* Jump backward implies we just went through the body of a + loop and matched nothing. Opcode jumped to should be + `on_failure_jump' or `succeed_n'. Just treat it like an + ordinary jump. For a * loop, it has pushed its failure + point already; if so, discard that as redundant. */ + if ((re_opcode_t) *p != on_failure_jump + && (re_opcode_t) *p != succeed_n) + continue; + + p++; + EXTRACT_NUMBER_AND_INCR (j, p); + p += j; + + /* If what's on the stack is where we are now, pop it. */ + if (!FAIL_STACK_EMPTY () + && fail_stack.stack[fail_stack.avail - 1] == p) + fail_stack.avail--; + + continue; + + + case on_failure_jump: + case on_failure_keep_string_jump: + handle_on_failure_jump: + EXTRACT_NUMBER_AND_INCR (j, p); + + /* For some patterns, e.g., `(a?)?', `p+j' here points to the + end of the pattern. We don't want to push such a point, + since when we restore it above, entering the switch will + increment `p' past the end of the pattern. We don't need + to push such a point since we obviously won't find any more + fastmap entries beyond `pend'. Such a pattern can match + the null string, though. */ + if (p + j < pend) + { + if (!PUSH_PATTERN_OP (p + j, fail_stack)) + return -2; + } + else + bufp->can_be_null = 1; + + if (succeed_n_p) + { + EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */ + succeed_n_p = false; + } + + continue; + + + case succeed_n: + /* Get to the number of times to succeed. */ + p += 2; + + /* Increment p past the n for when k != 0. */ + EXTRACT_NUMBER_AND_INCR (k, p); + if (k == 0) + { + p -= 4; + succeed_n_p = true; /* Spaghetti code alert. */ + goto handle_on_failure_jump; + } + continue; + + + case set_number_at: + p += 4; + continue; + + + case start_memory: + case stop_memory: + p += 2; + continue; + + + default: + abort (); /* We have listed all the cases. */ + } /* switch *p++ */ + + /* Getting here means we have found the possible starting + characters for one path of the pattern -- and that the empty + string does not match. We need not follow this path further. + Instead, look at the next alternative (remembered on the + stack), or quit if no more. The test at the top of the loop + does these things. */ + path_can_be_null = false; + p = pend; + } /* while p */ + + /* Set `can_be_null' for the last path (also the first path, if the + pattern is empty). */ + bufp->can_be_null |= path_can_be_null; + return 0; +} /* re_compile_fastmap */ + +/* Set REGS to hold NUM_REGS registers, storing them in STARTS and + ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use + this memory for recording register information. STARTS and ENDS + must be allocated using the malloc library routine, and must each + be at least NUM_REGS * sizeof (regoff_t) bytes long. + + If NUM_REGS == 0, then subsequent matches should allocate their own + register data. + + Unless this function is called, the first search or match using + PATTERN_BUFFER will allocate its own register data, without + freeing the old data. */ + +void +re_set_registers ( struct re_pattern_buffer *bufp, + struct re_registers *regs, unsigned num_regs, + regoff_t *starts, regoff_t *ends ) +{ + if (num_regs) + { + bufp->regs_allocated = REGS_REALLOCATE; + regs->num_regs = num_regs; + regs->start = starts; + regs->end = ends; + } + else + { + bufp->regs_allocated = REGS_UNALLOCATED; + regs->num_regs = 0; + regs->start = regs->end = (regoff_t *) 0; + } +} + +/* Searching routines. */ + +/* Like re_search_2, below, but only one string is specified, and + doesn't let you say where to stop matching. */ + +int +re_search ( struct re_pattern_buffer *bufp, const char *string, + int size, int startpos, int range, struct re_registers *regs ) +{ + return re_search_2 (bufp, NULL, string, 0, size, startpos, range, + regs, size); +} + + +/* Using the compiled pattern in BUFP->buffer, first tries to match the + virtual concatenation of STRING1 and STRING2, starting first at index + STARTPOS, then at STARTPOS + 1, and so on. + + STRING1 and STRING2 have length SIZE1 and SIZE2, respectively. + + RANGE is how far to scan while trying to match. RANGE = 0 means try + only at STARTPOS; in general, the last start tried is STARTPOS + + RANGE. + + In REGS, return the indices of the virtual concatenation of STRING1 + and STRING2 that matched the entire BUFP->buffer and its contained + subexpressions. + + Do not consider matching one past the index STOP in the virtual + concatenation of STRING1 and STRING2. + + We return either the position in the strings at which the match was + found, -1 if no match, or -2 if error (such as failure + stack overflow). */ + +int +re_search_2 ( struct re_pattern_buffer *bufp, + const char *string1, const char *string2, int size1, int size2, + int startpos, int range, struct re_registers *regs, int stop ) +{ + int val; + register char *fastmap = bufp->fastmap; + register char *translate = bufp->translate; + int total_size = size1 + size2; + int endpos = startpos + range; + + /* Check for out-of-range STARTPOS. */ + if (startpos < 0 || startpos > total_size) + return -1; + + /* Fix up RANGE if it might eventually take us outside + the virtual concatenation of STRING1 and STRING2. */ + if (endpos < -1) + range = -1 - startpos; + else if (endpos > total_size) + range = total_size - startpos; + + /* If the search isn't to be a backwards one, don't waste time in a + search for a pattern that must be anchored. */ + if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0) + { + if (startpos > 0) + return -1; + else + range = 1; + } + + /* Update the fastmap now if not correct already. */ + if (fastmap && !bufp->fastmap_accurate) + if (re_compile_fastmap (bufp) == -2) + return -2; + + /* Loop through the string, looking for a place to start matching. */ + for (;;) + { + /* If a fastmap is supplied, skip quickly over characters that + cannot be the start of a match. If the pattern can match the + null string, however, we don't need to skip characters; we want + the first null string. */ + if (fastmap && startpos < total_size && !bufp->can_be_null) + { + if (range > 0) /* Searching forwards. */ + { + register const char *d; + register int lim = 0; + int irange = range; + + if (startpos < size1 && startpos + range >= size1) + lim = range - (size1 - startpos); + + d = (startpos >= size1 ? string2 - size1 : string1) + startpos; + + /* Written out as an if-else to avoid testing `translate' + inside the loop. */ + if (translate) + while (range > lim + && !fastmap[(unsigned char) + translate[(unsigned char) *d++]]) + range--; + else + while (range > lim && !fastmap[(unsigned char) *d++]) + range--; + + startpos += irange - range; + } + else /* Searching backwards. */ + { + register char c = (size1 == 0 || startpos >= size1 + ? string2[startpos - size1] + : string1[startpos]); + + if (!fastmap[(unsigned char) TRANSLATE (c)]) + goto advance; + } + } + + /* If can't match the null string, and that's all we have left, fail. */ + if (range >= 0 && startpos == total_size && fastmap + && !bufp->can_be_null) + return -1; + + val = re_match_2 (bufp, string1, string2, size1, size2, + startpos, regs, stop); + if (val >= 0) + return startpos; + + if (val == -2) + return -2; + + advance: + if (!range) + break; + else if (range > 0) + { + range--; + startpos++; + } + else + { + range++; + startpos--; + } + } + return -1; +} /* re_search_2 */ + +/* Declarations and macros for re_match_2. */ + +//static int bcmp_translate (); +static int +bcmp_translate ( const char *s1, const char *s2, + register int len, char *translate ); + +//static boolean alt_match_null_string_p (), + +// common_op_match_null_string_p (); +// group_match_null_string_p (); + + +/* Structure for per-register (a.k.a. per-group) information. + This must not be longer than one word, because we push this value + onto the failure stack. Other register information, such as the + starting and ending positions (which are addresses), and the list of + inner groups (which is a bits list) are maintained in separate + variables. + + We are making a (strictly speaking) nonportable assumption here: that + the compiler will pack our bit fields into something that fits into + the type of `word', i.e., is something that fits into one item on the + failure stack. */ +typedef union +{ + fail_stack_elt_t word; + struct + { + /* This field is one if this group can match the empty string, + zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */ +#define MATCH_NULL_UNSET_VALUE 3 + unsigned match_null_string_p : 2; + unsigned is_active : 1; + unsigned matched_something : 1; + unsigned ever_matched_something : 1; + } bits; +} register_info_type; + +static boolean +alt_match_null_string_p ( unsigned char *p, unsigned char *end, + register_info_type *reg_info ); + +static boolean +group_match_null_string_p ( unsigned char **p, unsigned char *end, + register_info_type *reg_info ); +static boolean +common_op_match_null_string_p ( unsigned char **p, unsigned char *end, + register_info_type *reg_info ); + + +#define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) +#define IS_ACTIVE(R) ((R).bits.is_active) +#define MATCHED_SOMETHING(R) ((R).bits.matched_something) +#define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) + + +/* Call this when have matched a real character; it sets `matched' flags + for the subexpressions which we are currently inside. Also records + that those subexprs have matched. */ +#define SET_REGS_MATCHED() \ + do \ + { \ + unsigned r; \ + for (r = lowest_active_reg; r <= highest_active_reg; r++) \ + { \ + MATCHED_SOMETHING (reg_info[r]) \ + = EVER_MATCHED_SOMETHING (reg_info[r]) \ + = 1; \ + } \ + } \ + while (0) + + +/* This converts PTR, a pointer into one of the search strings `string1' + and `string2' into an offset from the beginning of that string. */ +#define POINTER_TO_OFFSET(ptr) \ + (FIRST_STRING_P (ptr) ? (ptr) - string1 : (ptr) - string2 + size1) + +/* Registers are set to a sentinel when they haven't yet matched. */ +#define REG_UNSET_VALUE ((char *) -1) +#define REG_UNSET(e) ((e) == REG_UNSET_VALUE) + + +/* Macros for dealing with the split strings in re_match_2. */ + +#define MATCHING_IN_FIRST_STRING (dend == end_match_1) + +/* Call before fetching a character with *d. This switches over to + string2 if necessary. */ +#define PREFETCH() \ + while (d == dend) \ + { \ + /* End of string2 => fail. */ \ + if (dend == end_match_2) \ + goto fail; \ + /* End of string1 => advance to string2. */ \ + d = string2; \ + dend = end_match_2; \ + } + + +/* Test if at very beginning or at very end of the virtual concatenation + of `string1' and `string2'. If only one string, it's `string2'. */ +#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2) +#define AT_STRINGS_END(d) ((d) == end2) + + +/* Test if D points to a character which is word-constituent. We have + two special cases to check for: if past the end of string1, look at + the first character in string2; and if before the beginning of + string2, look at the last character in string1. */ +#define WORDCHAR_P(d) \ + (SYNTAX ((d) == end1 ? *string2 \ + : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ + == Sword) + +/* Test if the character before D and the one at D differ with respect + to being word-constituent. */ +#define AT_WORD_BOUNDARY(d) \ + (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \ + || WORDCHAR_P (d - 1) != WORDCHAR_P (d)) + + +/* Free everything we malloc. */ +#ifdef REGEX_MALLOC +#define FREE_VAR(var) if (var) free (var); var = NULL +#define FREE_VARIABLES() \ + do { \ + FREE_VAR (fail_stack.stack); \ + FREE_VAR (regstart); \ + FREE_VAR (regend); \ + FREE_VAR (old_regstart); \ + FREE_VAR (old_regend); \ + FREE_VAR (best_regstart); \ + FREE_VAR (best_regend); \ + FREE_VAR (reg_info); \ + FREE_VAR (reg_dummy); \ + FREE_VAR (reg_info_dummy); \ + } while (0) +#else /* not REGEX_MALLOC */ +/* Some MIPS systems (at least) want this to free alloca'd storage. */ +#define FREE_VARIABLES() alloca (0) +#endif /* not REGEX_MALLOC */ + + +/* These values must meet several constraints. They must not be valid + register values; since we have a limit of 255 registers (because + we use only one byte in the pattern for the register number), we can + use numbers larger than 255. They must differ by 1, because of + NUM_FAILURE_ITEMS above. And the value for the lowest register must + be larger than the value for the highest register, so we do not try + to actually save any registers when none are active. */ +#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH) +#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1) + +/* Matching routines. */ + +#ifndef emacs /* Emacs never uses this. */ +/* re_match is like re_match_2 except it takes only a single string. */ + +int +re_match (struct re_pattern_buffer *bufp, const char *string, int size, int + pos, struct re_registers *regs) +{ + return re_match_2 (bufp, NULL, string, 0, size, pos, regs, size); +} +#endif /* not emacs */ + + +/* re_match_2 matches the compiled pattern in BUFP against the + the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1 + and SIZE2, respectively). We start matching at POS, and stop + matching at STOP. + + If REGS is non-null and the `no_sub' field of BUFP is nonzero, we + store offsets for the substring each group matched in REGS. See the + documentation for exactly how many groups we fill. + + We return -1 if no match, -2 if an internal error (such as the + failure stack overflowing). Otherwise, we return the length of the + matched substring. */ + +int +re_match_2 ( struct re_pattern_buffer *bufp, const char *string1, + const char *string2, int size1, int size2, int pos, + struct re_registers *regs, int stop ) +{ + /* General temporaries. */ + int mcnt; + unsigned char *p1; + + /* Just past the end of the corresponding string. */ + const char *end1, *end2; + + /* Pointers into string1 and string2, just past the last characters in + each to consider matching. */ + const char *end_match_1, *end_match_2; + + /* Where we are in the data, and the end of the current string. */ + const char *d, *dend; + + /* Where we are in the pattern, and the end of the pattern. */ + unsigned char *p = bufp->buffer; + register unsigned char *pend = p + bufp->used; + + /* We use this to map every character in the string. */ + char *translate = bufp->translate; + + /* Failure point stack. Each place that can handle a failure further + down the line pushes a failure point on this stack. It consists of + restart, regend, and reg_info for all registers corresponding to + the subexpressions we're currently inside, plus the number of such + registers, and, finally, two char *'s. The first char * is where + to resume scanning the pattern; the second one is where to resume + scanning the strings. If the latter is zero, the failure point is + a ``dummy''; if a failure happens and the failure point is a dummy, + it gets discarded and the next next one is tried. */ + fail_stack_type fail_stack; +#ifdef DEBUG + static unsigned failure_id = 0; + unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0; +#endif + + /* We fill all the registers internally, independent of what we + return, for use in backreferences. The number here includes + an element for register zero. */ + unsigned num_regs = bufp->re_nsub + 1; + + /* The currently active registers. */ + unsigned lowest_active_reg = NO_LOWEST_ACTIVE_REG; + unsigned highest_active_reg = NO_HIGHEST_ACTIVE_REG; + + /* Information on the contents of registers. These are pointers into + the input strings; they record just what was matched (on this + attempt) by a subexpression part of the pattern, that is, the + regnum-th regstart pointer points to where in the pattern we began + matching and the regnum-th regend points to right after where we + stopped matching the regnum-th subexpression. (The zeroth register + keeps track of what the whole pattern matches.) */ + const char **regstart=0, **regend=0; + + /* If a group that's operated upon by a repetition operator fails to + match anything, then the register for its start will need to be + restored because it will have been set to wherever in the string we + are when we last see its open-group operator. Similarly for a + register's end. */ + const char **old_regstart=0, **old_regend=0; + + /* The is_active field of reg_info helps us keep track of which (possibly + nested) subexpressions we are currently in. The matched_something + field of reg_info[reg_num] helps us tell whether or not we have + matched any of the pattern so far this time through the reg_num-th + subexpression. These two fields get reset each time through any + loop their register is in. */ + register_info_type *reg_info=0; + + /* The following record the register info as found in the above + variables when we find a match better than any we've seen before. + This happens as we backtrack through the failure points, which in + turn happens only if we have not yet matched the entire string. */ + unsigned best_regs_set = false; + const char **best_regstart=0, **best_regend=0; + + /* Logically, this is `best_regend[0]'. But we don't want to have to + allocate space for that if we're not allocating space for anything + else (see below). Also, we never need info about register 0 for + any of the other register vectors, and it seems rather a kludge to + treat `best_regend' differently than the rest. So we keep track of + the end of the best match so far in a separate variable. We + initialize this to NULL so that when we backtrack the first time + and need to test it, it's not garbage. */ + const char *match_end = NULL; + + /* Used when we pop values we don't care about. */ + const char **reg_dummy=0; + register_info_type *reg_info_dummy=0; + +#ifdef DEBUG + /* Counts the total number of registers pushed. */ + unsigned num_regs_pushed = 0; +#endif + + DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); + + INIT_FAIL_STACK (); + + /* Do not bother to initialize all the register variables if there are + no groups in the pattern, as it takes a fair amount of time. If + there are groups, we include space for register 0 (the whole + pattern), even though we never use it, since it simplifies the + array indexing. We should fix this. */ + if (bufp->re_nsub) + { + regstart = REGEX_TALLOC (num_regs, const char *); + regend = REGEX_TALLOC (num_regs, const char *); + old_regstart = REGEX_TALLOC (num_regs, const char *); + old_regend = REGEX_TALLOC (num_regs, const char *); + best_regstart = REGEX_TALLOC (num_regs, const char *); + best_regend = REGEX_TALLOC (num_regs, const char *); + reg_info = REGEX_TALLOC (num_regs, register_info_type); + reg_dummy = REGEX_TALLOC (num_regs, const char *); + reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type); + + if (!(regstart && regend && old_regstart && old_regend && reg_info + && best_regstart && best_regend && reg_dummy && reg_info_dummy)) + { + FREE_VARIABLES (); + return -2; + } + } +#ifdef REGEX_MALLOC + else + { + /* We must initialize all our variables to NULL, so that + `FREE_VARIABLES' doesn't try to free them. */ + regstart = regend = old_regstart = old_regend = best_regstart + = best_regend = reg_dummy = NULL; + reg_info = reg_info_dummy = (register_info_type *) NULL; + } +#endif /* REGEX_MALLOC */ + + /* The starting position is bogus. */ + if (pos < 0 || pos > size1 + size2) + { + FREE_VARIABLES (); + return -1; + } + + /* Initialize subexpression text positions to -1 to mark ones that no + start_memory/stop_memory has been seen for. Also initialize the + register information struct. */ + for (mcnt = 1; mcnt < num_regs; mcnt++) + { + regstart[mcnt] = regend[mcnt] + = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE; + + REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE; + IS_ACTIVE (reg_info[mcnt]) = 0; + MATCHED_SOMETHING (reg_info[mcnt]) = 0; + EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0; + } + + /* We move `string1' into `string2' if the latter's empty -- but not if + `string1' is null. */ + if (size2 == 0 && string1 != NULL) + { + string2 = string1; + size2 = size1; + string1 = 0; + size1 = 0; + } + end1 = string1 + size1; + end2 = string2 + size2; + + /* Compute where to stop matching, within the two strings. */ + if (stop <= size1) + { + end_match_1 = string1 + stop; + end_match_2 = string2; + } + else + { + end_match_1 = end1; + end_match_2 = string2 + stop - size1; + } + + /* `p' scans through the pattern as `d' scans through the data. + `dend' is the end of the input string that `d' points within. `d' + is advanced into the following input string whenever necessary, but + this happens before fetching; therefore, at the beginning of the + loop, `d' can be pointing at the end of a string, but it cannot + equal `string2'. */ + if (size1 > 0 && pos <= size1) + { + d = string1 + pos; + dend = end_match_1; + } + else + { + d = string2 + pos - size1; + dend = end_match_2; + } + + DEBUG_PRINT1 ("The compiled pattern is: "); + DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend); + DEBUG_PRINT1 ("The string to match is: `"); + DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2); + DEBUG_PRINT1 ("'\n"); + + /* This loops over pattern commands. It exits by returning from the + function if the match is complete, or it drops through if the match + fails at this starting point in the input data. */ + for (;;) + { + DEBUG_PRINT2 ("\n0x%x: ", p); + + if (p == pend) + { /* End of pattern means we might have succeeded. */ + DEBUG_PRINT1 ("end of pattern ... "); + + /* If we haven't matched the entire string, and we want the + longest match, try backtracking. */ + if (d != end_match_2) + { + DEBUG_PRINT1 ("backtracking.\n"); + + if (!FAIL_STACK_EMPTY ()) + { /* More failure points to try. */ + boolean same_str_p = (FIRST_STRING_P (match_end) + == MATCHING_IN_FIRST_STRING); + + /* If exceeds best match so far, save it. */ + if (!best_regs_set + || (same_str_p && d > match_end) + || (!same_str_p && !MATCHING_IN_FIRST_STRING)) + { + best_regs_set = true; + match_end = d; + + DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); + + for (mcnt = 1; mcnt < num_regs; mcnt++) + { + best_regstart[mcnt] = regstart[mcnt]; + best_regend[mcnt] = regend[mcnt]; + } + } + goto fail; + } + + /* If no failure points, don't restore garbage. */ + else if (best_regs_set) + { + restore_best_regs: + /* Restore best match. It may happen that `dend == + end_match_1' while the restored d is in string2. + For example, the pattern `x.*y.*z' against the + strings `x-' and `y-z-', if the two strings are + not consecutive in memory. */ + DEBUG_PRINT1 ("Restoring best registers.\n"); + + d = match_end; + dend = ((d >= string1 && d <= end1) + ? end_match_1 : end_match_2); + + for (mcnt = 1; mcnt < num_regs; mcnt++) + { + regstart[mcnt] = best_regstart[mcnt]; + regend[mcnt] = best_regend[mcnt]; + } + } + } /* d != end_match_2 */ + + DEBUG_PRINT1 ("Accepting match.\n"); + + /* If caller wants register contents data back, do it. */ + if (regs && !bufp->no_sub) + { + /* Have the register data arrays been allocated? */ + if (bufp->regs_allocated == REGS_UNALLOCATED) + { /* No. So allocate them with malloc. We need one + extra element beyond `num_regs' for the `-1' marker + GNU code uses. */ + regs->num_regs = MAX (RE_NREGS, num_regs + 1); + regs->start = TALLOC (regs->num_regs, regoff_t); + regs->end = TALLOC (regs->num_regs, regoff_t); + if (regs->start == NULL || regs->end == NULL) + return -2; + bufp->regs_allocated = REGS_REALLOCATE; + } + else if (bufp->regs_allocated == REGS_REALLOCATE) + { /* Yes. If we need more elements than were already + allocated, reallocate them. If we need fewer, just + leave it alone. */ + if (regs->num_regs < num_regs + 1) + { + regs->num_regs = num_regs + 1; + RETALLOC (regs->start, regs->num_regs, regoff_t); + RETALLOC (regs->end, regs->num_regs, regoff_t); + if (regs->start == NULL || regs->end == NULL) + return -2; + } + } + else + assert (bufp->regs_allocated == REGS_FIXED); + + /* Convert the pointer data in `regstart' and `regend' to + indices. Register zero has to be set differently, + since we haven't kept track of any info for it. */ + if (regs->num_regs > 0) + { + regs->start[0] = pos; + regs->end[0] = (MATCHING_IN_FIRST_STRING ? d - string1 + : d - string2 + size1); + } + + /* Go through the first `min (num_regs, regs->num_regs)' + registers, since that is all we initialized. */ + for (mcnt = 1; mcnt < MIN (num_regs, regs->num_regs); mcnt++) + { + if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt])) + regs->start[mcnt] = regs->end[mcnt] = -1; + else + { + regs->start[mcnt] = POINTER_TO_OFFSET (regstart[mcnt]); + regs->end[mcnt] = POINTER_TO_OFFSET (regend[mcnt]); + } + } + + /* If the regs structure we return has more elements than + were in the pattern, set the extra elements to -1. If + we (re)allocated the registers, this is the case, + because we always allocate enough to have at least one + -1 at the end. */ + for (mcnt = num_regs; mcnt < regs->num_regs; mcnt++) + regs->start[mcnt] = regs->end[mcnt] = -1; + } /* regs && !bufp->no_sub */ + + FREE_VARIABLES (); + DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", + nfailure_points_pushed, nfailure_points_popped, + nfailure_points_pushed - nfailure_points_popped); + DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); + + mcnt = d - pos - (MATCHING_IN_FIRST_STRING + ? string1 + : string2 - size1); + + DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); + + return mcnt; + } + + /* Otherwise match next pattern command. */ +#ifdef SWITCH_ENUM_BUG + switch ((int) ((re_opcode_t) *p++)) +#else + switch ((re_opcode_t) *p++) +#endif + { + /* Ignore these. Used to ignore the n of succeed_n's which + currently have n == 0. */ + case no_op: + DEBUG_PRINT1 ("EXECUTING no_op.\n"); + break; + + + /* Match the next n pattern characters exactly. The following + byte in the pattern defines n, and the n bytes after that + are the characters to match. */ + case exactn: + mcnt = *p++; + DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt); + + /* This is written out as an if-else so we don't waste time + testing `translate' inside the loop. */ + if (translate) + { + do + { + PREFETCH (); + if (translate[(unsigned char) *d++] != (char) *p++) + goto fail; + } + while (--mcnt); + } + else + { + do + { + PREFETCH (); + if (*d++ != (char) *p++) goto fail; + } + while (--mcnt); + } + SET_REGS_MATCHED (); + break; + + + /* Match any character except possibly a newline or a null. */ + case anychar: + DEBUG_PRINT1 ("EXECUTING anychar.\n"); + + PREFETCH (); + + if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n') + || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000')) + goto fail; + + SET_REGS_MATCHED (); + DEBUG_PRINT2 (" Matched `%d'.\n", *d); + d++; + break; + + + case charset: + case charset_not: + { + register unsigned char c; + boolean not = (re_opcode_t) *(p - 1) == charset_not; + + DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : ""); + + PREFETCH (); + c = TRANSLATE (*d); /* The character to match. */ + + /* Cast to `unsigned' instead of `unsigned char' in case the + bit list is a full 32 bytes long. */ + if (c < (unsigned) (*p * BYTEWIDTH) + && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) + not = !not; + + p += 1 + *p; + + if (!not) goto fail; + + SET_REGS_MATCHED (); + d++; + break; + } + + + /* The beginning of a group is represented by start_memory. + The arguments are the register number in the next byte, and the + number of groups inner to this one in the next. The text + matched within the group is recorded (in the internal + registers data structure) under the register number. */ + case start_memory: + DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]); + + /* Find out if this group can match the empty string. */ + p1 = p; /* To send to group_match_null_string_p. */ + + if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE) + REG_MATCH_NULL_STRING_P (reg_info[*p]) + = group_match_null_string_p (&p1, pend, reg_info); + + /* Save the position in the string where we were the last time + we were at this open-group operator in case the group is + operated upon by a repetition operator, e.g., with `(a*)*b' + against `ab'; then we want to ignore where we are now in + the string in case this attempt to match fails. */ + old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) + ? REG_UNSET (regstart[*p]) ? d : regstart[*p] + : regstart[*p]; + DEBUG_PRINT2 (" old_regstart: %d\n", + POINTER_TO_OFFSET (old_regstart[*p])); + + regstart[*p] = d; + DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p])); + + IS_ACTIVE (reg_info[*p]) = 1; + MATCHED_SOMETHING (reg_info[*p]) = 0; + + /* This is the new highest active register. */ + highest_active_reg = *p; + + /* If nothing was active before, this is the new lowest active + register. */ + if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) + lowest_active_reg = *p; + + /* Move past the register number and inner group count. */ + p += 2; + break; + + + /* The stop_memory opcode represents the end of a group. Its + arguments are the same as start_memory's: the register + number, and the number of inner groups. */ + case stop_memory: + DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]); + + /* We need to save the string position the last time we were at + this close-group operator in case the group is operated + upon by a repetition operator, e.g., with `((a*)*(b*)*)*' + against `aba'; then we want to ignore where we are now in + the string in case this attempt to match fails. */ + old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) + ? REG_UNSET (regend[*p]) ? d : regend[*p] + : regend[*p]; + DEBUG_PRINT2 (" old_regend: %d\n", + POINTER_TO_OFFSET (old_regend[*p])); + + regend[*p] = d; + DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p])); + + /* This register isn't active anymore. */ + IS_ACTIVE (reg_info[*p]) = 0; + + /* If this was the only register active, nothing is active + anymore. */ + if (lowest_active_reg == highest_active_reg) + { + lowest_active_reg = NO_LOWEST_ACTIVE_REG; + highest_active_reg = NO_HIGHEST_ACTIVE_REG; + } + else + { /* We must scan for the new highest active register, since + it isn't necessarily one less than now: consider + (a(b)c(d(e)f)g). When group 3 ends, after the f), the + new highest active register is 1. */ + unsigned char r = *p - 1; + while (r > 0 && !IS_ACTIVE (reg_info[r])) + r--; + + /* If we end up at register zero, that means that we saved + the registers as the result of an `on_failure_jump', not + a `start_memory', and we jumped to past the innermost + `stop_memory'. For example, in ((.)*) we save + registers 1 and 2 as a result of the *, but when we pop + back to the second ), we are at the stop_memory 1. + Thus, nothing is active. */ + if (r == 0) + { + lowest_active_reg = NO_LOWEST_ACTIVE_REG; + highest_active_reg = NO_HIGHEST_ACTIVE_REG; + } + else + highest_active_reg = r; + } + + /* If just failed to match something this time around with a + group that's operated on by a repetition operator, try to + force exit from the ``loop'', and restore the register + information for this group that we had before trying this + last match. */ + if ((!MATCHED_SOMETHING (reg_info[*p]) + || (re_opcode_t) p[-3] == start_memory) + && (p + 2) < pend) + { + boolean is_a_jump_n = false; + + p1 = p + 2; + mcnt = 0; + switch ((re_opcode_t) *p1++) + { + case jump_n: + is_a_jump_n = true; + case pop_failure_jump: + case maybe_pop_jump: + case jump: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if (is_a_jump_n) + p1 += 2; + break; + + default: + /* do nothing */ ; + } + p1 += mcnt; + + /* If the next operation is a jump backwards in the pattern + to an on_failure_jump right before the start_memory + corresponding to this stop_memory, exit from the loop + by forcing a failure after pushing on the stack the + on_failure_jump's jump in the pattern, and d. */ + if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump + && (re_opcode_t) p1[3] == start_memory && p1[4] == *p) + { + /* If this group ever matched anything, then restore + what its registers were before trying this last + failed match, e.g., with `(a*)*b' against `ab' for + regstart[1], and, e.g., with `((a*)*(b*)*)*' + against `aba' for regend[3]. + + Also restore the registers for inner groups for, + e.g., `((a*)(b*))*' against `aba' (register 3 would + otherwise get trashed). */ + + if (EVER_MATCHED_SOMETHING (reg_info[*p])) + { + unsigned r; + + EVER_MATCHED_SOMETHING (reg_info[*p]) = 0; + + /* Restore this and inner groups' (if any) registers. */ + for (r = *p; r < *p + *(p + 1); r++) + { + regstart[r] = old_regstart[r]; + + /* xx why this test? */ + if ((int) old_regend[r] >= (int) regstart[r]) + regend[r] = old_regend[r]; + } + } + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + PUSH_FAILURE_POINT (p1 + mcnt, d, -2); + + goto fail; + } + } + + /* Move past the register number and the inner group count. */ + p += 2; + break; + + + /* \ has been turned into a `duplicate' command which is + followed by the numeric value of as the register number. */ + case duplicate: + { + register const char *d2, *dend2; + int regno = *p++; /* Get which register to match against. */ + DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno); + + /* Can't back reference a group which we've never matched. */ + if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno])) + goto fail; + + /* Where in input to try to start matching. */ + d2 = regstart[regno]; + + /* Where to stop matching; if both the place to start and + the place to stop matching are in the same string, then + set to the place to stop, otherwise, for now have to use + the end of the first string. */ + + dend2 = ((FIRST_STRING_P (regstart[regno]) + == FIRST_STRING_P (regend[regno])) + ? regend[regno] : end_match_1); + for (;;) + { + /* If necessary, advance to next segment in register + contents. */ + while (d2 == dend2) + { + if (dend2 == end_match_2) break; + if (dend2 == regend[regno]) break; + + /* End of string1 => advance to string2. */ + d2 = string2; + dend2 = regend[regno]; + } + /* At end of register contents => success */ + if (d2 == dend2) break; + + /* If necessary, advance to next segment in data. */ + PREFETCH (); + + /* How many characters left in this segment to match. */ + mcnt = dend - d; + + /* Want how many consecutive characters we can match in + one shot, so, if necessary, adjust the count. */ + if (mcnt > dend2 - d2) + mcnt = dend2 - d2; + + /* Compare that many; failure if mismatch, else move + past them. */ + if (translate + ? bcmp_translate (d, d2, mcnt, translate) + : bcmp (d, d2, mcnt)) + goto fail; + d += mcnt, d2 += mcnt; + } + } + break; + + + /* begline matches the empty string at the beginning of the string + (unless `not_bol' is set in `bufp'), and, if + `newline_anchor' is set, after newlines. */ + case begline: + DEBUG_PRINT1 ("EXECUTING begline.\n"); + + if (AT_STRINGS_BEG (d)) + { + if (!bufp->not_bol) break; + } + else if (d[-1] == '\n' && bufp->newline_anchor) + { + break; + } + /* In all other cases, we fail. */ + goto fail; + + + /* endline is the dual of begline. */ + case endline: + DEBUG_PRINT1 ("EXECUTING endline.\n"); + + if (AT_STRINGS_END (d)) + { + if (!bufp->not_eol) break; + } + + /* We have to ``prefetch'' the next character. */ + else if ((d == end1 ? *string2 : *d) == '\n' + && bufp->newline_anchor) + { + break; + } + goto fail; + + + /* Match at the very beginning of the data. */ + case begbuf: + DEBUG_PRINT1 ("EXECUTING begbuf.\n"); + if (AT_STRINGS_BEG (d)) + break; + goto fail; + + + /* Match at the very end of the data. */ + case endbuf: + DEBUG_PRINT1 ("EXECUTING endbuf.\n"); + if (AT_STRINGS_END (d)) + break; + goto fail; + + + /* on_failure_keep_string_jump is used to optimize `.*\n'. It + pushes NULL as the value for the string on the stack. Then + `pop_failure_point' will keep the current value for the + string, instead of restoring it. To see why, consider + matching `foo\nbar' against `.*\n'. The .* matches the foo; + then the . fails against the \n. But the next thing we want + to do is match the \n against the \n; if we restored the + string value, we would be back at the foo. + + Because this is used only in specific cases, we don't need to + check all the things that `on_failure_jump' does, to make + sure the right things get saved on the stack. Hence we don't + share its code. The only reason to push anything on the + stack at all is that otherwise we would have to change + `anychar's code to do something besides goto fail in this + case; that seems worse than this. */ + case on_failure_keep_string_jump: + DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt); + + PUSH_FAILURE_POINT (p + mcnt, NULL, -2); + break; + + + /* Uses of on_failure_jump: + + Each alternative starts with an on_failure_jump that points + to the beginning of the next alternative. Each alternative + except the last ends with a jump that in effect jumps past + the rest of the alternatives. (They really jump to the + ending jump of the following alternative, because tensioning + these jumps is a hassle.) + + Repeats start with an on_failure_jump that points past both + the repetition text and either the following jump or + pop_failure_jump back to this on_failure_jump. */ + case on_failure_jump: + on_failure: + DEBUG_PRINT1 ("EXECUTING on_failure_jump"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt); + + /* If this on_failure_jump comes right before a group (i.e., + the original * applied to a group), save the information + for that group and all inner ones, so that if we fail back + to this point, the group's information will be correct. + For example, in \(a*\)*\1, we need the preceding group, + and in \(\(a*\)b*\)\2, we need the inner group. */ + + /* We can't use `p' to check ahead because we push + a failure point to `p + mcnt' after we do this. */ + p1 = p; + + /* We need to skip no_op's before we look for the + start_memory in case this on_failure_jump is happening as + the result of a completed succeed_n, as in \(a\)\{1,3\}b\1 + against aba. */ + while (p1 < pend && (re_opcode_t) *p1 == no_op) + p1++; + + if (p1 < pend && (re_opcode_t) *p1 == start_memory) + { + /* We have a new highest active register now. This will + get reset at the start_memory we are about to get to, + but we will have saved all the registers relevant to + this repetition op, as described above. */ + highest_active_reg = *(p1 + 1) + *(p1 + 2); + if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) + lowest_active_reg = *(p1 + 1); + } + + DEBUG_PRINT1 (":\n"); + PUSH_FAILURE_POINT (p + mcnt, d, -2); + break; + + + /* A smart repeat ends with `maybe_pop_jump'. + We change it to either `pop_failure_jump' or `jump'. */ + case maybe_pop_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt); + { + register unsigned char *p2 = p; + + /* Compare the beginning of the repeat with what in the + pattern follows its end. If we can establish that there + is nothing that they would both match, i.e., that we + would have to backtrack because of (as in, e.g., `a*a') + then we can change to pop_failure_jump, because we'll + never have to backtrack. + + This is not true in the case of alternatives: in + `(a|ab)*' we do need to backtrack to the `ab' alternative + (e.g., if the string was `ab'). But instead of trying to + detect that here, the alternative has put on a dummy + failure point which is what we will end up popping. */ + + /* Skip over open/close-group commands. */ + while (p2 + 2 < pend + && ((re_opcode_t) *p2 == stop_memory + || (re_opcode_t) *p2 == start_memory)) + p2 += 3; /* Skip over args, too. */ + + /* If we're at the end of the pattern, we can change. */ + if (p2 == pend) + { + /* Consider what happens when matching ":\(.*\)" + against ":/". I don't really understand this code + yet. */ + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 + (" End of pattern: change to `pop_failure_jump'.\n"); + } + + else if ((re_opcode_t) *p2 == exactn + || (bufp->newline_anchor && (re_opcode_t) *p2 == endline)) + { + register unsigned char c + = *p2 == (unsigned char) endline ? '\n' : p2[2]; + p1 = p + mcnt; + + /* p1[0] ... p1[2] are the `on_failure_jump' corresponding + to the `maybe_finalize_jump' of this case. Examine what + follows. */ + if ((re_opcode_t) p1[3] == exactn && p1[5] != c) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", + c, p1[5]); + } + + else if ((re_opcode_t) p1[3] == charset + || (re_opcode_t) p1[3] == charset_not) + { + int not = (re_opcode_t) p1[3] == charset_not; + + if (c < (unsigned char) (p1[4] * BYTEWIDTH) + && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) + not = !not; + + /* `not' is equal to 1 if c would match, which means + that we can't change to pop_failure_jump. */ + if (!not) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + } + } + } + p -= 2; /* Point at relative address again. */ + if ((re_opcode_t) p[-1] != pop_failure_jump) + { + p[-1] = (unsigned char) jump; + DEBUG_PRINT1 (" Match => jump.\n"); + goto unconditional_jump; + } + /* Note fall through. */ + + + /* The end of a simple repeat has a pop_failure_jump back to + its matching on_failure_jump, where the latter will push a + failure point. The pop_failure_jump takes off failure + points put on by this pop_failure_jump's matching + on_failure_jump; we got through the pattern to here from the + matching on_failure_jump, so didn't fail. */ + case pop_failure_jump: + { + /* We need to pass separate storage for the lowest and + highest registers, even though we don't care about the + actual values. Otherwise, we will restore only one + register from the stack, since lowest will == highest in + `pop_failure_point'. */ + unsigned dummy_low_reg, dummy_high_reg; + unsigned char *pdummy; + const char *sdummy; + + DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n"); + POP_FAILURE_POINT (sdummy, pdummy, + dummy_low_reg, dummy_high_reg, + reg_dummy, reg_dummy, reg_info_dummy); + } + /* Note fall through. */ + + + /* Unconditionally jump (without popping any failure points). */ + case jump: + unconditional_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */ + DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt); + p += mcnt; /* Do the jump. */ + DEBUG_PRINT2 ("(to 0x%x).\n", p); + break; + + + /* We need this opcode so we can detect where alternatives end + in `group_match_null_string_p' et al. */ + case jump_past_alt: + DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n"); + goto unconditional_jump; + + + /* Normally, the on_failure_jump pushes a failure point, which + then gets popped at pop_failure_jump. We will end up at + pop_failure_jump, also, and with a pattern of, say, `a+', we + are skipping over the on_failure_jump, so we have to push + something meaningless for pop_failure_jump to pop. */ + case dummy_failure_jump: + DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n"); + /* It doesn't matter what we push for the string here. What + the code at `fail' tests is the value for the pattern. */ + PUSH_FAILURE_POINT (0, 0, -2); + goto unconditional_jump; + + + /* At the end of an alternative, we need to push a dummy failure + point in case we are followed by a `pop_failure_jump', because + we don't want the failure point for the alternative to be + popped. For example, matching `(a|ab)*' against `aab' + requires that we match the `ab' alternative. */ + case push_dummy_failure: + DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n"); + /* See comments just above at `dummy_failure_jump' about the + two zeroes. */ + PUSH_FAILURE_POINT (0, 0, -2); + break; + + /* Have to succeed matching what follows at least n times. + After that, handle like `on_failure_jump'. */ + case succeed_n: + EXTRACT_NUMBER (mcnt, p + 2); + DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); + + assert (mcnt >= 0); + /* Originally, this is how many times we HAVE to succeed. */ + if (mcnt > 0) + { + mcnt--; + p += 2; + STORE_NUMBER_AND_INCR (p, mcnt); + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p, mcnt); + } + else if (mcnt == 0) + { + DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", p+2); + p[2] = (unsigned char) no_op; + p[3] = (unsigned char) no_op; + goto on_failure; + } + break; + + case jump_n: + EXTRACT_NUMBER (mcnt, p + 2); + DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); + + /* Originally, this is how many times we CAN jump. */ + if (mcnt) + { + mcnt--; + STORE_NUMBER (p + 2, mcnt); + goto unconditional_jump; + } + /* If don't have to jump any more, skip over the rest of command. */ + else + p += 4; + break; + + case set_number_at: + { + DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); + p1 = p + mcnt; + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt); + STORE_NUMBER (p1, mcnt); + break; + } + + case wordbound: + DEBUG_PRINT1 ("EXECUTING wordbound.\n"); + if (AT_WORD_BOUNDARY (d)) + break; + goto fail; + + case notwordbound: + DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); + if (AT_WORD_BOUNDARY (d)) + goto fail; + break; + + case wordbeg: + DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); + if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1))) + break; + goto fail; + + case wordend: + DEBUG_PRINT1 ("EXECUTING wordend.\n"); + if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1) + && (!WORDCHAR_P (d) || AT_STRINGS_END (d))) + break; + goto fail; + +#ifdef emacs +#ifdef emacs19 + case before_dot: + DEBUG_PRINT1 ("EXECUTING before_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) >= point) + goto fail; + break; + + case at_dot: + DEBUG_PRINT1 ("EXECUTING at_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) != point) + goto fail; + break; + + case after_dot: + DEBUG_PRINT1 ("EXECUTING after_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) <= point) + goto fail; + break; +#else /* not emacs19 */ + case at_dot: + DEBUG_PRINT1 ("EXECUTING at_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) + 1 != point) + goto fail; + break; +#endif /* not emacs19 */ + + case syntaxspec: + DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt); + mcnt = *p++; + goto matchsyntax; + + case wordchar: + DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n"); + mcnt = (int) Sword; + matchsyntax: + PREFETCH (); + if (SYNTAX (*d++) != (enum syntaxcode) mcnt) + goto fail; + SET_REGS_MATCHED (); + break; + + case notsyntaxspec: + DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt); + mcnt = *p++; + goto matchnotsyntax; + + case notwordchar: + DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n"); + mcnt = (int) Sword; + matchnotsyntax: + PREFETCH (); + if (SYNTAX (*d++) == (enum syntaxcode) mcnt) + goto fail; + SET_REGS_MATCHED (); + break; + +#else /* not emacs */ + case wordchar: + DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n"); + PREFETCH (); + if (!WORDCHAR_P (d)) + goto fail; + SET_REGS_MATCHED (); + d++; + break; + + case notwordchar: + DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n"); + PREFETCH (); + if (WORDCHAR_P (d)) + goto fail; + SET_REGS_MATCHED (); + d++; + break; +#endif /* not emacs */ + + default: + abort (); + } + continue; /* Successfully executed one pattern command; keep going. */ + + + /* We goto here if a matching operation fails. */ + fail: + if (!FAIL_STACK_EMPTY ()) + { /* A restart point is known. Restore to that state. */ + DEBUG_PRINT1 ("\nFAIL:\n"); + POP_FAILURE_POINT (d, p, + lowest_active_reg, highest_active_reg, + regstart, regend, reg_info); + + /* If this failure point is a dummy, try the next one. */ + if (!p) + goto fail; + + /* If we failed to the end of the pattern, don't examine *p. */ + assert (p <= pend); + if (p < pend) + { + boolean is_a_jump_n = false; + + /* If failed to a backwards jump that's part of a repetition + loop, need to pop this failure point and use the next one. */ + switch ((re_opcode_t) *p) + { + case jump_n: + is_a_jump_n = true; + case maybe_pop_jump: + case pop_failure_jump: + case jump: + p1 = p + 1; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + + if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n) + || (!is_a_jump_n + && (re_opcode_t) *p1 == on_failure_jump)) + goto fail; + break; + default: + /* do nothing */ ; + } + } + + if (d >= string1 && d <= end1) + dend = end_match_1; + } + else + break; /* Matching at this starting point really fails. */ + } /* for (;;) */ + + if (best_regs_set) + goto restore_best_regs; + + FREE_VARIABLES (); + + return -1; /* Failure to match. */ +} /* re_match_2 */ + +/* Subroutine definitions for re_match_2. */ + + +/* We are passed P pointing to a register number after a start_memory. + + Return true if the pattern up to the corresponding stop_memory can + match the empty string, and false otherwise. + + If we find the matching stop_memory, sets P to point to one past its number. + Otherwise, sets P to an undefined byte less than or equal to END. + + We don't handle duplicates properly (yet). */ + +static boolean +group_match_null_string_p ( unsigned char **p, unsigned char *end, + register_info_type *reg_info ) +{ + int mcnt; + /* Point to after the args to the start_memory. */ + unsigned char *p1 = *p + 2; + + while (p1 < end) + { + /* Skip over opcodes that can match nothing, and return true or + false, as appropriate, when we get to one that can't, or to the + matching stop_memory. */ + + switch ((re_opcode_t) *p1) + { + /* Could be either a loop or a series of alternatives. */ + case on_failure_jump: + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + + /* If the next operation is not a jump backwards in the + pattern. */ + + if (mcnt >= 0) + { + /* Go through the on_failure_jumps of the alternatives, + seeing if any of the alternatives cannot match nothing. + The last alternative starts with only a jump, + whereas the rest start with on_failure_jump and end + with a jump, e.g., here is the pattern for `a|b|c': + + /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6 + /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3 + /exactn/1/c + + So, we have to first go through the first (n-1) + alternatives and then deal with the last one separately. */ + + + /* Deal with the first (n-1) alternatives, which start + with an on_failure_jump (see above) that jumps to right + past a jump_past_alt. */ + + while ((re_opcode_t) p1[mcnt-3] == jump_past_alt) + { + /* `mcnt' holds how many bytes long the alternative + is, including the ending `jump_past_alt' and + its number. */ + + if (!alt_match_null_string_p (p1, p1 + mcnt - 3, + reg_info)) + return false; + + /* Move to right after this alternative, including the + jump_past_alt. */ + p1 += mcnt; + + /* Break if it's the beginning of an n-th alternative + that doesn't begin with an on_failure_jump. */ + if ((re_opcode_t) *p1 != on_failure_jump) + break; + + /* Still have to check that it's not an n-th + alternative that starts with an on_failure_jump. */ + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if ((re_opcode_t) p1[mcnt-3] != jump_past_alt) + { + /* Get to the beginning of the n-th alternative. */ + p1 -= 3; + break; + } + } + + /* Deal with the last alternative: go back and get number + of the `jump_past_alt' just before it. `mcnt' contains + the length of the alternative. */ + EXTRACT_NUMBER (mcnt, p1 - 2); + + if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info)) + return false; + + p1 += mcnt; /* Get past the n-th alternative. */ + } /* if mcnt > 0 */ + break; + + + case stop_memory: + assert (p1[1] == **p); + *p = p1 + 2; + return true; + + + default: + if (!common_op_match_null_string_p (&p1, end, reg_info)) + return false; + } + } /* while p1 < end */ + + return false; +} /* group_match_null_string_p */ + + +/* Similar to group_match_null_string_p, but doesn't deal with alternatives: + It expects P to be the first byte of a single alternative and END one + byte past the last. The alternative can contain groups. */ + +static boolean +alt_match_null_string_p ( unsigned char *p, unsigned char *end, + register_info_type *reg_info ) +{ + int mcnt; + unsigned char *p1 = p; + + while (p1 < end) + { + /* Skip over opcodes that can match nothing, and break when we get + to one that can't. */ + + switch ((re_opcode_t) *p1) + { + /* It's a loop. */ + case on_failure_jump: + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + break; + + default: + if (!common_op_match_null_string_p (&p1, end, reg_info)) + return false; + } + } /* while p1 < end */ + + return true; +} /* alt_match_null_string_p */ + + +/* Deals with the ops common to group_match_null_string_p and + alt_match_null_string_p. + + Sets P to one after the op and its arguments, if any. */ + +static boolean +common_op_match_null_string_p ( unsigned char **p, unsigned char *end, + register_info_type *reg_info ) +{ + int mcnt; + boolean ret; + int reg_no; + unsigned char *p1 = *p; + + switch ((re_opcode_t) *p1++) + { + case no_op: + case begline: + case endline: + case begbuf: + case endbuf: + case wordbeg: + case wordend: + case wordbound: + case notwordbound: +#ifdef emacs + case before_dot: + case at_dot: + case after_dot: +#endif + break; + + case start_memory: + reg_no = *p1; + assert (reg_no > 0 && reg_no <= MAX_REGNUM); + ret = group_match_null_string_p (&p1, end, reg_info); + + /* Have to set this here in case we're checking a group which + contains a group and a back reference to it. */ + + if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE) + REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret; + + if (!ret) + return false; + break; + + /* If this is an optimized succeed_n for zero times, make the jump. */ + case jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if (mcnt >= 0) + p1 += mcnt; + else + return false; + break; + + case succeed_n: + /* Get to the number of times to succeed. */ + p1 += 2; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + + if (mcnt == 0) + { + p1 -= 4; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + } + else + return false; + break; + + case duplicate: + if (!REG_MATCH_NULL_STRING_P (reg_info[*p1])) + return false; + break; + + case set_number_at: + p1 += 4; + + default: + /* All other opcodes mean we cannot match the empty string. */ + return false; + } + + *p = p1; + return true; +} /* common_op_match_null_string_p */ + + +/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN + bytes; nonzero otherwise. */ + +static int +bcmp_translate ( const char *s1, const char *s2, register int len, + char *translate ) +{ + register unsigned char *p1 = (unsigned char *)s1, + *p2 = (unsigned char *)s2; + while (len) + { + if (translate[*p1++] != translate[*p2++]) return 1; + len--; + } + return 0; +} + +/* Entry points for GNU code. */ + +/* re_compile_pattern is the GNU regular expression compiler: it + compiles PATTERN (of length SIZE) and puts the result in BUFP. + Returns 0 if the pattern was valid, otherwise an error string. + + Assumes the `allocated' (and perhaps `buffer') and `translate' fields + are set in BUFP on entry. + + We call regex_compile to do the actual compilation. */ + +const char * +re_compile_pattern ( const char *pattern, int length, + struct re_pattern_buffer *bufp ) +{ + reg_errcode_t ret; + + /* GNU code is written to assume at least RE_NREGS registers will be set + (and at least one extra will be -1). */ + bufp->regs_allocated = REGS_UNALLOCATED; + + /* And GNU code determines whether or not to get register information + by passing null for the REGS argument to re_match, etc., not by + setting no_sub. */ + bufp->no_sub = 0; + + /* Match anchors at newline. */ + bufp->newline_anchor = 1; + + ret = regex_compile (pattern, length, re_syntax_options, bufp); + + return re_error_msg[(int) ret]; +} + +/* Entry points compatible with 4.2 BSD regex library. We don't define + them if this is an Emacs or POSIX compilation. */ + +#if !defined (emacs) && !defined (_POSIX_SOURCE) + +/* BSD has one and only one pattern buffer. */ +static struct re_pattern_buffer re_comp_buf; + +char * +re_comp ( const char *s ) +{ + reg_errcode_t ret; + + if (!s) + { + if (!re_comp_buf.buffer) + return "No previous regular expression"; + return 0; + } + + if (!re_comp_buf.buffer) + { + re_comp_buf.buffer = (unsigned char *) malloc (200); + if (re_comp_buf.buffer == NULL) + return "Memory exhausted"; + re_comp_buf.allocated = 200; + + re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH); + if (re_comp_buf.fastmap == NULL) + return "Memory exhausted"; + } + + /* Since `re_exec' always passes NULL for the `regs' argument, we + don't need to initialize the pattern buffer fields which affect it. */ + + /* Match anchors at newlines. */ + re_comp_buf.newline_anchor = 1; + + ret = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); + + /* Yes, we're discarding `const' here. */ + return (char *) re_error_msg[(int) ret]; +} + + +int +re_exec ( const char *s ) +{ + const int len = strlen (s); + return + 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0); +} +#endif /* not emacs and not _POSIX_SOURCE */ + +/* POSIX.2 functions. Don't define these for Emacs. */ + +#ifndef emacs + +/* regcomp takes a regular expression as a string and compiles it. + + PREG is a regex_t *. We do not expect any fields to be initialized, + since POSIX says we shouldn't. Thus, we set + + `buffer' to the compiled pattern; + `used' to the length of the compiled pattern; + `syntax' to RE_SYNTAX_POSIX_EXTENDED if the + REG_EXTENDED bit in CFLAGS is set; otherwise, to + RE_SYNTAX_POSIX_BASIC; + `newline_anchor' to REG_NEWLINE being set in CFLAGS; + `fastmap' and `fastmap_accurate' to zero; + `re_nsub' to the number of subexpressions in PATTERN. + + PATTERN is the address of the pattern string. + + CFLAGS is a series of bits which affect compilation. + + If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we + use POSIX basic syntax. + + If REG_NEWLINE is set, then . and [^...] don't match newline. + Also, regexec will try a match beginning after every newline. + + If REG_ICASE is set, then we considers upper- and lowercase + versions of letters to be equivalent when matching. + + If REG_NOSUB is set, then when PREG is passed to regexec, that + routine will report only success or failure, and nothing about the + registers. + + It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for + the return codes and their meanings.) */ + +int +regcomp ( regex_t *preg, const char *pattern, int cflags ) +{ + reg_errcode_t ret; + unsigned syntax + = (cflags & REG_EXTENDED) ? + RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC; + + /* regex_compile will allocate the space for the compiled pattern. */ + preg->buffer = 0; + preg->allocated = 0; + + /* Don't bother to use a fastmap when searching. This simplifies the + REG_NEWLINE case: if we used a fastmap, we'd have to put all the + characters after newlines into the fastmap. This way, we just try + every character. */ + preg->fastmap = 0; + + if (cflags & REG_ICASE) + { + unsigned i; + + preg->translate = (char *) malloc (CHAR_SET_SIZE); + if (preg->translate == NULL) + return (int) REG_ESPACE; + + /* Map uppercase characters to corresponding lowercase ones. */ + for (i = 0; i < CHAR_SET_SIZE; i++) + preg->translate[i] = ISUPPER (i) ? tolower (i) : i; + } + else + preg->translate = NULL; + + /* If REG_NEWLINE is set, newlines are treated differently. */ + if (cflags & REG_NEWLINE) + { /* REG_NEWLINE implies neither . nor [^...] match newline. */ + syntax &= ~RE_DOT_NEWLINE; + syntax |= RE_HAT_LISTS_NOT_NEWLINE; + /* It also changes the matching behavior. */ + preg->newline_anchor = 1; + } + else + preg->newline_anchor = 0; + + preg->no_sub = !!(cflags & REG_NOSUB); + + /* POSIX says a null character in the pattern terminates it, so we + can use strlen here in compiling the pattern. */ + ret = regex_compile (pattern, strlen (pattern), syntax, preg); + + /* POSIX doesn't distinguish between an unmatched open-group and an + unmatched close-group: both are REG_EPAREN. */ + if (ret == REG_ERPAREN) ret = REG_EPAREN; + + return (int) ret; +} + + +/* regexec searches for a given pattern, specified by PREG, in the + string STRING. + + If NMATCH is zero or REG_NOSUB was set in the cflags argument to + `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at + least NMATCH elements, and we set them to the offsets of the + corresponding matched substrings. + + EFLAGS specifies `execution flags' which affect matching: if + REG_NOTBOL is set, then ^ does not match at the beginning of the + string; if REG_NOTEOL is set, then $ does not match at the end. + + We return 0 if we find a match and REG_NOMATCH if not. */ + +int +regexec ( const regex_t *preg, const char *string, size_t nmatch, + regmatch_t pmatch[], int eflags ) +{ + int ret; + struct re_registers regs; + regex_t private_preg; + int len = strlen (string); + boolean want_reg_info = !preg->no_sub && nmatch > 0; + + private_preg = *preg; + + private_preg.not_bol = !!(eflags & REG_NOTBOL); + private_preg.not_eol = !!(eflags & REG_NOTEOL); + + /* The user has told us exactly how many registers to return + information about, via `nmatch'. We have to pass that on to the + matching routines. */ + private_preg.regs_allocated = REGS_FIXED; + + if (want_reg_info) + { + regs.num_regs = nmatch; + regs.start = TALLOC (nmatch, regoff_t); + regs.end = TALLOC (nmatch, regoff_t); + if (regs.start == NULL || regs.end == NULL) + return (int) REG_NOMATCH; + } + + /* Perform the searching operation. */ + ret = re_search (&private_preg, string, len, + /* start: */ 0, /* range: */ len, + want_reg_info ? ®s : (struct re_registers *) 0); + + /* Copy the register information to the POSIX structure. */ + if (want_reg_info) + { + if (ret >= 0) + { + unsigned r; + + for (r = 0; r < nmatch; r++) + { + pmatch[r].rm_so = regs.start[r]; + pmatch[r].rm_eo = regs.end[r]; + } + } + + /* If we needed the temporary register info, free the space now. */ + free (regs.start); + free (regs.end); + } + + /* We want zero return to mean success, unlike `re_search'. */ + return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH; +} + + +/* Returns a message corresponding to an error code, ERRCODE, returned + from either regcomp or regexec. We don't use PREG here. */ + +size_t +regerror ( int errcode, const regex_t *preg, char *errbuf, + size_t errbuf_size ) +{ + const char *msg; + size_t msg_size; + + if (preg) preg=0; // Avoid not used warnings + if (errcode < 0 + || errcode >= (sizeof (re_error_msg) / sizeof (re_error_msg[0]))) + /* Only error codes returned by the rest of the code should be passed + to this routine. If we are given anything else, or if other regex + code generates an invalid error code, then the program has a bug. + Dump core so we can fix it. */ + abort (); + + msg = re_error_msg[errcode]; + + /* POSIX doesn't require that we do anything in this case, but why + not be nice. */ + if (! msg) + msg = "Success"; + + msg_size = strlen (msg) + 1; /* Includes the null. */ + + if (errbuf_size != 0) + { + if (msg_size > errbuf_size) + { + strncpy (errbuf, msg, errbuf_size - 1); + errbuf[errbuf_size - 1] = 0; + } + else + strcpy (errbuf, msg); + } + + return msg_size; +} + + +/* Free dynamically allocated space used by PREG. */ + +void +regfree ( regex_t *preg ) +{ + if (preg->buffer != NULL) + free (preg->buffer); + preg->buffer = NULL; + + preg->allocated = 0; + preg->used = 0; + + if (preg->fastmap != NULL) + free (preg->fastmap); + preg->fastmap = NULL; + preg->fastmap_accurate = 0; + + if (preg->translate != NULL) + free (preg->translate); + preg->translate = NULL; +} + +#endif /* not emacs */ + +#ifdef TVComp_BCPP +#pragma option pop +#endif + +#endif // NEEDS_REGEX + +/* +Local variables: +make-backup-files: t +version-control: t +trim-versions-without-asking: nil +End: +*/ diff --git a/tvision/compat/releasec.c b/tvision/compat/releasec.c new file mode 100644 index 0000000..cf526be --- /dev/null +++ b/tvision/compat/releasec.c @@ -0,0 +1,68 @@ +/* Copyright (C) 1996-1998 Robert H”hne */ +/* Modified by Salvador E. Tropea, Vadim Bolodorov and Anatoli Soltan */ +#include + +#ifdef TVCompf_djgpp +#include + +void CLY_ReleaseCPU() +{ + __dpmi_yield(); // Release the time slice +} +#endif // DJGPP + + +#ifdef TVOS_Win32 +#define WIN32_LEAN_AND_MEAN +#include + +// I don't know if the following difference could be unified: +#ifdef TVOSf_NT +// SET: Anatoli's port for NT releases the CPU until the console received +// some message. +extern void __tvWin32Yield(int micros); + +void CLY_ReleaseCPU() +{ + __tvWin32Yield(-1); +} +#else +// By Vadim Beloborodov to be used on WIN32 console +// SET: Vadim's port just waits 0.1 seconds. I think that's because he uses +// another thread for input. +void CLY_ReleaseCPU() +{ + Sleep(100); +} +#endif + +#endif // Win32 + + +#if defined(TVOSf_QNX4) + #include + + static void usleep(unsigned long sleeptime) + { + struct timespec wait; + + wait.tv_nsec=sleeptime; + wait.tv_sec=0; + + do { + if (nanosleep(&wait, &wait)==0) + { + break; + } + } while(1); + } +#endif + +#ifdef TVOS_UNIX +#include + +void CLY_ReleaseCPU() +{ + usleep(1000); // Linux, release 1 ms +} +#endif diff --git a/tvision/compat/snprintf.c b/tvision/compat/snprintf.c new file mode 100644 index 0000000..fc61538 --- /dev/null +++ b/tvision/compat/snprintf.c @@ -0,0 +1,892 @@ +/* + Unix snprintf implementation. + Version 1.1 + Code by Caolán McNamara + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + Revision History: + + 1.1: + * added changes from Miles Bader + * corrected a bug with %f + * added support for %#g + * added more comments :-) + 1.0: + * supporting must ANSI syntaxic_sugars + 0.0: + * suppot %s %c %d + + THANKS(for the patches and ideas): + Miles Bader + Cyrille Rustom + Jacek Slabocewiz + Mike Parker(mouse) + ------------------------------------ + + Modified by Salvador E. Tropea (c) 2003. + Don't blame Caolán for the bugs introduced by me ;-) + I removed all the pre-ANSI previsions because they make the code unreadable +and I don't plan to support such an old compilers. + I modified (or at least tried to ;-) the code to return not the used length +but the length needed to put all. This is the standard behavior and not what +Caolán implemented. In fact this code gets useless without it because I use +a first call without a buffer to determine the length of the buffer in most +cases. + +*/ + +#include + +#ifdef NEEDS_SNPRINTF + +#include +#include /* for atoi() */ +#include +#include /* strlen() and others */ + +/* + * For the FLOATING POINT FORMAT : + * the challenge was finding a way to + * manipulate the Real numbers without having + * to resort to mathematical function(it + * would require to link with -lm) and not + * going down to the bit pattern(not portable) + * + * so a number, a real is: + + real = integral + fraction + + integral = ... + a(2)*10^2 + a(1)*10^1 + a(0)*10^0 + fraction = b(1)*10^-1 + b(2)*10^-2 + ... + + where: + 0 <= a(i) => 9 + 0 <= b(i) => 9 + + from then it was simple math + */ + +/* + * size of the buffer for the integral part + * and the fraction part + */ +#define MAX_INT 99 + 1 /* 1 for the null */ +#define MAX_FRACT 29 + 1 + +/* + * numtoa() uses PRIVATE buffers to store the results, + * So this function is not reentrant + */ +#define itoa(n) numtoa(n, 10, 0, (char **)0) +#define otoa(n) numtoa(n, 8, 0, (char **)0) +#define htoa(n) numtoa(n, 16, 0, (char **)0) +#define dtoa(n, p, f) numtoa(n, 10, p, f) + +#define SWAP_INT(a,b) {int t; t = (a); (a) = (b); (b) = t;} + +/* this struct holds everything we need */ +struct DATA { + int length; + char *holder; + int counter; + const char *pf; +/* FLAGS */ + int width, precision; + int justify; char pad; + int square, space, star_w, star_p, a_long ; +}; + +#define PRIVATE static +#define PUBLIC +/* signature of the functions */ +/* the floating point stuff */ + PRIVATE double pow_10(int); + PRIVATE int log_10(double); + PRIVATE double integral(double, double *); + PRIVATE char * numtoa(double, int, int, char **); + +/* for the format */ + PRIVATE void conv_flag(char *, struct DATA *); + PRIVATE void floating(struct DATA *, double); + PRIVATE void exponent(struct DATA *, double); + PRIVATE void decimal(struct DATA *, double); + PRIVATE void octal(struct DATA *, double); + PRIVATE void hexa(struct DATA *, double); + PRIVATE void strings(struct DATA *, char *); + +/* those are defines specific to snprintf to hopefully + * make the code clearer :-) + */ +#define RIGHT 1 +#define LEFT 0 +#define NOT_FOUND -1 +#define FOUND 1 +#define MAX_FIELD 15 + +/* the conversion flags */ +#define isflag(c) ((c) == '#' || (c) == ' ' || \ + (c) == '*' || (c) == '+' || \ + (c) == '-' || (c) == '.' || \ + isdigit(c)) + +/* round off to the precision */ +#define ROUND(d, p) \ + (d < 0.) ? \ + d - pow_10(-(p)->precision) * 0.5 : \ + d + pow_10(-(p)->precision) * 0.5 + +/* set default precision */ +#define DEF_PREC(p) \ + if ((p)->precision == NOT_FOUND) \ + (p)->precision = 6 + +/* put a char */ +#define PUT_CHAR(c, p) \ + { \ + if ((p)->counter < (p)->length) \ + *(p)->holder++ = (c); \ + (p)->counter++; /* SET: Moved outside if */ \ + } + +/* SET: put a char, no increment */ +#define PUT_EOS(p) \ + { \ + if ((p)->counter <= (p)->length) \ + *(p)->holder = 0; \ + } + +#define PUT_PLUS(d, p) \ + if ((d) > 0. && (p)->justify == RIGHT) \ + PUT_CHAR('+', p) + +#define PUT_SPACE(d, p) \ + if ((p)->space == FOUND && (d) > 0.) \ + PUT_CHAR(' ', p) + +/* pad right */ +#define PAD_RIGHT(p) \ + if ((p)->width > 0 && (p)->justify != LEFT) \ + for (; (p)->width > 0; (p)->width--) \ + PUT_CHAR((p)->pad, p) + +/* pad left */ +#define PAD_LEFT(p) \ + if ((p)->width > 0 && (p)->justify == LEFT) \ + for (; (p)->width > 0; (p)->width--) \ + PUT_CHAR((p)->pad, p) + +/* if width and prec. in the args */ +#define STAR_ARGS(p) \ + if ((p)->star_w == FOUND) \ + (p)->width = va_arg(args, int); \ + if ((p)->star_p == FOUND) \ + (p)->precision = va_arg(args, int) + +/* + * Find the nth power of 10 + */ +PRIVATE double +pow_10(int n) +{ + int i; + double P; + + if (n < 0) + for (i = 1, P = 1., n = -n ; i <= n ; i++) {P *= .1;} + else + for (i = 1, P = 1. ; i <= n ; i++) {P *= 10.0;} + return P; +} + +/* + * Find the integral part of the log in base 10 + * Note: this not a real log10() + I just need and approximation(integerpart) of x in: + 10^x ~= r + * log_10(200) = 2; + * log_10(250) = 2; + */ +PRIVATE int +log_10(double r) +{ + int i = 0; + double result = 1.; + + if (r < 0.) + r = -r; + + if (r < 1.) { + while (result >= r) {result *= .1; i++;} + return (-i); + } else { + while (result <= r) {result *= 10.; i++;} + return (i - 1); + } +} + +/* + * This function return the fraction part of a double + * and set in ip the integral part. + * In many ways it resemble the modf() found on most Un*x + */ +PRIVATE double +integral(double real, double * ip) +{ + int j; + double i, s, p; + double real_integral = 0.; + +/* take care of the obvious */ +/* equal to zero ? */ + if (real == 0.) { + *ip = 0.; + return (0.); + } + +/* negative number ? */ + if (real < 0.) + real = -real; + +/* a fraction ? */ + if ( real < 1.) { + *ip = 0.; + return real; + } +/* the real work :-) */ + for (j = log_10(real); j >= 0; j--) { + p = pow_10(j); + s = (real - real_integral)/p; + i = 0.; + while (i + 1. <= s) {i++;} + real_integral += i*p; + } + *ip = real_integral; + return (real - real_integral); +} + +#define PRECISION 1.e-6 +/* + * return an ascii representation of the integral part of the number + * and set fract to be an ascii representation of the fraction part + * the container for the fraction and the integral part or staticly + * declare with fix size + */ +PRIVATE char * +numtoa(double number, int base, int precision, char ** fract) +{ + register int i, j; + double ip, fp; /* integer and fraction part */ + double fraction; + int digits = MAX_INT - 1; + static char integral_part[MAX_INT]; + static char fraction_part[MAX_FRACT]; + double sign; + int ch; + +/* taking care of the obvious case: 0.0 */ + if (number == 0.) { + integral_part[0] = '0'; + integral_part[1] = '\0'; + fraction_part[0] = '0'; + fraction_part[1] = '\0'; + return integral_part; + } + +/* for negative numbers */ + if ((sign = number) < 0.) { + number = -number; + digits--; /* sign consume one digit */ + } + + fraction = integral(number, &ip); + number = ip; +/* do the integral part */ + if ( ip == 0.) { + integral_part[0] = '0'; + i = 1; + } else { + for ( i = 0; i < digits && number != 0.; ++i) { + number /= base; + fp = integral(number, &ip); + ch = (int)((fp + PRECISION)*base); /* force to round */ + integral_part[i] = (ch <= 9) ? ch + '0' : ch + 'a' - 10; + if (! isxdigit(integral_part[i])) /* bail out overflow !! */ + break; + number = ip; + } + } + +/* Oh No !! out of bound, ho well fill it up ! */ + if (number != 0.) + for (i = 0; i < digits; ++i) + integral_part[i] = '9'; + +/* put the sign ? */ + if (sign < 0.) + integral_part[i++] = '-'; + + integral_part[i] = '\0'; + +/* reverse every thing */ + for ( i--, j = 0; j < i; j++, i--) + SWAP_INT(integral_part[i], integral_part[j]); + +/* the fractionnal part */ + for (i=0, fp=fraction; precision > 0 && i < MAX_FRACT ; i++, precision-- ) { + fraction_part[i] = (int)((fp + PRECISION)*10. + '0'); + if (! isdigit(fraction_part[i])) /* underflow ? */ + break; + fp = (fp*10.0) - (double)(long)((fp + PRECISION)*10.); + } + fraction_part[i] = '\0'; + + if (fract != (char **)0) + *fract = fraction_part; + + return integral_part; + +} + +/* for %d and friends, it puts in holder + * the representation with the right padding + */ +PRIVATE void +decimal(struct DATA *p, double d) +{ + char *tmp; + + tmp = itoa(d); + p->width -= strlen(tmp); + PAD_RIGHT(p); + PUT_PLUS(d, p); + PUT_SPACE(d, p); + while (*tmp) { /* the integral */ + PUT_CHAR(*tmp, p); + tmp++; + } + PAD_LEFT(p); +} + +/* for %o octal representation */ +PRIVATE void +octal(struct DATA *p, double d) +{ + char *tmp; + + tmp = otoa(d); + p->width -= strlen(tmp); + PAD_RIGHT(p); + if (p->square == FOUND) /* had prefix '0' for octal */ + PUT_CHAR('0', p); + while (*tmp) { /* octal */ + PUT_CHAR(*tmp, p); + tmp++; + } + PAD_LEFT(p); +} + +/* for %x %X hexadecimal representation */ +PRIVATE void +hexa(struct DATA *p, double d) +{ + char *tmp; + + tmp = htoa(d); + p->width -= strlen(tmp); + PAD_RIGHT(p); + if (p->square == FOUND) { /* prefix '0x' for hexa */ + PUT_CHAR('0', p); PUT_CHAR(*p->pf, p); + } + while (*tmp) { /* hexa */ + PUT_CHAR((*p->pf == 'X' ? toupper(*tmp) : *tmp), p); + tmp++; + } + PAD_LEFT(p); +} + +/* %s strings */ +PRIVATE void +strings(struct DATA *p, char *tmp) +{ + int i; + + i = strlen(tmp); + if (p->precision != NOT_FOUND) /* the smallest number */ + i = (i < p->precision ? i : p->precision); + p->width -= i; + PAD_RIGHT(p); + while (i-- > 0) { /* put the sting */ + PUT_CHAR(*tmp, p); + tmp++; + } + PAD_LEFT(p); +} + +/* %f or %g floating point representation */ +PRIVATE void +floating(struct DATA *p, double d) +{ + char *tmp, *tmp2; + int i; + + DEF_PREC(p); + d = ROUND(d, p); + tmp = dtoa(d, p->precision, &tmp2); + /* calculate the padding. 1 for the dot */ + p->width = p->width - + ((d > 0. && p->justify == RIGHT) ? 1:0) - + ((p->space == FOUND) ? 1:0) - + strlen(tmp) - p->precision - 1; + PAD_RIGHT(p); + PUT_PLUS(d, p); + PUT_SPACE(d, p); + while (*tmp) { /* the integral */ + PUT_CHAR(*tmp, p); + tmp++; + } + if (p->precision != 0 || p->square == FOUND) + PUT_CHAR('.', p); /* put the '.' */ + if (*p->pf == 'g' || *p->pf == 'G') /* smash the trailing zeros */ + for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--) + tmp2[i] = '\0'; + for (; *tmp2; tmp2++) + PUT_CHAR(*tmp2, p); /* the fraction */ + + PAD_LEFT(p); +} + +/* %e %E %g exponent representation */ +PRIVATE void +exponent(struct DATA *p, double d) +{ + char *tmp, *tmp2; + int j, i; + + DEF_PREC(p); + j = log_10(d); + d = d / pow_10(j); /* get the Mantissa */ + d = ROUND(d, p); + tmp = dtoa(d, p->precision, &tmp2); + /* 1 for unit, 1 for the '.', 1 for 'e|E', + * 1 for '+|-', 3 for 'exp' */ + /* calculate how much padding need */ + p->width = p->width - + ((d > 0. && p->justify == RIGHT) ? 1:0) - + ((p->space == FOUND) ? 1:0) - p->precision - 7; + PAD_RIGHT(p); + PUT_PLUS(d, p); + PUT_SPACE(d, p); + while (*tmp) {/* the integral */ + PUT_CHAR(*tmp, p); + tmp++; + } + if (p->precision != 0 || p->square == FOUND) + PUT_CHAR('.', p); /* the '.' */ + if (*p->pf == 'g' || *p->pf == 'G') /* smash the trailing zeros */ + for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--) + tmp2[i] = '\0'; + for (; *tmp2; tmp2++) + PUT_CHAR(*tmp2, p); /* the fraction */ + + if (*p->pf == 'g' || *p->pf == 'e') { /* the exponent put the 'e|E' */ + PUT_CHAR('e', p); + } else + PUT_CHAR('E', p); + if (j > 0) { /* the sign of the exp */ + PUT_CHAR('+', p); + } else { + PUT_CHAR('-', p); + j = -j; + } + tmp = itoa((double)j); + if (j < 9) { /* need to pad the exponent with 0 '000' */ + PUT_CHAR('0', p); PUT_CHAR('0', p); + } else if (j < 99) + PUT_CHAR('0', p); + while (*tmp) { /* the exponent */ + PUT_CHAR(*tmp, p); + tmp++; + } + PAD_LEFT(p); +} + +/* initialize the conversion specifiers */ +PRIVATE void +conv_flag(char * s, struct DATA * p) +{ + char number[MAX_FIELD/2]; + int i; + + p->precision = p->width = NOT_FOUND; + p->star_w = p->star_p = NOT_FOUND; + p->square = p->space = NOT_FOUND; + p->a_long = p->justify = NOT_FOUND; + p->pad = ' '; + + for(;s && *s ;s++) { + switch(*s) { + case ' ': p->space = FOUND; break; + case '#': p->square = FOUND; break; + case '*': if (p->width == NOT_FOUND) + p->width = p->star_w = FOUND; + else + p->precision = p->star_p = FOUND; + break; + case '+': p->justify = RIGHT; break; + case '-': p->justify = LEFT; break; + case '.': if (p->width == NOT_FOUND) + p->width = 0; + break; + case '0': p->pad = '0'; break; + case '1': case '2': case '3': + case '4': case '5': case '6': + case '7': case '8': case '9': /* gob all the digits */ + for (i = 0; isdigit(*s); i++, s++) + if (i < MAX_FIELD/2 - 1) + number[i] = *s; + number[i] = '\0'; + if (p->width == NOT_FOUND) + p->width = atoi(number); + else + p->precision = atoi(number); + s--; /* went to far go back */ + break; + } + } +} + +PUBLIC int +CLY_vsnprintf(char *string, size_t length, const char * format, va_list args) +{ + struct DATA data; + char conv_field[MAX_FIELD]; + double d; /* temporary holder */ + int state; + int i; + + data.length = length - 1; /* leave room for '\0' */ + data.holder = string; + data.pf = format; + data.counter = 0; + + +/* sanity check, the string must be > 1 + SET: Wrong! we must compute the length! + if (length < 1) + return -1; */ + + + for (; *data.pf /*SET: && (data.counter < data.length)*/; data.pf++) { + if ( *data.pf == '%' ) { /* we got a magic % cookie */ + conv_flag((char *)0, &data); /* initialise format flags */ + for (state = 1; *data.pf && state;) { + switch (*(++data.pf)) { + case '\0': /* a NULL here ? ? bail out */ + PUT_EOS(&data); + return data.counter; + break; + case 'f': /* float, double */ + STAR_ARGS(&data); + d = va_arg(args, double); + floating(&data, d); + state = 0; + break; + case 'g': + case 'G': + STAR_ARGS(&data); + DEF_PREC(&data); + d = va_arg(args, double); + i = log_10(d); + /* + * for '%g|%G' ANSI: use f if exponent + * is in the range or [-4,p] exclusively + * else use %e|%E + */ + if (-4 < i && i < data.precision) + floating(&data, d); + else + exponent(&data, d); + state = 0; + break; + case 'e': + case 'E': /* Exponent double */ + STAR_ARGS(&data); + d = va_arg(args, double); + exponent(&data, d); + state = 0; + break; + case 'u': + case 'd': /* decimal */ + STAR_ARGS(&data); + if (data.a_long == FOUND) + d = va_arg(args, long); + else + d = va_arg(args, int); + decimal(&data, d); + state = 0; + break; + case 'o': /* octal */ + STAR_ARGS(&data); + if (data.a_long == FOUND) + d = va_arg(args, long); + else + d = va_arg(args, int); + octal(&data, d); + state = 0; + break; + case 'x': + case 'X': /* hexadecimal */ + STAR_ARGS(&data); + if (data.a_long == FOUND) + d = va_arg(args, long); + else + d = va_arg(args, int); + hexa(&data, d); + state = 0; + break; + case 'c': /* character */ + d = va_arg(args, int); + PUT_CHAR((char)d, &data); + state = 0; + break; + case 's': /* string */ + STAR_ARGS(&data); + strings(&data, va_arg(args, char *)); + state = 0; + break; + case 'n': + *(va_arg(args, int *)) = data.counter; /* what's the count ? */ + state = 0; + break; + case 'l': + data.a_long = FOUND; + break; + case 'h': + break; + case '%': /* nothing just % */ + PUT_CHAR('%', &data); + state = 0; + break; + case '#': case ' ': case '+': case '*': + case '-': case '.': case '0': case '1': + case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + /* initialize width and precision */ + for (i = 0; isflag(*data.pf); i++, data.pf++) + if (i < MAX_FIELD - 1) + conv_field[i] = *data.pf; + conv_field[i] = '\0'; + conv_flag(conv_field, &data); + data.pf--; /* went to far go back */ + break; + default: + /* is this an error ? maybe bail out */ + state = 0; + break; + } /* end switch */ + } /* end of for state */ + } else { /* not % */ + PUT_CHAR(*data.pf, &data); /* add the char the string */ + } + } + + PUT_EOS(&data); /* the end ye ! */ + + return data.counter; +} + +#ifndef HAVE_SNPRINTF + +PUBLIC int +CLY_snprintf(char *string, size_t length, const char * format, ...) +{ + int rval; + va_list args; + + va_start(args, format); + + rval = CLY_vsnprintf (string, length, format, args); + + va_end(args); + + return rval; +} + +#endif /* HAVE_SNPRINTF */ + + +#ifdef DRIVER + +#include + +/* set of small tests for snprintf() */ +int main() +{ + char holder[100]; + int i; + +/* + printf("Suite of test for snprintf:\n"); + printf("a_format\n"); + printf("printf() format\n"); + printf("snprintf() format\n\n"); +*/ +/* Checking the field widths */ + + printf("/%%d/, 336\n"); + CLY_snprintf(holder, sizeof holder, "/%d/\n", 336); + printf("/%d/\n", 336); + printf("%s\n", holder); + + printf("/%%2d/, 336\n"); + CLY_snprintf(holder, sizeof holder, "/%2d/\n", 336); + printf("/%2d/\n", 336); + printf("%s\n", holder); + + printf("/%%10d/, 336\n"); + CLY_snprintf(holder, sizeof holder, "/%10d/\n", 336); + printf("/%10d/\n", 336); + printf("%s\n", holder); + + printf("/%%-10d/, 336\n"); + CLY_snprintf(holder, sizeof holder, "/%-10d/\n", 336); + printf("/%-10d/\n", 336); + printf("%s\n", holder); + + +/* floating points */ + + printf("/%%f/, 1234.56\n"); + CLY_snprintf(holder, sizeof holder, "/%f/\n", 1234.56); + printf("/%f/\n", 1234.56); + printf("%s\n", holder); + + printf("/%%e/, 1234.56\n"); + CLY_snprintf(holder, sizeof holder, "/%e/\n", 1234.56); + printf("/%e/\n", 1234.56); + printf("%s\n", holder); + + printf("/%%4.2f/, 1234.56\n"); + CLY_snprintf(holder, sizeof holder, "/%4.2f/\n", 1234.56); + printf("/%4.2f/\n", 1234.56); + printf("%s\n", holder); + + printf("/%%3.1f/, 1234.56\n"); + CLY_snprintf(holder, sizeof holder, "/%3.1f/\n", 1234.56); + printf("/%3.1f/\n", 1234.56); + printf("%s\n", holder); + + printf("/%%10.3f/, 1234.56\n"); + CLY_snprintf(holder, sizeof holder, "/%10.3f/\n", 1234.56); + printf("/%10.3f/\n", 1234.56); + printf("%s\n", holder); + + printf("/%%10.3e/, 1234.56\n"); + CLY_snprintf(holder, sizeof holder, "/%10.3e/\n", 1234.56); + printf("/%10.3e/\n", 1234.56); + printf("%s\n", holder); + + printf("/%%+4.2f/, 1234.56\n"); + CLY_snprintf(holder, sizeof holder, "/%+4.2f/\n", 1234.56); + printf("/%+4.2f/\n", 1234.56); + printf("%s\n", holder); + + printf("/%%010.2f/, 1234.56\n"); + CLY_snprintf(holder, sizeof holder, "/%010.2f/\n", 1234.56); + printf("/%010.2f/\n", 1234.56); + printf("%s\n", holder); + +#define BLURB "Outstanding acting !" +/* strings precisions */ + + printf("/%%2s/, \"%s\"\n", BLURB); + CLY_snprintf(holder, sizeof holder, "/%2s/\n", BLURB); + printf("/%2s/\n", BLURB); + printf("%s\n", holder); + + printf("/%%22s/ %s\n", BLURB); + CLY_snprintf(holder, sizeof holder, "/%22s/\n", BLURB); + printf("/%22s/\n", BLURB); + printf("%s\n", holder); + + printf("/%%22.5s/ %s\n", BLURB); + CLY_snprintf(holder, sizeof holder, "/%22.5s/\n", BLURB); + printf("/%22.5s/\n", BLURB); + printf("%s\n", holder); + + printf("/%%-22.5s/ %s\n", BLURB); + CLY_snprintf(holder, sizeof holder, "/%-22.5s/\n", BLURB); + printf("/%-22.5s/\n", BLURB); + printf("%s\n", holder); + +/* see some flags */ + + printf("%%x %%X %%#x, 31, 31, 31\n"); + CLY_snprintf(holder, sizeof holder, "%x %X %#x\n", 31, 31, 31); + printf("%x %X %#x\n", 31, 31, 31); + printf("%s\n", holder); + + printf("**%%d**%% d**%% d**, 42, 42, -42\n"); + CLY_snprintf(holder, sizeof holder, "**%d**% d**% d**\n", 42, 42, -42); + printf("**%d**% d**% d**\n", 42, 42, -42); + printf("%s\n", holder); + +/* other flags */ + + printf("/%%g/, 31.4\n"); + CLY_snprintf(holder, sizeof holder, "/%g/\n", 31.4); + printf("/%g/\n", 31.4); + printf("%s\n", holder); + + printf("/%%.6g/, 31.4\n"); + CLY_snprintf(holder, sizeof holder, "/%.6g/\n", 31.4); + printf("/%.6g/\n", 31.4); + printf("%s\n", holder); + + printf("/%%.1G/, 31.4\n"); + CLY_snprintf(holder, sizeof holder, "/%.1G/\n", 31.4); + printf("/%.1G/\n", 31.4); + printf("%s\n", holder); + + printf("abc%%n\n"); + printf("abc%n", &i); printf("%d\n", i); + CLY_snprintf(holder, sizeof holder, "abc%n", &i); + printf("%s", holder); printf("%d\n\n", i); + + printf("%%*.*s --> 10.10\n"); + CLY_snprintf(holder, sizeof holder, "%*.*s\n", 10, 10, BLURB); + printf("%*.*s\n", 10, 10, BLURB); + printf("%s\n", holder); + + printf("%%%%%%%%\n"); + CLY_snprintf(holder, sizeof holder, "%%%%\n"); + printf("%%%%\n"); + printf("%s\n", holder); + +#define BIG "Hello this is a too big string for the buffer" + printf("A buffer to small of 10, trying to put this:\n"); + printf("<%%>, %s\n", BIG); + i = CLY_snprintf(holder, 10, "%s\n", BIG); + printf("<%s>\n", BIG); + printf("<%s>\n", holder); + printf("Value returned is %d\n",i); + + return 0; +} +#endif + +#endif /* NEEDS_SNPRINTF */ + diff --git a/tvision/compat/ssc_streams.cc b/tvision/compat/ssc_streams.cc new file mode 100644 index 0000000..3de30a0 --- /dev/null +++ b/tvision/compat/ssc_streams.cc @@ -0,0 +1,294 @@ +#include + +#ifdef HAVE_SSC + +#define Uses_SSC_Streams +#define Uses_stdio +#define Uses_stdlib +#define Uses_unistd +#define Uses_fcntl +#define Uses_string +#include + +// Ultra dummies: +SSC_StreamOffT SSC_streambuf::seekoff(SSC_StreamOffT , SSC_IOSSeekDir, + SSC_OpenModeT) +{ + return SSC_StreamOffT(0); +} + +void SSC_streambuf::sync() {} + +void SSC_streambuf::sputc(char ) {} + +void SSC_streambuf::sputn(char *, size_t ) {} + +int SSC_streambuf::sbumpc() { return EOF; } + +size_t SSC_streambuf::sgetn(char *, size_t ) +{ + return size_t(0); +} + +SSC_filebuf::SSC_filebuf() +{ + opened=0; + fde=NULL; + mode=0; +} + +SSC_filebuf::SSC_filebuf(int fh, SSC_OpenModeT aMode) +{ + mode=aMode; + opened=1; + attach(fh); +} + +SSC_filebuf *SSC_filebuf::open(const char *name, SSC_OpenModeT aMode, int prot) +{ + //printf("Open %s\n",name); + mode=aMode; + int flags=0; + // Note: glibc docs lies, O_RDWR!=(O_RDONLY|O_WRONLY) + if (mode & SSC_ios::in) + { + if (mode & SSC_ios::out) + flags|=O_RDWR | O_CREAT; + else + flags|=O_RDONLY; + } + else + { + if (mode & SSC_ios::out) + flags|=O_WRONLY | O_CREAT; + } + if (mode & SSC_ios::trunc) flags|=O_TRUNC; + if (mode & SSC_ios::app) flags|=O_APPEND; + int fh=::open(name,flags,prot); + if (fh==-1) + { + //printf("Error en open\n"); + return NULL; + } + if (mode & SSC_ios::ate) + lseek(fh,0,SEEK_END); + attach(fh); + return this; +} + +SSC_filebuf *SSC_filebuf::attach(int fh) +{ + char sMode[4]; + int index=0; + + if (!mode) mode=SSC_ios::in|SSC_ios::out|SSC_ios::binary; + + if (mode & SSC_ios::in) + sMode[index++]='r'; + else if (mode & SSC_ios::out) + sMode[index++]='w'; + + sMode[index++]=mode & SSC_ios::binary ? 'b' : 't'; + + if ((mode & SSC_ios::in) && (mode & SSC_ios::out)) + sMode[index++]='+'; + + sMode[index]=0; + fde=fdopen(fh,sMode); + if (fde) + opened=1; + else + perror("fdopen"); + //printf("Attach %d %s %d\n",fh,sMode,opened); + + return this; +} + +SSC_filebuf *SSC_filebuf::close() +{ + if (!opened) + return 0; + opened=0; + if (fclose(fde)==0) + return this; + return 0; +} + +SSC_streambuf *SSC_filebuf::setbuf(char *buffer, size_t len) +{ + if (!opened) return NULL; + if (setvbuf(fde,buffer,_IOFBF,len)==0) + return (SSC_streambuf *)1; // :-)) + return NULL; +} + +SSC_StreamOffT SSC_filebuf::seekoff(SSC_StreamOffT pos, SSC_IOSSeekDir dir, + SSC_OpenModeT) +{ + if (!opened) return SSC_StreamOffT(0); + fseek(fde,pos,dir); + return (SSC_StreamOffT)ftell(fde); +} + +void SSC_filebuf::sync() +{ + if (opened) + fflush(fde); +} + +void SSC_filebuf::sputc(char c) +{ + if (opened) + fputc(c,fde); +} + +void SSC_filebuf::sputn(char *data, size_t cant) +{ + if (opened) + fwrite(data,cant,1,fde); +} + +int SSC_filebuf::sbumpc() +{ + if (opened) + return fgetc(fde); + return EOF; +} + +size_t SSC_filebuf::sgetn(char *data, size_t cant) +{ + if (opened) + return fread(data,1,cant,fde); + return size_t(0); +} + +SSC_strstreambuf::SSC_strstreambuf() +{ + buffer=NULL; + tlen=length=offset=0; +} + +SSC_strstreambuf::SSC_strstreambuf(void *buf, int len) +{ + buffer=buf; + tlen=length=len; + offset=0; +} + +SSC_StreamOffT SSC_strstreambuf::seekoff(SSC_StreamOffT pos, SSC_IOSSeekDir dir, + SSC_OpenModeT) +{ + switch (dir) + { + case SSC_ios::beg: + if (pos>=0 && pos<=length) + offset=pos; + break; + case SSC_ios::cur: + if (pos>0) + { + if (length-offset>=pos) + offset+=pos; + } + else + { + if (offset>=pos) + offset+=pos; + } + break; + case SSC_ios::end: + if (pos<=0 && pos<=length) + offset=length+pos; + break; + } + return offset; +} + +void SSC_strstreambuf::sputc(char c) +{ + MakeRoomFor(1); + char *s=(char *)buffer; + s[offset++]=c; +} + +void SSC_strstreambuf::sputn(char *data, size_t cant) +{ + MakeRoomFor(cant); + memcpy(((char *)buffer)+offset,data,cant); + offset+=cant; +} + +int SSC_strstreambuf::sbumpc() +{ + if (offsetavail) + cant=avail; + memcpy(data,((char *)buffer)+offset,cant); + offset+=cant; + return cant; +} + +SSC_strstreambuf::~SSC_strstreambuf() +{ + free(buffer); +} + +void SSC_strstreambuf::MakeRoomFor(size_t bytes) +{ + size_t avail=length-offset; + if (avail>=bytes) + return; + size_t tavail=tlen-offset; + if (tavail>=bytes) + { + length=offset+bytes; + return; + } + tlen=bytes+offset+4096; + buffer=realloc(buffer,tlen); + if (!buffer) + abort(); + length=offset+bytes; +} + +#ifdef TEST +// g++ -DTEST -o /tmp/test -I../include ssc_streams.cc + +int main(int argc, char *argv[]) +{ + CLY_filebuf pp; + pp.open("test.txt",CLY_IOSIn | CLY_IOSOut | CLY_IOSBin,0644); + pp.sputn("Hola\n",5); + pp.pubseekoff(0,CLY_IOSBeg); + char buf[6+5]; + pp.sgetn(buf,5); + buf[5]=0; + printf("%s\n",buf); + + printf("----- strbase test\n"); + CLY_strstreambuf pp2; + pp2.sputn("Hola\n",5); + pp2.sputn("Chau\n",5); + pp2.pubseekoff(0,CLY_IOSBeg); + pp2.sgetn(buf,5+5); + buf[5+5]=0; + printf("%s",buf); + + return 0; +} +#endif + +#endif + diff --git a/tvision/compat/strlwr.c b/tvision/compat/strlwr.c new file mode 100644 index 0000000..73996ad --- /dev/null +++ b/tvision/compat/strlwr.c @@ -0,0 +1,16 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#ifdef NEEDS_STRLWR +#include + +char *strlwr(char *_s) +{ + char *rv = _s; + while (*_s) + { + *_s = tolower((unsigned char)*_s); + _s++; + } + return rv; +} +#endif diff --git a/tvision/compat/strupr.c b/tvision/compat/strupr.c new file mode 100644 index 0000000..a36538c --- /dev/null +++ b/tvision/compat/strupr.c @@ -0,0 +1,16 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#ifdef NEEDS_STRUPR +#include + +char *strupr(char *_s) +{ + char *rv = _s; + while (*_s) + { + *_s = toupper((unsigned char)*_s); + _s++; + } + return rv; +} +#endif diff --git a/tvision/compat/ticks.c b/tvision/compat/ticks.c new file mode 100644 index 0000000..1861406 --- /dev/null +++ b/tvision/compat/ticks.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1996-1998 Robert H”hne */ +/* Modified by Salvador E. Tropea, Vadim Bolodorov and Anatoli Soltan */ +#include + +#ifdef TVCompf_djgpp +#include +#include + +unsigned short CLY_Ticks(void) +{ + return _farpeekw(_dos_ds,0x46c); +} +#endif // DJGPP + + + +#ifdef TVOS_Win32 +#define WIN32_LEAN_AND_MEAN +#include //for GetTickCount + +unsigned short CLY_Ticks(void) +{ + // X ms * 1s/1000ms * 18.2 ticks/s = X/55 ticks, roughly. + return GetTickCount() / 55; +} +#endif // Win32 + + + +#ifdef TVOS_UNIX +#include +#include /* for NULL */ + +unsigned short CLY_Ticks(void) +{ + struct timeval val; + gettimeofday(&val,(struct timezone *)NULL); + return (val.tv_sec*18 + (val.tv_usec*18)/1000000); +// return clock(); +} +#endif + diff --git a/tvision/compat/unc.c b/tvision/compat/unc.c new file mode 100644 index 0000000..ade318f --- /dev/null +++ b/tvision/compat/unc.c @@ -0,0 +1,96 @@ +/* + Copyright (c) 2000 by Anatoli Soltan. + Covered by the GPL license. +*/ +#include + +#ifdef NEEDS_UNC +#define WIN32_LEAN_AND_MEAN +#include +#include + +#if (__MINGW32_MAJOR_VERSION>=2) && !defined(alloca) + #define alloca __builtin_alloca +#endif + +int CLY_isUNC_helper_NT(const char* server, const char* share); +int CLY_isUNC_helper_95(const char* server, const char* share); + +#define is_slash(c) (c == '/' || c == '\\') +#define is_term(c) (c == '/' || c == '\\' || c == '\0') + +/**[txh]******************************************************************** + + Description: + Returns 1 if passed path looks like an UNC name. That is it starts with +//server. + + Return: 1 if UNC + +***************************************************************************/ + +int CLY_IsUNC(const char* path) +{ + if (!is_slash(path[0]) || !is_slash(path[1]) || is_term(path[2])) + return 0; + return 1; +} + +/**[txh]******************************************************************** + + Description: + Returns 1 if passed path refers to a network share. That is the path +matches //server/share[/[.]] mask and the share really exists. + + Return: 1 if that's an existing share. + +***************************************************************************/ + +int CLY_IsUNCShare(const char* path) +{ + static int nt = -1; + char* path2 = (char*)alloca(strlen(path) + 1); + char* p; + const char *server, *share; + + strcpy(path2, path); + + if (!CLY_IsUNC(path2)) + return 0; + server = path2 + 2; + p = strchr(server, '/'); + if (!p) + p = strchr(server, '\\'); + if (!p) + return 0; + if (p[1] == '\0') + return 0; + *p = '\0'; + + share = p + 1; + p = strchr(share, '/'); + if (!p) + p = strchr(share, '\\'); + if (!p || p[1] == '\0' || (p[1] == '.' && p[2] == '\0')) + { + int ret; + if (p) *p = '\0'; + if (nt == -1 || nt == 1) + { + ret = CLY_isUNC_helper_NT(server, share); + nt = !(ret == -1); + } + if (nt == 0) + { + ret = CLY_isUNC_helper_95(server, share); + if (ret == -1) nt = -1, ret = 0; + } + return ret; + } + + return 0; +} +#endif // NEEDS_UNC + +/* vi: set ts=8 sw=2 : */ + diff --git a/tvision/compat/unc_95.c b/tvision/compat/unc_95.c new file mode 100644 index 0000000..f8041a1 --- /dev/null +++ b/tvision/compat/unc_95.c @@ -0,0 +1,112 @@ +/* + Copyright (c) 2000 by Anatoli Soltan. + Covered by the GPL license. +*/ +#include + +#ifdef NEEDS_UNC +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include + +#if (__MINGW32_MAJOR_VERSION>=2) && !defined(alloca) + #define alloca __builtin_alloca +#endif + +#if _MSC_VER >= 1400 + #undef strupr + #define strupr(a) _strupr(a) +#endif + +static HMODULE hLib; +static API_RET_TYPE +(APIENTRY *pNetShareGetInfo) ( + const char FAR * pszServer, + const char FAR * pszNetName, + short sLevel, + char FAR * pbBuffer, + unsigned short cbBuffer, + unsigned short FAR * pcbTotalAvail + ); + +/**[txh]******************************************************************** + + Description: + Internal helper to validate an UNC for Win9x/Me. + + Return: 1 if that's an existing share. + +***************************************************************************/ + +int CLY_isUNC_helper_95(const char* server, const char* share) +{ + struct share_info_1* pshi1; + struct share_info_50* pshi50; + NET_API_STATUS status; + short level; + unsigned short cbTotalAvail; + int ret; + char *userver, *ushare; + + /* + * Win95 wants server name to be prefixed by two slashes and share + * name to be uppercased. + */ + userver = alloca(strlen(server) + 3); + ushare = alloca(strlen(share) + 1); + userver[0] = '/'; + userver[1] = '/'; + strcpy(userver + 2, server); + strcpy(ushare, share); + strupr(ushare); + + if (!hLib) + { + hLib = LoadLibrary(TEXT("SVRAPI.DLL")); + if (!hLib) + { + ret = -1; + goto clean; + } + } + if (!pNetShareGetInfo) + { + pNetShareGetInfo = (void*)GetProcAddress(hLib, "NetShareGetInfo"); + if (!pNetShareGetInfo) + { + ret = -1; + goto clean; + } + } + + level = 50; + status = (*pNetShareGetInfo)(userver, ushare, level, NULL, 0, &cbTotalAvail); + if (status == ERROR_INVALID_LEVEL) + { + level = 1; + status = (*pNetShareGetInfo)(userver, ushare, level, NULL, 0, &cbTotalAvail); + } + if (status != NERR_BufTooSmall) + return 0; + + pshi1 = (struct share_info_1 *)malloc(cbTotalAvail); + pshi50 = (struct share_info_50 *)pshi1; + status = (*pNetShareGetInfo)(userver, ushare, level, (char*)pshi1, cbTotalAvail, &cbTotalAvail); + ret = (status == 0) && + ((level == 1 ? pshi1->shi1_type : pshi50->shi50_type) == STYPE_DISKTREE); + free(pshi1); + return ret; + +clean: + if (hLib) + { + FreeLibrary(hLib); + hLib = NULL; + pNetShareGetInfo = NULL; + } + return ret; +} +#endif // NEEDS_UNC + diff --git a/tvision/compat/unc_nt.c b/tvision/compat/unc_nt.c new file mode 100644 index 0000000..c3842af --- /dev/null +++ b/tvision/compat/unc_nt.c @@ -0,0 +1,109 @@ +/* + Copyright (c) 2000 by Anatoli Soltan. + Covered by the GPL license. +*/ +#include + +#ifdef NEEDS_UNC +#define WIN32_LEAN_AND_MEAN +/* UNICODE must be defined because all Net APIs on WinNT are UNICODE */ +#define UNICODE +#include +#include +#include +#include +#include + +#if (__MINGW32_MAJOR_VERSION>=2) && !defined(alloca) + #define alloca __builtin_alloca +#endif + +static HMODULE hLib; +static NET_API_STATUS +(NET_API_FUNCTION *pNetShareGetInfo) ( + IN LPTSTR servername, + IN LPTSTR netname, + IN DWORD level, + OUT LPBYTE *bufptr + ); +static NET_API_STATUS +(NET_API_FUNCTION *pNetApiBufferFree) ( + IN LPVOID Buffer + ); + +/**[txh]******************************************************************** + + Description: + Internal helper to validate an UNC for Win NT (2k, XP, etc.). + + Return: 1 if that's an existing share. + +***************************************************************************/ + +int CLY_isUNC_helper_NT(const char* server, const char* share) +{ + SHARE_INFO_1* pshi; + NET_API_STATUS status; + int serverlen, sharelen; + WCHAR *wserver, *wshare; + int ret; + + if (!hLib) + { + hLib = LoadLibraryA("NETAPI32.DLL"); + if (!hLib) + { + ret = -1; + goto clean; + } + } + if (!pNetShareGetInfo) + { + pNetShareGetInfo = (void*)GetProcAddress(hLib, "NetShareGetInfo"); + if (!pNetShareGetInfo) + { + ret = -1; + goto clean; + } + } + if (!pNetApiBufferFree) + { + pNetApiBufferFree = (void*)GetProcAddress(hLib, "NetApiBufferFree"); + if (!pNetApiBufferFree) + { + ret = -1; + goto clean; + } + } + + serverlen = strlen(server); + sharelen = strlen(share); + wserver = (WCHAR*)alloca((serverlen + 1) * sizeof(WCHAR)); + wshare = (WCHAR*)alloca((sharelen + 1) * sizeof(WCHAR)); + + MultiByteToWideChar(CP_ACP, 0, server, serverlen, wserver, serverlen); + MultiByteToWideChar(CP_ACP, 0, share, sharelen, wshare, sharelen); + wserver[serverlen] = 0; + wshare[sharelen] = 0; + + status = (*pNetShareGetInfo)(wserver, wshare, 1, (LPBYTE*)&pshi); + if (status == ERROR_CALL_NOT_IMPLEMENTED) + { + ret = -1; + goto clean; + } + ret = (status == 0) && (pshi->shi1_type == STYPE_DISKTREE); + (*pNetApiBufferFree)(pshi); + return ret; + +clean: + if (hLib) + { + FreeLibrary(hLib); + hLib = NULL; + pNetShareGetInfo = NULL; + pNetApiBufferFree = NULL; + } + return ret; +} +#endif diff --git a/tvision/compat/validfilename.c b/tvision/compat/validfilename.c new file mode 100644 index 0000000..7704c97 --- /dev/null +++ b/tvision/compat/validfilename.c @@ -0,0 +1,51 @@ +/* + Copyright (C) 1996-1998 Robert H”hne + Copyright (C) 2000 Vadim Beloborodov + Copyright (C) 2000 Anatoli Soltan + Copyright (C) 2000 Salvador E. Tropea + Covered by the GPL license. +*/ + +#define Uses_string +#include + +#ifdef TVCompf_djgpp +#include +static const char * const IllegalChars1 = ";,=+<>|\"[]/"; +static const char * const IllegalChars2 = "<>|/\""; + +inline static +const char *GetInvalidChars(const char *fileName) +{ + // SET: Added a check for LFNs, in LFN drives ;,[]=+ are valid + if (_use_lfn(fileName)) + return IllegalChars2; + return IllegalChars1; +} +#else +static const char * const IllegalChars = "<>|/\""; + +static +const char *GetInvalidChars(const char *unused) +{ + if (unused) unused=0; + return IllegalChars; +} +#endif + +int CLY_ValidFileName(const char *fileName) +{ + static const char * illegalChars; + const char *slash=strrchr(fileName,DIRSEPARATOR); + + illegalChars=GetInvalidChars(fileName); + if (!slash) + { + if (strpbrk(fileName,illegalChars) != 0) + return 0; + return 1; + } + if (strpbrk(slash+1,illegalChars) != 0) + return 0; + return CLY_PathValid(fileName); +} diff --git a/tvision/compat/yieldpro.c b/tvision/compat/yieldpro.c new file mode 100644 index 0000000..91c2bb0 --- /dev/null +++ b/tvision/compat/yieldpro.c @@ -0,0 +1,75 @@ +#include + +#ifdef TVCompf_djgpp +#include +#include + +void CLY_YieldProcessor(int micros) +{ + __dpmi_yield(); + if (micros>0) + usleep(micros); +} +#endif + +#if defined(TVOSf_QNX4) + #include + + static void usleep(unsigned long sleeptime) + { + struct timespec wait; + + wait.tv_sec=0; + wait.tv_nsec=sleeptime; + + do { + if (nanosleep(&wait, &wait)==0) + { + break; + } + } while(1); + } +#endif // TVOSf_QNX4 + +#ifdef TVOS_UNIX +#include + // See if this system have the POSIX function + #if 0 //def _POSIX_PRIORITY_SCHEDULING + #include + + void CLY_YieldProcessor(int micros) + { + sched_yield(); + if (micros>0) + usleep(micros); + } + #else + // No POSIX, just sleep + void CLY_YieldProcessor(int micros) + { + if (micros<0) + micros=10000; // 10 ms + usleep(micros); + } + #endif +#endif + +#ifdef TVComp_BCPP //TVOSf_NT +void CLY_YieldProcessor(int micros) +{ + extern void __tvWin32Yield(int micros); + if (micros<0) + micros=27472; // 1000000 / (18.2 * 2) + __tvWin32Yield(micros); +} +#endif + +#if defined(TVOS_Win32) && !defined(TVComp_BCPP) //!defined(TVOSf_NT) +#define WIN32_LEAN_AND_MEAN +#include + +void CLY_YieldProcessor(int micros) +{ + Sleep(micros/1000); +} +#endif diff --git a/tvision/config.pl b/tvision/config.pl new file mode 100644 index 0000000..c3a7444 --- /dev/null +++ b/tvision/config.pl @@ -0,0 +1,1355 @@ +#!/usr/bin/perl +# Copyright (C) 1999-2009 by Salvador E. Tropea (SET), +# see copyrigh file for details +# +# To specify the compilation flags define the CFLAGS environment variable. +# + +require "miscperl.pl"; +require "conflib.pl"; + +# If the script is newer discard the cache. +#GetCache() unless (-M 'config.pl' < -M 'configure.cache'); +GetVersion(''); + +# I never tested with an older version, you can try reducing it. +$GPMVersionNeeded='1.10'; +# I never tested with an older version, you can try reducing it. +#$NCursesVersionNeeded='1.9.9'; +# That's a test to see if that works: +$NCursesVersionNeeded='1.8.6'; +$DJGPPVersionNeeded='2.0.2'; +$AllegroVersionNeeded='4'; +unlink $ErrorLog; +$UseDummyIntl=0; + +SeeCommandLine(); + +if ($JustSpec) + { + UpdateSpec(); + exit 0; + } + +print "Configuring Turbo Vision v$Version library\n\n"; +# Determine the OS +$OS=DetectOS(); +# Test for a working gcc +$GCC=CheckGCC(); +# Determine C flags +$CFLAGS=FindCFLAGS(); +# Determine C++ flags +$CXXFLAGS=FindCXXFLAGS(); +# Extra lib directories +$LDExtraDirs=FindLDExtraDirs(); +# Check if gcc can compile C++ +$GXX=CheckGXX(); +# Which architecture are we using? +DetectCPU(); +# 32 or 64 bits pointers? +DetectPointersSize(); +# Some platforms aren't easy to detect until we can compile. +DetectOS2(); +# The prefix can be better determined if we know all the rest +# about the environment +LookForPrefix(); +# Only gnu make have the command line and commands we use. +LookForGNUMake(); +# Same for ar, it could be `gar' +$GAR=LookForGNUar(); +# Similar for install tool. +LookForGNUinstall(); +# Look for xgettext +LookForGettextTools(); +# Is the right djgpp? +if ($OS eq 'DOS') + { + LookForDJGPP($DJGPPVersionNeeded); + } + +if ($OS eq 'UNIX') + { + LookForGPM($GPMVersionNeeded); + LookForNCurses($NCursesVersionNeeded); + LookForKeysyms(); + LookForXlib(); + # Used for X11 driver. Linux implementation of POSIX threads is very bad + # and needs a lot of workarounds. Some of them could be just bugs in the + # glibc I use but the fact is that the needed tricks make it very Linux + # dependent. + LookForPThread() if $OSf eq 'Linux'; + LookForOutB(); + } +if ($Compf eq 'Cygwin') + {# Cygwin incorporates a XFree86 port + LookForXlib(); + } +LookForIntlSupport(); +LookForAllegro($AllegroVersionNeeded); +LookForEndianess(); +LookForMaintainerTools() if $conf{'MAINTAINER_MODE'} eq 'yes'; + +print "\n"; +GenerateMakefile(); +# +# For the examples +# +$here=RunRedirect('pwd',$ErrorLog); +chop($here); +if (!$here && ($OS ne 'UNIX')) + {# command.com, cmd.exe, etc. have it. + $here=`cd`; + chop($here); + } +if ($Compf eq 'MinGW') + { + $here=~s/\\/\//g; + } +$realPrefix=@conf{'real-prefix'}; +$realPrefix=@conf{'prefix'} unless $realPrefix; +# Path for the includes, used for examples +$MakeDefsRHIDE[1]='TVSRC=../../include '; +$MakeDefsRHIDE[1].=$here.'/include ' unless $conf{'libs-here'} eq 'no'; +$MakeDefsRHIDE[1].=$realPrefix.'/include/rhtvision'; +$MakeDefsRHIDE[1].=' '.$conf{'X11IncludePath'} if (@conf{'HAVE_X11'} eq 'yes'); +# Path reported by rhtv-config --include +$MakeDefsRHIDE[11]='INCLUDE='.$realPrefix.'/include/rhtvision'; +$MakeDefsRHIDE[11].=' '.$conf{'X11IncludePath'} if (@conf{'HAVE_X11'} eq 'yes'); +# Extra path for the includes, used for the library +$MakeDefsRHIDE[9]='EXTRA_INCLUDE_DIRS='.$conf{'EXTRA_INCLUDE_DIRS'}; +$MakeDefsRHIDE[7]='RHIDE_LIBS='; +# Libraries needed +$MakeDefsRHIDE[2]='RHIDE_OS_LIBS='; +# RHIDE doesn't know about anything different than DJGPP and Linux so -lstdc++ must +# be added for things like FreeBSD or SunOS. But not for QNX. +$MakeDefsRHIDE[2].=substr($stdcxx,2); # unless (($OS eq 'DOS') || ($OSf eq 'Linux') || ($OSf eq 'QNXRtP')); +# Linux, Solaris and FreeBSD have gettext in its C library. +$OSUSesIntl=!(($OSf eq 'Linux') || ($OSf eq 'Solaris') || ($OSf eq 'FreeBSD')); +if ($OSUSesIntl) + { + if ((@conf{'intl-force-dummy'} ne 'yes') && (@conf{'intl'} eq 'yes')) + { + $MakeDefsRHIDE[2].=' intl'; + } + else + {# Use the dummy unless the user requested not to use it + if ((@conf{'intl-force-dummy'} eq 'yes') || (@conf{'no-intl'} ne 'yes')) + { + $MakeDefsRHIDE[2].=' tvfintl'; + $UseDummyIntl=1; + } + } + } +$MakeDefsRHIDE[2].=' iconv' if (@conf{'iconv'} eq 'yes') && !$UseDummyIntl; +$MakeDefsRHIDE[2].=' '.$conf{'NameCurses'} if ($conf{'ncurses'} ne 'no') && ($OS eq 'UNIX'); +$MakeDefsRHIDE[2].=' m' if ($OS eq 'UNIX'); +$MakeDefsRHIDE[2].=' gpm' if @conf{'HAVE_GPM'} eq 'yes'; +$MakeDefsRHIDE[2].=' '.$conf{'X11Lib'} if ($conf{'HAVE_X11'} eq 'yes'); +$MakeDefsRHIDE[2].=' mss' if @conf{'mss'} eq 'yes'; +$MakeDefsRHIDE[2].=' intl' if ((($OSf eq 'FreeBSD') || ($OSf eq 'QNXRtP')) && ($conf{'intl'} eq 'yes')); +$MakeDefsRHIDE[2].=' pthread' if $conf{'HAVE_LINUX_PTHREAD'} eq 'yes'; +$MakeDefsRHIDE[2].=' termlib unix' if ($OSf eq 'QNX4'); +if ($conf{'HAVE_ALLEGRO'} eq 'yes') + { + $aux=`allegro-config --libs`; + $a1=$aux; + $aux=~s/\-L(\S+)//g; + $AllegroLibs=$aux; + $aux=~s/\-l//g; + $MakeDefsRHIDE[2].=" $aux"; + $aux=$a1; + $aux=~s/\-l(\S+)//g; + $aux=~s/\-L//g; + $AllegroPath=$aux; + } +if ($OS eq 'UNIX') + { + $MakeDefsRHIDE[0]='RHIDE_STDINC=/usr/include /usr/local/include /usr/include/g++ /usr/local/include/g++ /usr/lib/gcc-lib /usr/local/lib/gcc-lib'; + if (@conf{'HAVE_X11'} eq 'yes') + { + $aux=$conf{'X11IncludePath'} ? ' '.$conf{'X11IncludePath'} : ' /usr/X11R6/include'; + $MakeDefsRHIDE[0].=$aux; + $MakeDefsRHIDE[9].=$aux; + } + $MakeDefsRHIDE[3]='TVOBJ='.$LDExtraDirs.' '; + # QNX 6.2 beta 3 workaround + $MakeDefsRHIDE[3].='/lib ' if ($OSf eq 'QNXRtP'); + # Link with installed libraries + $MakeDefsRHIDE[3].=$realPrefix.'/lib '; + $MakeDefsRHIDE[3].='../../makes '; + $MakeDefsRHIDE[3].=$here.'/makes ' unless $conf{'libs-here'} eq 'no'; + $MakeDefsRHIDE[3].='../../intl/dummy ' if $UseDummyIntl; + $MakeDefsRHIDE[3].=$conf{'X11LibPath'}.' ' if ($conf{'HAVE_X11'} eq 'yes'); + $MakeDefsRHIDE[3].=$AllegroPath.' ' if $conf{'HAVE_ALLEGRO'} eq 'yes'; + } +elsif ($OS eq 'DOS') + { + $MakeDefsRHIDE[0]='RHIDE_STDINC=$(DJDIR)/include $(DJDIR)/lang/cxx $(DJDIR)/lib/gcc-lib'; + # DJGPP's gcc includes djgpp.ver from the same directory where specs + $a=`redir -eo $GCC -v`; + if ($a=~/(\w:)(.*)\/specs/i) + { + $here=RunRedirect('pwd',$ErrorLog); + chop($here); + chdir("$1$2"); + $a=RunRedirect('pwd',$ErrorLog); + chop($a); + chdir($here); + $MakeDefsRHIDE[0].=" $a" + } + $MakeDefsRHIDE[3]='TVOBJ=../../makes '; + $MakeDefsRHIDE[3].=$here.'/makes ' unless $conf{'libs-here'} eq 'no'; + $MakeDefsRHIDE[3].=$realPrefix.'/lib '.$LDExtraDirs; + $MakeDefsRHIDE[3].=' ../../intl/dummy' if $UseDummyIntl; + $MakeDefsRHIDE[3].=$AllegroPath.' ' if $conf{'HAVE_ALLEGRO'} eq 'yes'; + } +elsif ($OS eq 'Win32') + { + $MakeDefsRHIDE[0]='RHIDE_STDINC='; + $MakeDefsRHIDE[2].=' gdi32'; # Needed for WinGr driver + $MakeDefsRHIDE[3]='TVOBJ=../../makes '; + $MakeDefsRHIDE[3].=$here.'/makes ' unless $conf{'libs-here'} eq 'no'; + $MakeDefsRHIDE[3].=$realPrefix.'/lib '.$LDExtraDirs; + $MakeDefsRHIDE[3].=' ../../intl/dummy' if $UseDummyIntl; + $MakeDefsRHIDE[3].=' '.$conf{'X11LibPath'} if ($conf{'HAVE_X11'} eq 'yes'); + $MakeDefsRHIDE[3].=$AllegroPath.' ' if $conf{'HAVE_ALLEGRO'} eq 'yes'; + } +$MakeDefsRHIDE[4]='STDCPP_LIB='.$stdcxx; +# C options for dynamic lib +if ($OSf ne 'Darwin') + { + $MakeDefsRHIDE[5]='SHARED_CODE_OPTION=-fPIC'; + $MakeDefsRHIDE[5].=' -shared' if ($OSf eq 'QNXRtP'); + } +else + {# PPC code is always position independent + # However, the linker doesn't allow "common" symbols in shared libraries. + $MakeDefsRHIDE[5]='SHARED_CODE_OPTION=-fno-common'; + } +# Flags to link as a dynamic lib +$ldflags1='RHIDE_LDFLAGS='; +$ldflags2=$ldflags1; +if ($OS eq 'UNIX') + { + if ($OSf ne 'Darwin') + { + $soname='-soname'; + if ($OSf eq 'Solaris') + { + system("$GCC -v 2> test.ld"); + $test=cat('test.ld'); + unlink 'test.ld'; + # Why?! I think gcc should translate it when using the native ld. + $soname='-h' if $test=~'ccs/bin/ld'; + } + $ldflags1.='-L/lib' if ($OSf eq 'QNXRtP'); + $ldflags1.=' -shared -Wl,'.$soname.',librhtv.so.'.$Version; + } + else + {# Darwin semantic for dynamic libs is quite different + $ldflags1.='-dynamiclib -install_name '.$realPrefix.'/lib/librhtv.'.$Version.'.dylib'; + $ldflags1.=' -compatibility_version '.$Version.' -current_version '.$Version; + } + $libs=$conf{'X11Lib'}; + $libs=~s/(\S+)/-l$1/g; + $aux=''; + $aux.=" -L".$conf{'X11LibPath'}." $libs" if @conf{'HAVE_X11'} eq 'yes'; + $aux.=' -lgpm' if @conf{'HAVE_GPM'} eq 'yes'; + $aux.=(($OSf eq 'QNXRtP') ? ' -lncursesS' : ' -lncurses') unless $conf{'ncurses'} eq 'no'; + $aux.=" $stdcxx -lm -lc"; + $aux.=' -lpthread' if $conf{'HAVE_LINUX_PTHREAD'} eq 'yes'; + $aux.=' '.$AllegroLibs if ($conf{'HAVE_ALLEGRO'} eq 'yes'); + $aux.=' libtvfintl.a' if ($OSf eq 'Darwin') && $UseDummyIntl; + $MakeDefsRHIDE[7].=$aux; + } + +$MakeDefsRHIDE[8]="LIB_VER=$Version"; +$MakeDefsRHIDE[10]="LIB_VER_MAJOR=$VersionMajor"; + +ModifyMakefiles('intl/dummy/Makefile'); +$MakeDefsRHIDE[6]=$ldflags1; +CreateRHIDEenvs('makes/rhide.env','compat/rhide.env'); +$MakeDefsRHIDE[6]=$ldflags2; +CreateRHIDEenvs('examples/rhide.env'); + +# Repeated later for other targets +CreateConfigH(); + +# Help BC++ target +system("perl confignt.pl"); + +# +# Adjust .mak files +# +print "Makefiles for examples.\n"; +chdir('examples'); +`perl patchenv.pl`; +chdir('..'); + +print "Makefiles for translations.\n"; +ReplaceText('intl/gnumake.in','intl/Makefile'); +UpdateSpec(); + +print "\nSuccesful configuration!\n\n"; + +GiveAdvice(); +CreateCache(); +unlink $ErrorLog; +unlink 'test.exe'; + +sub UpdateSpec() +{ + $ReplaceTags{'version'}=$Version; + ReplaceText('redhat/librhtv.spec.in',"redhat/librhtv-$Version.spec"); + ReplaceText('qnxrtp/tvision.qpg.in',"qnxrtp/tvision.qpg"); +} + +sub SeeCommandLine +{ + my $i; + + foreach $i (@ARGV) + { + if ($i eq '--help') + { + ShowHelp(); + die "\n"; + } + elsif ($i=~'--prefix=(.*)') + { + $conf{'prefix'}=$1; + } + elsif ($i=~'--real-prefix=(.*)') + { + $conf{'real-prefix'}=$1; + } + elsif ($i eq '--no-intl') + { + $conf{'no-intl'}='yes'; + } + elsif ($i eq '--force-dummy') + { + $conf{'intl-force-dummy'}='yes'; + } + elsif ($i=~'--cflags=(.*)') + { + @conf{'CFLAGS'}=$1; + } + elsif ($i=~'--cxxflags=(.*)') + { + @conf{'CXXFLAGS'}=$1; + } + elsif ($i eq '--fhs') + { + $conf{'fhs'}='yes'; + } + elsif ($i eq '--no-fhs') + { + $conf{'fhs'}='no'; + } + elsif ($i=~'--X11lib=(.*)') + { + $conf{'X11Lib'}=$1; + } + elsif ($i eq '--with-mss') + { + $conf{'mss'}='yes'; + } + elsif ($i eq '--without-mss') + { + $conf{'mss'}='no'; + } + elsif ($i=~'--x-include=(.*)') + { + $conf{'X11IncludePath'}=$1; + } + elsif ($i=~'--x-lib=(.*)') + { + $conf{'X11LibPath'}=$1; + } + elsif ($i eq '--with-debug') + { + $conf{'debugInfo'}='yes'; + } + elsif ($i eq '--without-debug') + { + $conf{'debugInfo'}='no'; + } + elsif ($i eq '--with-ssc') + { + $conf{'HAVE_SSC'}='yes'; + } + elsif ($i eq '--without-ssc') + { + $conf{'HAVE_SSC'}='no'; + } + elsif ($i eq '--no-libs-here') + { + $conf{'libs-here'}='no'; + } + elsif ($i eq '--enable-maintainer-mode') + { + $conf{'MAINTAINER_MODE'}='yes'; + } + elsif ($i eq '--just-spec') + { + $JustSpec=1; + } + elsif ($i eq '--with-pthread') + { + $conf{'try-pthread'}='yes'; + } + elsif ($i eq '--without-pthread') + { + $conf{'try-pthread'}='no'; + } + elsif ($i eq '--without-static') + { + $conf{'no-static'}='yes'; + } + elsif ($i eq '--without-dynamic') + { + $conf{'no-dynamic'}='yes'; + } + elsif ($i eq '--unsafe-memcpy') + { + $conf{'HAVE_UNSAFE_MEMCPY'}='yes'; + } + elsif ($i eq '--safe-memcpy') + { + $conf{'HAVE_UNSAFE_MEMCPY'}='no'; + } + elsif ($i=~'--include=(.*)') + { + $conf{'EXTRA_INCLUDE_DIRS'}.=" $1"; + } + elsif ($i eq '--debug') + { + $conf{'CFLAGS'}= + $conf{'CXXFLAGS'}='-O2 -Wall -Werror -gstabs+3'; + } + # For compatibility with autoconf: + # LinCS/tiger - ignore some autoconf generated params + elsif (($i=~'--cache-file=(.*)') || ($i=~'--srcdir=(.*)') || ($i=~'--enable-ltdl-convenience')) + { + } + else + { + ShowHelp(); + die "Unknown option: $i\n"; + } + } +} + +sub ShowHelp +{ + print "Available options:\n\n"; + print "Flags:\n"; + print "--cflags=val : normal C flags [default is env. CFLAGS].\n"; + print "--cxxflags=val : normal C++ flags [default is env. CXXFLAGS].\n"; + print "--debug : selects C/C++ switches for debugging\n"; + + print "\nPaths and library names:\n"; + print "--x-include=path: X11 include path [/usr/X11R6/lib].\n"; + print "--x-lib=path : X11 library path [/usr/X11R6/include].\n"; + print "--X11lib=val : Name of X11 libraries [default is X11 Xmu].\n"; + print "--include=path : Add this path for includes. Repeat for each dir.\n"; + print "--no-libs-here : Don't use the sources path for libs.\n"; + + print "\nIntallation:\n"; + print "--prefix=path : defines the base directory for installation.\n"; + print "--fhs : force the FHS layout under UNIX.\n"; + print "--no-fhs : force to not use the FHS layout under UNIX.\n"; + print "--with-debug : install dynamic library without running strip.\n"; + print "--without-debug : run strip to reduce the size [default]\n"; + print "--real-prefix=pa: real prefix, for Debian package\n"; + + print "\nLibraries:\n"; + print "--force-dummy : use the dummy intl library even when gettext is detected.\n"; + print "--no-intl : don't use international support.\n"; + print "--without-static : don't create the static library.\n"; + print "--without-dynamic: don't create the dynamic library.\n"; + print "--with-mss : compiles with MSS memory debugger.\n"; + print "--without-mss : compiles without MSS [default].\n"; + print "--with-ssc : compiles using Simple Streams Compatibility.\n"; + print "--without-ssc : compiles without SSC [default].\n"; + print "--with-pthread : uses pthread for X11 driver.\n"; + print "--without-pthread: avoids pthread for X11 driver [default].\n"; + + print "\nOthers:\n"; + print "--enable-maintainer-mode:\n"; + print " : enables header dependencies and other stuff needed\n"; + print " for developement, not just use the editor.\n"; + print "--just-spec : update RPMs spec file and exit.\n"; + print "--unsafe-memcpy : disable the use of memcpy when memory overlaps\n"; + print "--help : displays this text.\n"; +} + +sub GiveAdvice +{ + if ((@conf{'intl'} eq 'no') && (@conf{'no-intl'} ne 'yes')) + { + print "\n"; + print "* The international support was disabled because gettext library could not\n"; + print " be detected.\n"; + if ($OSf eq 'Linux') + { + print " Starting with glibc 2.0 this is included in libc, perhaps your system\n"; + print " just lacks the propper header file.\n"; + } + elsif ($OS eq 'DOS') + { + print " Install the gtxtNNNb.zip package from the v2gnu directory of djgpp's\n"; + print " distribution. Read the readme file for more information.\n"; + } + elsif ($Compf eq 'MinGW') + { + print " That's normal for MinGW.\n"; + } + elsif ($Compf eq 'Cygwin') + { + print " Install gettext library.\n"; + } + } + if ($UseDummyIntl) + { + print " [[[[[[[*******************>>>>> IMPORTANT!!! <<<<<*******************]]]]]]]\n"; + print " You must link with libtvfintl.a or you'll get undefined symbols. To avoid\n"; + print " using this library reconfigure using --no-intl. Read about it in the readme.\n"; + print " [[[[[[[*******************>>>>> IMPORTANT!!! <<<<<*******************]]]]]]]\n"; + } + if ((@conf{'HAVE_GPM'} eq 'no') && ($OSf eq 'Linux')) + { + print "\n"; + print "* No mouse support for console! please install the libgpm package needed\n"; + print " for development. (i.e. libgpmg1-dev_1.13-5.deb).\n"; + } + if (@conf{'GNU_Make'} ne 'make') + { + print "\n"; + print "* Please use $conf{'GNU_Make'} instead of make command.\n"; + } + if ((@conf{'HAVE_X11'} eq 'no') && ($OS eq 'UNIX')) + { + print "\n"; + print "* No X11 support detected. If X11 is installed make sure you have the\n"; + print " development package installed (i.e. xlibs-dev). Also check the options\n"; + print " to specify the paths for X11 libs and headers\n"; + } +} + +sub LookForEndianess +{ + + my $test; + + print 'Checking endianess: '; + + if (@conf{'TV_BIG_ENDIAN'} eq 'yes') + { + print "big endian (cached)\n"; + return; + } + if (@conf{'TV_BIG_ENDIAN'} eq 'no') + { + print "little endian (cached)\n"; + return; + } + $test=' +#include +int main(void) +{ + int a=1; + char *s=(char *)&a; + printf("%s\n",s[0]==1 ? "little" : "big"); + return 0; +} +'; + $test=RunGCCTest($GCC,'c',$test,''); + $test=~s/\W//g; + $conf{'TV_BIG_ENDIAN'}=($test eq "big") ? 'yes' : 'no'; + print "$test endian\n"; +} + +sub LookForIntlSupport +{ + my $vNeed=$_[0]; + my ($test,$a,$djdir,$intllib,$intltest,$libdir); + + print 'Checking for international support: '; + if (@conf{'intl-force-dummy'} eq 'yes') + { + print "using dummy by user request.\n"; + $conf{'intl'}='yes'; + $conf{'iconv'}='no'; + return; + } + if (@conf{'no-intl'} eq 'yes') + { + print "disabled by user request.\n"; + $conf{'intl'}='no'; + $conf{'iconv'}='no'; + #`cp include/tv/nointl.h include/tv/intl.h`; + return; + } + if (@conf{'intl'} eq 'yes') + { + print "yes (cached)\n"; + return; + } + if (@conf{'intl'} eq 'no') + { + print "no (cached)\n"; + return; + } + if ($OS eq 'DOS') + { # gettext 0.10.32 port have a bug in the headers, correct it + $djdir=@ENV{'DJDIR'}; + $a=cat("$djdir/include/libintl.h"); + if (length($a) && $a=~/\@INCLUDE_LOCALE_H@/) + { + $a=~s/\@INCLUDE_LOCALE_H\@//; + replace("$djdir/include/libintl.h",$a); + } + } + $intltest=' +#include +#define FORCE_INTL_SUPPORT +#include +int main(void) +{ + printf("%s\n",_("OK")); + return 0; +} +'; + $intllib=(($OS eq 'DOS') || ($OS eq 'Win32') || ($OSf eq 'FreeBSD') || ($OSf eq 'QNXRtP')) ? '-lintl' : ''; + $libdir=$LDExtraDirs; + $libdir=~s/(\S+)/-L$1/g; + $test=RunGCCTest($GCC,'c',$intltest,'-Iinclude/ '.$libdir.' '.$intllib); + $test=~s/\W//g; + if ($test ne "OK") + { + print "no, additional check required.\n"; + print "Checking for extra libs for international support: "; + $test=RunGCCTest($GCC,'c',$intltest,'-Iinclude/ '.$intllib.' -liconv'); + $test=~s/\W//g; + if ($test ne "OK") + { + print "none found\n"; + print "International support absent or non-working\n"; + $conf{'intl'}='no'; + $conf{'iconv'}='no'; + } + else + { + print "-liconv, OK\n"; + $conf{'intl'}='yes'; + $conf{'iconv'}='yes'; + } + } + else + { + print "yes OK\n"; + $conf{'intl'}='yes'; + $conf{'iconv'}='no'; + } +} + +sub LookForKeysyms +{ + my $test; + + print 'Looking for X keysyms definitions: '; + if (@conf{'HAVE_KEYSYMS'}) + { + print "@conf{'HAVE_KEYSYMS'} (cached)\n"; + return; + } + $test=' +#include +#include +int main(void) +{ + if (XK_Return!=0) + printf("OK\n"); + return 0; +} +'; + $test=RunGCCTest($GCC,'c',$test,''); + $test=~s/\W//g; + if ($test eq "OK") + { + $conf{'HAVE_KEYSYMS'}='yes'; + print " yes OK\n"; + } + else + { + $conf{'HAVE_KEYSYMS'}='no'; + print " no, disabling enhanced support for Eterm 0.8.10+\n"; + } +} + +sub LookForXlib() +{ + my ($test,$o,$libs,$testPr,$libs); + + print 'Looking for X11 libs: '; + if (@conf{'HAVE_X11'}) + { + print "@conf{'HAVE_X11'} (cached)\n"; + return; + } + $testPr=' +#include +#include +#include +#include +Display *Test() +{ return XOpenDisplay(""); } +int main(void) +{ + printf("OK, %d.%d\n",X_PROTOCOL,X_PROTOCOL_REVISION); + return 0; +} +'; + $conf{'X11LibPath'}='/usr/X11R6/lib' unless $conf{'X11LibPath'}; + # Looks like Cygwin does all static! + $libs=($Compf eq 'Cygwin') ? 'Xmu Xt SM ICE X11' : 'X11 Xmu'; + # QNX4 does all static! + $libs='Xmu Xt SM ICE X11 socket' if ($OSf eq 'QNX4'); + $conf{'X11Lib'}=$libs unless $conf{'X11Lib'}; + $libs=$conf{'X11Lib'}; + $libs=~s/(\S+)/-l$1/g; + $o=''; + $o.='-I'.$conf{'X11IncludePath'} if $conf{'X11IncludePath'}; + $o.=" -L$conf{'X11LibPath'} $libs"; + $test=RunGCCTest($GCC,'c',$testPr,$o); + if ($test=~/OK, (\d+)\.(\d+)/) + { + $conf{'HAVE_X11'}='yes'; + print "yes OK (X$1 rev $2)\n"; + } + else + { + if (!$conf{'X11IncludePath'}) + { + $conf{'X11IncludePath'}='/usr/X11R6/include'; + $o.=" -I$conf{'X11IncludePath'} -L$conf{'X11LibPath'} $libs"; + $test=RunGCCTest($GCC,'c',$testPr,$o); + if ($test=~/OK, (\d+)\.(\d+)/) + { + $conf{'HAVE_X11'}='yes'; + print "yes OK (X$1 rev $2)\n"; + return; + } + } + $conf{'HAVE_X11'}='no'; + print "no, disabling X11 version\n"; + } +} + +# +# GlibC 2.1.3 defines it by itself, lamentably doesn't have any protection +# mechanism to avoid collisions with the kernel headers, too bad. +# +sub LookForOutB +{ + my $test; + + print 'Looking for outb definition in sys/io.h: '; + if (@conf{'HAVE_OUTB_IN_SYS'}) + { + print "@conf{'HAVE_OUTB_IN_SYS'} (cached)\n"; + return; + } + $test=' +#include +#include +#ifdef __i386__ +void Test(void) { outb(10,0x300); } +#endif +int main(void) +{ + printf("OK\n"); + return 0; +} +'; + $test=RunGCCTest($GCC,'c',$test,''); + $test=~s/\W//g; + $conf{'HAVE_OUTB_IN_SYS'}=($test eq "OK") ? 'yes' : 'no'; + print "@conf{'HAVE_OUTB_IN_SYS'}\n"; + #print ">$test<\n"; +} + +sub LookForGPM +{ + my $vNeed=$_[0],$test; + + print 'Looking for gpm library: '; + if (@conf{'gpm'}) + { + print "@conf{'gpm'} (cached) OK\n"; + return; + } + $test=' +#include +#include +int main(void) +{ + int version; + printf("%s",Gpm_GetLibVersion(&version)); + return 0; +} +'; + $test=RunGCCTest($GCC,'c',$test,'-lgpm'); + if (!length($test)) + { + #print "\nError: gpm library not found, please install gpm $vNeed or newer\n"; + #print "Look in $ErrorLog for potential compile errors of the test\n"; + #CreateCache(); + #die "Missing library\n"; + $conf{'HAVE_GPM'}='no'; + print " no, disabling mouse support\n"; + return; + } + if (!CompareVersion($test,$vNeed)) + { + #print "$test, too old\n"; + #print "Please upgrade your gpm library to version $vNeed or newer.\n"; + #print "You can try with $test forcing the configure scripts.\n"; + #CreateCache(); + #die "Old library\n"; + $conf{'HAVE_GPM'}='no'; + print " too old, disabling mouse support\n"; + return; + } + $conf{'gpm'}=$test; + $conf{'HAVE_GPM'}='yes'; + print "$test OK\n"; +} + +sub LookForAllegro +{ + my $vNeed=$_[0],$test; + + print 'Looking for allegro library: '; + if (@conf{'HAVE_ALLEGRO'}) + { + print "@conf{'HAVE_ALLEGRO'} (cached)\n"; + return; + } + $test=`allegro-config --version`; + chomp $test; + if (!length($test)) + { + $conf{'HAVE_ALLEGRO'}='no'; + print " no, disabling AlCon\n"; + return; + } + if (!CompareVersion($test,$vNeed)) + { + $conf{'HAVE_ALLEGRO'}='no'; + print " too old, disabling AlCon\n"; + return; + } + $conf{'HAVE_ALLEGRO'}='yes'; + print "$test OK\n"; +} + +sub LookForNCurses +{ + my ($vNeed)=@_; + my ($result,$test); + + print 'Looking for ncurses library: '; + if (@conf{'ncurses'}) + { + print "@conf{'ncurses'} (cached) OK\n"; + return; + } + # Assume it is -lncurses + if ($OSf ne 'QNXRtP') + { + $conf{'NameCurses'}='ncurses' + } + else + { + $conf{'NameCurses'}='ncursesS' + } + $test=' +#include +#if defined(__QNX__) && !defined(__QNXNTO__) + #include +#else + #include +#endif +void dummy() {initscr();} +int main(void) +{ + printf(NCURSES_VERSION); + return 0; +} +'; + $result=RunGCCTest($GCC,'c',$test,'-lncurses') if ($OSf ne 'QNX4'); + $result=RunGCCTest($GCC,'c',$test,'-lncurses -lunix') if ($OSf eq 'QNX4'); + if (!length($result)) + {# Try again with -lcurses, In Solaris ncurses is installed this way + $result=RunGCCTest($GCC,'c',$test,'-lcurses'); + if (!length($result)) + { + print "no, disabling UNIX driver\n"; + $conf{'ncurses'}='no'; + return; + } + $conf{'NameCurses'}='curses'; + } + if (!CompareVersion($result,$vNeed)) + { + print "$result, too old, disabling UNIX driver\n"; + $conf{'ncurses'}='no'; + return; + } + print "$result OK\n"; + @conf{'ncurses'}=$result; + + print 'Checking if ncurses have define_key: '; + $test=' +#include +#include +void dummy(void) { define_key("\x1B[8~",KEY_F(59)); /* End */ } +int main(void) +{ + printf("Ok\n"); + return 0; +} +'; + $result=RunGCCTest($GCC,'c',$test,'-l'.$conf{'NameCurses'}); + $result=~s/\W//g; + if ($result eq 'Ok') + { + print "yes\n"; + $conf{'HAVE_DEFINE_KEY'}=1; + } + else + { + print "no\n"; + $conf{'HAVE_DEFINE_KEY'}=0; + } +} + +sub LookForGettextTools +{ + my $test; + + print 'Looking for xgettext: '; + if (@conf{'xgettext'}) + { + print @conf{'xgettext'}." (cached)\n"; + return; + } + #$test=`xgettext --version`; + $test=RunRedirect('xgettext --version',$ErrorLog); + if ($test=~/(\d+\.\d+(\.\d+)?)/) + { + print "$1\n"; + $conf{'xgettext'}=$1; + } + else + { + print "no\n"; + $conf{'xgettext'}='no'; + } +} + +sub LookForRecode +{ + my $test; + + print 'Looking for recode: '; + if (@conf{'recode'}) + { + print @conf{'recode'}." (cached)\n"; + return; + } + #$test=`recode --version`; + $test=RunRedirect('recode --version',$ErrorLog); + if ($test=~/(\d+\.\d+(\.\d+)?)/) + { + print "$1\n"; + $conf{'recode'}=$1; + if (CompareVersion($test,'3.5')) + { + $conf{'recode_sep'}='..'; + } + else + { + $conf{'recode_sep'}=':'; + } + } + else + { + print "no\n"; + $conf{'recode'}='no'; + } +} + +sub LookForPThread +{ + my $test; + + if ($conf{'try-pthread'} ne 'yes') + { + $conf{'HAVE_LINUX_PTHREAD'}='no'; + return; + } + + print 'Looking for pthread (LinuxThreads) library: '; + if (@conf{'HAVE_LINUX_PTHREAD'}) + { + print "@conf{'HAVE_LINUX_PTHREAD'} (cached)\n"; + return; + } + $test=' +// We need it for recursive mutex +#define _GNU_SOURCE +#include +#include + +static pthread_t th; +static pthread_mutex_t mutex; + +void *Test(void *unused) +{// The OK will be printed only if the thread worked + printf("OK\n"); + return NULL; +} + +int main(int argc, char *argv[]) +{// Test the attribute for recursive mutex. + pthread_mutexattr_t mt_attr; + pthread_mutexattr_init(&mt_attr); + pthread_mutexattr_settype(&mt_attr,PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&mutex,&mt_attr); + // Create a thread + pthread_create(&th,NULL,Test,NULL); + // Wait until it finishes + pthread_join(th,NULL); + return 0; +} +'; + $test=RunGCCTest($GCC,'c',$test,'-lpthread'); + if (!length($test)) + { + $conf{'HAVE_LINUX_PTHREAD'}='no'; + print " no, disabling X11 update thread option\n"; + return; + } + $conf{'HAVE_LINUX_PTHREAD'}='yes'; + print "OK\n"; +} + +sub DetectPointersSize() +{ + my $test; + + print 'Looking for pointer size: '; + if ($conf{'HAVE_64BITS_POINTERS'}) + { + print ($conf{'HAVE_64BITS_POINTERS'} eq 'yes' ? '64' : '32')."bits (cached)\n"; + return; + } + + $test=' +#include + +int main(void) +{ + printf("%d\n",(int) sizeof(void *)); + return 0; +} +'; + $test=RunGCCTest($GCC,'c',$test,''); + $test=~s/\W//g; + if ($test eq '8') + { + $conf{'HAVE_64BITS_POINTERS'}='yes'; + print " 64 bits\n"; + } + elsif ($test eq '4') + { + $conf{'HAVE_64BITS_POINTERS'}='no'; + print " 32 bits\n"; + } + else + { + CreateCache(); + die "Unknown pointer size!!\n"; + } +} + +sub GenerateMakefile +{ + my ($text,$rep,$makeDir,$ver,$internac,$maintain); + my ($dosta,$dodyn,$nameSO,$nameSOM,$nameSOV,$stripDebug); + + print "Generating Makefile\n"; + $text=cat('Makefile.in'); + if (!$text) + { + CreateCache(); + die "Can't find Makefile.in!!\n"; + } + $internac=@conf{'xgettext'} ne 'no'; + $maintain=@conf{'MAINTAINER_MODE'} eq 'yes'; + + $dosta=@conf{'no-static'} ne 'yes'; + $dodyn=($OS eq 'UNIX') && ($OSf ne 'QNX4') && (@conf{'no-dynamic'} ne 'yes'); + if (!$dosta && !$dodyn) + { + CreateCache(); + die "No static nor dynamic library created!!\n"; + } + + $rep =''; + $rep.=' maintainance' if $maintain; + $rep.=' static-lib' if $dosta; + $rep.=' rhtv-config$(EXE_EXT)'; + $rep.=' dynamic-lib' if $dodyn; + $rep.=' internac' if ($internac); + $text=~s/\@targets\@/$rep/g; + $text=~s/\@OS\@/$OS/g; + $text=~s/\@prefix\@/@conf{'prefix'}/g; + $text=~s/\@exe_ext\@/$ExeExt/g; + $text=~s/\@maintainer_mode\@/MAINTAINER_MODE=1/g if $maintain; + $text=~s/\@maintainer_mode\@//g unless $maintain; + $text=~s/\@install\@/@conf{'GNU_INSTALL'}/; + $text=~s/\@darwin\@/DARWIN=1/g if $OSf eq 'Darwin'; + $text=~s/\@darwin\@//g if $OSf ne 'Darwin'; + + $makeDir='makes'; + + # Write target maintainance rule: + $rep=''; + $rep="maintainance:\n\t\$(MAKE) -C $makeDir -f maintain.mak" if $maintain; + $text=~s/\@maintainance_rule\@/$rep/g; + + # Write target rules: + $rep=''; + if ($dosta) + { + $rep.="static-lib:\n\t\$(MAKE) -C $makeDir -f librhtv.mkf"; + $rep.="\n\tranlib $makeDir/librhtv.a" if $conf{'UseRanLib'}; + $rep.="\n"; + } + if ($dodyn) + { + $rep.="\ndynamic-lib: intl-dummy\n\t\$(MAKE) DYNAMIC_LIB=1 -C $makeDir -f librhtv.mkf\n"; + + if ($OSf ne 'Darwin') + { + $nameSO='librhtv.so'; + $nameSOM="librhtv.so.$VersionMajor"; + $nameSOV="librhtv.so.$Version"; + } + else + {# Darwin uses a different name + $nameSO='librhtv.dylib'; + $nameSOM="librhtv.$VersionMajor.dylib"; + $nameSOV="librhtv.$Version.dylib"; + } + # Note: -sf should work for Solaris 9 but at least in the machines at S.F. + # it doesn't. So we just delete the file and do the link. + $rep.="\t-cd $makeDir; rm -f $nameSO; ln -s $nameSOV $nameSO\n"; + $rep.="\t-cd $makeDir; rm -f $nameSOM; ln -s $nameSOV $nameSOM\n"; + } + if ($internac) + { + $rep.="\ninternac:\n"; + $rep.="\t\$(MAKE) -C intl\n"; + } + $text=~s/\@target_rules\@/$rep/g; + $rep="intl-dummy:\n\t\$(MAKE) -C intl/dummy\n"; + $rep.="\tcp intl/dummy/libtvfintl.a $makeDir\n"; + $rep.="\tranlib $makeDir/libtvfintl.a\n" if $conf{'UseRanLib'}; + $text=~s/\@intl_dummy_rule\@/$rep/g; + + $text=~s/\@GCC\@/$GCC/g; + + # Write install stuff + # What versions of the library we will install + $rep=''; + $rep.='install-static ' if $dosta; + $rep.='install-dynamic ' if $dodyn; + $rep.='install-internac ' if $internac; + $text=~s/\@installers\@/$rep/g; + + # Headers + + $rep= GenInstallDir('0755','$(prefix)/include/rhtvision'); + $rep.="\trm -f \$(prefix)/include/rhtvision/*.h\n"; + $rep.="\t".GenInstallFiles('0644','include/*.h','$(prefix)/include/rhtvision'); + $rep.="\t".GenInstallDir('0755','$(prefix)/include/rhtvision/tv'); + $rep.="\t".GenInstallFiles('0644','include/tv/*.h','$(prefix)/include/rhtvision/tv'); + if ($OS eq 'DOS') + { + $rep.="\t".GenInstallDir('0755','$(prefix)/include/rhtvision/tv/dos'); + $rep.="\t".GenInstallFiles('0644','include/tv/dos/*.h','$(prefix)/include/rhtvision/tv/dos'); + } + if ($OS eq 'UNIX') + { + $rep.="\t".GenInstallDir('0755','$(prefix)/include/rhtvision/tv/linux'); + $rep.="\t".GenInstallFiles('0644','include/tv/linux/*.h','$(prefix)/include/rhtvision/tv/linux'); + } + if ($OSf eq 'QNXRtP') + { + $rep.="\t".GenInstallDir('0755','$(prefix)/include/rhtvision/tv/qnxrtp'); + $rep.="\t".GenInstallFiles('0644','include/tv/qnxrtp/*.h','$(prefix)/include/rhtvision/tv/qnxrtp'); + } + if ($OS eq 'Win32') + { + $rep.="\t".GenInstallDir('0755','$(prefix)/include/rhtvision/tv/win32'); + $rep.="\t".GenInstallFiles('0644','include/tv/win32/*.h','$(prefix)/include/rhtvision/tv/win32'); + } + if (@conf{'HAVE_X11'} eq 'yes') + { + $rep.="\t".GenInstallDir('0755','$(prefix)/include/rhtvision/tv/x11'); + $rep.="\t".GenInstallFiles('0644','include/tv/x11/*.h','$(prefix)/include/rhtvision/tv/x11'); + } + $rep.="\t".GenInstallDir('0755','$(prefix)/include/rhtvision/cl'); + $rep.="\t".GenInstallFiles('0644','include/cl/*.h','$(prefix)/include/rhtvision/cl'); + $text=~s/\@install_headers\@/$rep/g; + + # Dummy replacement for i8n library + $rep ="install-intl-dummy: intl-dummy\n"; + $rep.="\t".GenInstallDir('0755','$(libdir)'); + $rep.="\t".GenInstallFiles('0644','intl/dummy/libtvfintl.a','$(libdir)'); + # In Darwin the linker checks the time stamp of the ranlib pass and the one of + # the file. It complains if we use ranlib and then copy the file. + $rep.="\tranlib \$(libdir)/libtvfintl.a\n" if $conf{'UseRanLib'}; + $text=~s/\@intl_dummy_install_rule\@/$rep/g; + + # Static library + $rep=''; + if ($dosta) + { + $rep.="install-static: static-lib\n"; + $rep.="\t".GenInstallDir('0755','$(libdir)'); + $rep.="\t".GenInstallFiles('0644',"$makeDir/librhtv.a",'$(libdir)'); + } + + if ($dodyn) + {# Dynamic library + $ver=($OSf eq 'FreeBSD') ? $nameSOM : $nameSOV; + $rep.="\ninstall-dynamic: dynamic-lib\n"; + $rep.="\t".GenInstallDir('0755','$(libdir)'); + $rep.="\trm -f \$(libdir)/$nameSO\n"; + $rep.="\trm -f \$(libdir)/$nameSOM\n"; + $rep.="\trm -f \$(libdir)/$nameSOV\n"; + $rep.="\tcd \$(libdir); ln -s $ver $nameSO\n"; + $rep.="\tcd \$(libdir); ln -s $ver $nameSOV\n" if $OSf eq 'FreeBSD'; + $rep.="\t".GenInstallFiles('0644',"$makeDir/$ver",'$(libdir)'); + $stripDebug=($OSf eq 'Darwin') ? '-S' : '--strip-debug'; + $rep.="\tstrip $stripDebug \$(libdir)/$ver\n" unless $conf{'debugInfo'} eq 'yes'; + # FreeBSD: merge data from libdir. + # Darwin: doesn't have ldconfig. + if ($OSf ne 'Darwin') + { + $rep.=($OSf eq 'FreeBSD') ? "\t-ldconfig -m \$(libdir)\n" : "\t-ldconfig\n"; + } + } + if ($internac) + { + $rep.="\ninstall-internac:\n\t\$(MAKE) -C intl install\n"; + } + $text=~s/\@install_rules\@/$rep/g; + + # rhtv-config installation + $rep= GenInstallDir('0755','$(prefix)/bin'); + $rep.="\t".GenInstallFiles('0755','rhtv-config$(EXE_EXT)','$(prefix)/bin'); + $text=~s/\@install_config\@/$rep/g; + + $rep= "clean:\n"; + $rep.="\trm -f $makeDir/librhtv.so*\n"; + $rep.="\trm -f $makeDir/obj/*.o\n"; + $rep.="\trm -f $makeDir/obj/*.lo\n"; + $rep.="\trm -f $makeDir/librhtv.a\n"; + $rep.="\trm -f compat/obj/*.o\n"; + $rep.="\trm -f compat/obj/*.lo\n"; + $rep.="\trm -f intl/dummy/*.o\n"; + $rep.="\trm -f intl/dummy/*.lo\n"; + $rep.="\trm -f intl/dummy/*.a\n"; + $rep.="\t-\$(MAKE) -C examples clean\n"; + $rep.="\t-\$(MAKE) -C intl clean\n"; + $rep.="\trm -f configure.cache\n"; + $rep.="\trm -f rhtv-config\$(EXE_EXT)\n"; + $text=~s/\@clean\@/$rep/g; + + replace('Makefile',$text); +} + +sub CreateConfigH +{ + my $text="/* Generated automatically by the configure script */"; + my $old; + + print 'Generating configuration header: '; + + $conf{'HAVE_NCURSES'}=($conf{'ncurses'} ne 'no') && ($OS eq 'UNIX') ? 'yes' : 'no'; + $text.=ConfigIncDefYes('HAVE_NCURSES','ncurses library'); + $text.=ConfigIncDef('HAVE_DEFINE_KEY','ncurses 4.2 or better have define_key (In Linux)'); + $text.=ConfigIncDefYes('HAVE_KEYSYMS','The X11 keysyms are there'); + $text.=ConfigIncDefYes('HAVE_X11','X11 library and headers'); + $text.=ConfigIncDefYes('HAVE_ALLEGRO','Allegro library'); + # Disable i8n only if the user requested, otherwise use gettext or the dummy + $conf{'HAVE_INTL_SUPPORT'}=@conf{'no-intl'} eq 'yes' ? 'no' : 'yes'; + $text.=ConfigIncDefYes('HAVE_INTL_SUPPORT','International support with gettext'); + $text.=ConfigIncDefYes('HAVE_GPM','GPM mouse support'); + $text.=ConfigIncDefYes('HAVE_OUTB_IN_SYS','out/in functions defined by glibc'); + $text.=ConfigIncDefYes('HAVE_SSC','Use stream replacements'); + $text.=ConfigIncDefYes('TV_BIG_ENDIAN','Byte order for this machine'); + $text.=ConfigIncDefYes('HAVE_LINUX_PTHREAD','Linux implementation of POSIX threads'); + $text.=ConfigIncDefYes('HAVE_UNSAFE_MEMCPY','Memcpy doesn\'t support overlaps'); + $text.=ConfigIncDefYes('HAVE_64BITS_POINTERS','64 bits pointers'); + $text.="\n\n"; + $text.="#define TVOS_$OS\n"; + $text.="#define TVOSf_$OSf\n"; + $text.="#define TVCPU_$CPU\n"; + $text.="#define TVComp_$Comp\n"; + $text.="#define TVCompf_$Compf\n"; + $text.="\n#define MSS\n#include \n" if @conf{'mss'} eq 'yes'; + $text.="\n"; + foreach $line (@MakeDefsRHIDE) + { + if ($line=~/([\w_]*)(\s*)=(\s*)(.*)/) + { + $text.="#define TVCONFIG_$1 \"$4\"\n"; + } + } + $text.="#define TVCONFIG_CFLAGS \"$CFLAGS\"\n"; + $text.="#define TVCONFIG_CXXFLAGS \"$CXXFLAGS\"\n"; + $text.="#define TVCONFIG_REF_DIR \"$here\"\n\n"; + + $old=cat('include/tv/configtv.h'); + if ($text eq $old) + { + print "no changes\n"; + } + else + { + print "created new header\n"; + replace('include/tv/configtv.h',$text); + } +} + +sub LookForMaintainerTools +{ + my $file; + + $file=LookForFileInPath('gpr2mak*'); + if (!length($file)) + { + die "\nRHIDE tools aren't installed. They are needed only for maintainer mode.\n". + "Install RHIDE or disable the maintaner mode.\n\n"; + } +} + diff --git a/tvision/confignt.pl b/tvision/confignt.pl new file mode 100644 index 0000000..e185f49 --- /dev/null +++ b/tvision/confignt.pl @@ -0,0 +1,67 @@ +#!/usr/bin/perl +# Copyright (C) 1996-2002 by Salvador E. Tropea (SET), +# see copyrigh file for details +# + +require "miscperl.pl"; +require "conflib.pl"; + +SeeCommandLine(); + +# 1) Get the list of files used by djgpp version +$col=14; +$a=ExtractItemsImk('makes/librhtv.imk',$col); +$a.=' '.ExtractItemsImk('compat/compat.imk',$col); +# 2) Remove djgpp specific things +$a=~s/vga.o//; +$a=~s/vgaregs.o//; +$a=~s/vgastate.o//; +$a=~s/vesa.o//; +# 3) Add BC++ specific +#$a.=' gkeyw32.cc'; +$b=$a; +$a=~s/(\w+)\.(\w+)/\+$1\.obj/g; +$a=~s/\t//g; +# 3b) MSVC specific +$b=~s/(\w+)\.(\w+)/\$\(OBJDIR\)\/$1\.o/g; +# 4) Generate makefile from the template +$ReplaceTags{'TV_OBJS_BCC'}=$a; +$ReplaceTags{'TV_OBJS_MSVC'}=$b; + +$ReplaceTags{'DYNRTL'} = $conf{'dynrtl'} ? "DYNRTL = 1" : ""; + +ReplaceText('winnt/bccmake.in','winnt/Makefile'); +ReplaceText('winnt/msvcmake.in','winnt/Makefile.nmk'); + +sub SeeCommandLine +{ + my $i; + + foreach $i (@ARGV) + { + if ($i eq '--help') + { + ShowHelp(); + die "\n"; + } + elsif ($i eq '--with-dynrtl') + { + $conf{'dynrtl'} = 1; + } + else + { + ShowHelp(); + die "Unknown option: $i\n"; + } + } +} + +sub ShowHelp +{ + print "Available options:\n\n"; + print "--help : displays this text.\n"; + print "--bindir=path : defines the directory where *.exe files will be installed.\n"; + print "--setdir=path : defines the directory where documentation andsupport files\n" . + " will be installed.\n"; + print "--with-dynrtl : compile with DLL runtime.\n"; +} diff --git a/tvision/configset b/tvision/configset new file mode 100755 index 0000000..05ed7c3 --- /dev/null +++ b/tvision/configset @@ -0,0 +1,30 @@ +#!/bin/sh +# Copyright (C) 1999-2003 by Salvador E. Tropea (SET), +# see copyrigh file for details +# +echo +echo This batch file configures the packages using the settings that the +echo *maintainer* uses for it\'s own needs. +echo These settings doesn\'t have to be the same you want. +echo The most common defaults are obtained by just running configure.bat. +echo If you want to reconfigure the package first delete configure.cache. +echo +echo Press the \'ENTER\' key to continue or hit \'CTRL+C\' to cancel. +read idontcare +rm -f configure.cache +rm -f Makefile +# gcc 2.95.4 compiles much faster (3.2x average) +#export CC="gcc-2.95" +#export CXX="g++-2.95" +# gcc 3.3.5 generates faster code (+20% aprox. for K7) +#export CC="gcc-3.3" +#export CXX="g++-3.3" +# Note: Using SSC gcc 3.3.5 compiles in less time (1.37x instead of 3.2x) +# gcc 3.4.4 test +#export CC="gcc-3.4" +#export CXX="g++-3.4" +perl config.pl --cflags=-O2\ -Wall\ -Werror\ -gstabs+3\ -pipe \ + --cxxflags=-O2\ -Wall\ -Werror\ -gstabs+3\ -pipe \ + --with-debug --enable-maintainer-mode --without-static \ + --with-ssc "$@" + diff --git a/tvision/configset.bat b/tvision/configset.bat new file mode 100644 index 0000000..b7c7734 --- /dev/null +++ b/tvision/configset.bat @@ -0,0 +1,14 @@ +:@Rem Copyright (C) 1999-2003 by Salvador E. Tropea (SET), +:@Rem see copyrigh file for details +@echo . +@echo This batch file configures the packages using the settings that the +@echo *maintainer* uses for your own needs. +@echo These settings doesn't have to be the same you want. +@echo The most common defaults are obtained by just running configure.bat. +@echo If you want to reconfigure the package first delete configure.cache +@echo . +@pause +@del configure.cache +@set CFLAGS=-O2 -Wall -Werror -gstabs+3 +@set CXXFLAGS=-O2 -Wall -Werror -gstabs+3 -fno-exceptions -fno-rtti +@configure.bat --enable-maintainer-mode --with-ssc --force-dummy %1 %2 %3 %4 %5 %6 %7 %8 %9 diff --git a/tvision/configure b/tvision/configure new file mode 100755 index 0000000..4d4f59f --- /dev/null +++ b/tvision/configure @@ -0,0 +1,2 @@ +#!/bin/sh +perl config.pl "$@" diff --git a/tvision/configure.bat b/tvision/configure.bat new file mode 100644 index 0000000..e8a1b0c --- /dev/null +++ b/tvision/configure.bat @@ -0,0 +1,3 @@ +@Echo off +@rm -f Makefile +@perl config.pl %1 %2 %3 %4 %5 %6 %7 %8 %9 diff --git a/tvision/conflib.pl b/tvision/conflib.pl new file mode 100644 index 0000000..5287293 --- /dev/null +++ b/tvision/conflib.pl @@ -0,0 +1,1524 @@ +#!/usr/bin/perl +# Copyright (C) 1999-2004 by Salvador E. Tropea (SET), +# see copyrigh file for details +# +# Common configuration routines. +# + +$ErrorLog='errormsg.txt'; +$MakeDefsRHIDE={}; +$ExtraModifyMakefiles={}; +# DOS, UNIX, Win32 +$OS=''; +# Linux, FreeBSD, NetBSD, Solaris, QNXRtP, QNX4 +$OSf=''; +# x86, Alpha, SPARC64, SPARC, PPC, HPPA, MIPS, Itanium, Unknown +$CPU=''; +# GCC, BCPP, MSVC +$Comp=''; +# djgpp, MinGW, Cygwin +$Compf=''; +# gcc's -pipe option +$UsePipe=0; + +sub GetCache +{ + my $val; + + if (open(FIL,') + { + if ($val=~/(.*) => (.*)\n/) + { + @conf{$1}=$2; + #print "$1 => $2\n"; + } + else + { + #print "No toma: ($val)"; + } + } + close(FIL); + } +} + + +sub CreateCache +{ + my ($i,$ff); + + $ff=1; + if (open(FIL,'>configure.cache')) + { + foreach $i (%conf) + { + if ($ff) + { + print FIL ("$i => @conf{$i}\n"); + $ff=0; + } + else + { + $ff=1; + } + } + close(FIL); + } +} + + +sub CompareVersion +{ + my ($actual,$needed)=@_; + my ($vact,$vneed); + + $actual=~/(\d+)\.(\d+)(\.(\d+))?/; + $vact=$1*1000000+$2*1000+$4; + $needed=~/(\d+)\.(\d+)(\.(\d+))?/; + $vneed=$1*1000000+$2*1000+$4; + #print "$vact v.s. $vneed\n"; + $vact>=$vneed; +} + + +sub LookForFile +{ + my ($file,@path)=@_; + my ($i,@a,$f); + + foreach $i (@path) + { + #print "Testing for ".$i.'/'.$file."\n"; + @a=glob($i.'/'.$file); + foreach $f (@a) + { + if (-e $f) + { + return $i; + } + } + } + ''; +} + +sub LookForFileInPath +{ + my ($file)=@_; + my @list; + + @list=(($OS eq 'UNIX') || ($Compf eq 'Cygwin')) ? split(/:/,@ENV{'PATH'}) : split(/;/,@ENV{'PATH'}); + return LookForFile($file,@list); +} + +###[txh]#################################################################### +# +# Prototype: RunRedirect($command,$ErrorLog) +# Description: +# Executes the desired command sending the stderr to $ErrorLog file +# (appending) and returning the stdout. +# +# Return: The value returned from the program (from stdout). +# +####################################################################[txi]### + +sub RunRedirect +{ + my ($command,$ErrorLog)=@_; + my $ret; + + if ($OS eq 'DOS') + { + $ret=`redir -ea $ErrorLog $command`; + } + elsif ($OS eq 'Win32') + { + $ret=`sh -c "$command 2>> $ErrorLog"`; + } + else + { + $ret=`$command 2>> $ErrorLog`; + } + $ret; +} + +sub AddIncludes +{ + my (@dirs)=split(' ',$conf{'EXTRA_INCLUDE_DIRS'}); + my ($res)=''; + for (@dirs) + { + $res.=" -I$_"; + } + return $res; +} + +###[txh]#################################################################### +# +# Prototype: RunGCCTest($gcc,$extension,$prog,$flags) +# Description: +# Compiles a test program with gcc and runs it callecting the output.@* +# You must pass the name of the compiler as argument, also the extension of +# the file (.c, .cc, etc.), the code to compile and any etra switch options +# needed to compile.@* +# Additionally the following global variables are used: $CFLAGS: standard +# flags for the C compiler (used when extension=='c'), $CXXFLAGS: standard +# flags for the C++ compiler (used when extension=='cc'), $ErrorLog: file +# to log the actions and errors and the $OS guess.@* +# +# Return: The value returned from the program (from stdout). +# +####################################################################[txi]### + +sub RunGCCTest +{ + my ($cc,$ext,$test,$switchs)=@_; + my ($command,$label); + my ($file,$flags)=('test.'.$ext,''); + + unlink 'test.exe'; + replace($file,$test."\n"); + $flags=$CFLAGS if ($ext eq 'c'); + $flags=$CXXFLAGS if ($ext eq 'cc'); + $flags.=AddIncludes(); + $command="$cc -o test.exe $flags $file $switchs"; + #print "Running: $command\n"; + $label=$command.":\n"; + `echo $label >> $ErrorLog`; + + RunRedirect($command,$ErrorLog); + $test=RunRedirect('./test.exe',$ErrorLog); + #print "\n$command: $test"; + # Does anybody know why I can't delete the exe here? + # In Linux it makes the variable $test to change! + #unlink('test.o',$file,'test.exe'); + unlink('test.o',$file); + $test; +} + +###[txh]#################################################################### +# +# Prototype: LookForPrefix() +# Description: +# Tries to find the right installation prefix. The following mechanisms +# are used:@* +# 1) Look for cached prefix key.@* +# 2) Look for prefix environment variable.@* +# 3) Look for PREFIX environment variable.@* +# UNIX:@* +# 4) Find where make is installed and guess from it.@* +# 5) If not found default to /usr@* +# DOS:@* +# 6) Use the DJDIR environment variable.@* +# The result is stored in the prefix configuration key. +# WIN32:@* +# 7) Locate make.exe in PATH and use parent directory for prefix. If the +# prefix string contains backslashes, convert them to slashes. +# make.exe must reside in $prefix/bin directory +# +####################################################################[txi]### + +sub LookForPrefix +{ + my ($test,$prefix,@lista,$i,$found); + + print 'Looking for prefix: '; + $prefix=@conf{'prefix'}; + if ($prefix) + { + print "$prefix (cached/specified)\n"; + LookIfFHS(); + return; + } + $prefix=@ENV{'prefix'}; + if (!$prefix) + { + $prefix=@ENV{'PREFIX'}; + } + if ($prefix) + { + print "$prefix (environment)\n"; + @conf{'prefix'}=$prefix; + LookIfFHS(); + return; + } + if (($OS eq 'UNIX') || ($Compf eq 'Cygwin')) + { + if (`which make`=~/(.*)\/bin\/make/) + { + $prefix=$1; + } + else + { + $prefix='/usr'; + } + } + elsif ($OS eq 'DOS') + { + $prefix=@ENV{'DJDIR'}; + } + else + { + if ($Compf eq 'MinGW') + { + @lista=(split(/;/,@ENV{'PATH'}),split(/:/,@ENV{'PATH'})); + $found=0; + foreach $i (@lista) + { + #print "Buscando ".$i."\\make.exe\n"; + if (!$found && (-e $i."\\make.exe") && + ($i=~/(.*)[\\\/][bB][iI][nN]/)) + { + $prefix=$1; + $prefix=~s/\\/\//g; + $found=1; + } + } + } + if (!$found) + { + if (!$test) + { + die "Some critical tools aren't installed please read the reame files"; + } + else + { + print "Unable to determine installation prefix, please use --prefix option.\n"; + print "You'll most probably need to quote the --prefix option (\"--prefix=path\").\n" if @ENV{'OS'} eq 'Windows_NT'; + die; + } + } + } + @conf{'prefix'}=$prefix; + print "$prefix\n"; + LookIfFHS(); +} + +sub LookIfFHS +{ + if ($OS eq 'UNIX') + { + print 'Checking if this system follows the FHS: '; + if ($conf{'fhs'}) + { + print "$conf{'fhs'} (cached/specified)\n"; + return; + } + # FreeBSD uses share/doc but not shared/info and shared/man + if ((-d $prefix.'/share/doc') && (-d $prefix.'/share/info') && (-d $prefix.'/share/man')) + { + $conf{'fhs'}='yes'; + } + else + { + $conf{'fhs'}='no'; + } + print "$conf{'fhs'}\n"; + } +} + +###[txh]#################################################################### +# +# Prototype: CheckGCC() +# Description: +# Tries to find a working C compiler. The following tests are done:@* +# 1) Look for cached GCC key.@* +# 2) Look for CC environment variable.@* +# 3) Default to gcc.@* +# Then a small test program is compiled. If it fails the program dies.@* +# The result is stored in the GCC configuration key. +# +# Return: The name of the working compiler. +# +####################################################################[txi]### + +sub CheckGCC +{ + my ($cc,$test); + + print 'Looking for a working gcc: '; + $cc=@conf{'GCC'}; + if ($cc) + { + print "$cc (cached) OK\n"; + return $cc; + } + $cc=$ENV{'CC'}; + if (!length($cc)) + { + $cc='gcc'; + } + print "$cc "; + $test='#include +int main(void) +{ + printf("OK\n"); + return 0; +} +'; + $test=RunGCCTest($cc,'c',$test,''); + $test=~s/\W//g; + if ($test ne "OK") + { + CreateCache(); + die 'Not working gcc found'; + } + print "OK\n"; + $conf{'GCC'}=$cc; + $cc; +} + +###[txh]#################################################################### +# +# Prototype: CheckGCCcanXX($gcc) +# Description: +# Checks if the C compiler can be used to compile C++ code. +# +# Return: 'yes' or 'no' according to a compilation test. +# +####################################################################[txi]### + +sub CheckGCCcanXX +{ + my $cc=$_[0]; + my ($ret,$test); + + print "$cc can compile C++ code: "; + $test=' +#if __GNUC__>=3 + #include + #define STD(a) std::a +#else + #include + #define STD(a) a +#endif +int main(void) +{ + STD(cout) << "OK" << STD(endl); + return 0; +}'; + $test=RunGCCTest($cc,'cc',$test,$stdcxx); + $test=~s/\W//g; + if ($test eq "OK") + { + print "yes\n"; + $ret=1; + } + else + { + print "no\n"; + $ret=0; + } + $ret; +} + + +###[txh]#################################################################### +# +# Prototype: CheckGXX() +# Description: +# Finds the C++ compiler. Mechanism:@* +# 1) Cached GXX key.@* +# 2) Compiler declared in global $GCC variable.@* +# 3) Return value from CheckGXXReal().@* +# The result is stored in the GXX configuration key and the $GXX global +# variable. +# +# Return: The $GXX value. +# +####################################################################[txi]### + +sub CheckGXX +{ + if (@conf{'GXX'}) + { + print "C++ compiler: @conf{'GXX'} (cached) OK\n"; + return @conf{'GXX'}; + } + # Test for a working g++ + $GXX=CheckGXXReal(); + + $conf{'GXX'}=$GXX; +} + +###[txh]#################################################################### +# +# Prototype: CheckGXXReal() +# Description: +# Tries to find if $defaultCXX can compile C++. This global variable is +# determined during the OS detection. If it fails the program dies. +# +# Return: The name of the compiler. +# +####################################################################[txi]### + +sub CheckGXXReal +{ + my ($test,$res,@list,$i,$cxx); + + print 'Looking for the C++ compiler: '; + $test=' +#if __GNUC__>=3 + #include + #define STD(a) std::a +#else + #include + #define STD(a) a +#endif +int main(void) +{ + STD(cout) << "OK" << STD(endl); + return 0; +}'; + @list=split(/:/,$defaultCXX); + $cxx=$ENV{'CXX'}; + if (length($cxx)) + { + unshift @list,$cxx; + } + foreach $i (@list) + { + $res=RunGCCTest($i,'cc',$test,$stdcxx); + $res=~s/\W//g; + if ($res eq "OK") + { + print "$i\n"; + return $i; + } + } + return $GCC if (CheckGCCcanXX($GCC)); + CreateCache(); + die('can not find it'); +} + +###[txh]#################################################################### +# +# Prototype: LookForDJGPP($versionNeeded) +# Description: +# Finds if the installed djgpp version is the needed. Note that the +# version should be provided in the following way: djgpp v2.01 => 2.0.1. +# I did it to accomodate to the version comparisson test. Mechanism:@* +# 1) Cached djgpp key.@* +# 2) Compilation of a small program printing DJGPP.0.DJGPP_MINOR.@* +# If the version is incorrect the program dies.@* +# The result is stored in the 'djgpp' configuration key. +# +####################################################################[txi]### + +sub LookForDJGPP +{ + my $vNeed=$_[0]; + my $test; + + print 'Checking DJGPP version: '; + $test=@conf{'djgpp'}; + if ($test) + { + print "$test (cached) OK\n"; + return; + } + $test=' +#include +int main(void) +{ + printf("%d.0.%d",DJGPP,DJGPP_MINOR); + return 0; +} +'; + $test=RunGCCTest($GCC,'c',$test,''); + if (!CompareVersion($test,$vNeed)) + { + print "\nWrong DJGPP version, please use $vNeed or newer\n"; + print "Look in $ErrorLog for potential compile errors of the test\n"; + CreateCache(); + die "Wrong version\n"; + } + print "$test OK\n"; + $conf{'djgpp'}=$test; +} + +###[txh]#################################################################### +# +# Prototype: FindCFLAGS() +# Description: +# Determines the flags to be used for compilation. Mechanism:@* +# 1) Cached CFLAGS key.@* +# 2) Environment variable CFLAGS.@* +# 3) -O2 -gstabs+3 (-pipe if UNIX).@* +# The result is stored in the 'CFLAGS' configuration key. +# +# Return: The value determined. +# +####################################################################[txi]### + +sub FindCFLAGS +{ + my ($ret,$ver); + + print 'C flags: '; + $ret=@conf{'CFLAGS'}; + if ($ret) + { + print "$ret (cached)\n"; + return $ret; + } + $ret=@ENV{'CFLAGS'}; + if (!$ret) + { + $ret='-O2'; # -gstabs+3'; + # In UNIX pipes are in memory and allows multithreading so they are + # usually faster. In Linux that's faster. + $ret.=' -pipe' if $UsePipe; + # Looks like that's common and some sysadmins doesn't configure gcc to + # look there: + $conf{'EXTRA_INCLUDE_DIRS'}.=' /usr/local/include' if ($OSf eq 'FreeBSD'); + # Darwin is using a temporal size + $ret.=' -Wno-long-double' if ($OSf eq 'Darwin'); + # QNX4 X11 is in /usr/X11R6 + # This should be automatic now. (EXTRA_INCLUDE_DIRS). + #$ret.=' -I/usr/X11R6/include' if ($OSf eq 'QNX4'); + $ver=RunRedirect("$GCC -dumpversion",$ErrorLog); + $ret.=' -Wno-packed' if $ver>=4; + } + print "$ret\n"; + $conf{'CFLAGS'}=$ret; + $ret; +} + +###[txh]#################################################################### +# +# Prototype: FindLDExtraDirs() +# Description: +# Simple hook to get the extra dirs. +# +# Return: +# Space separated list of directories. +# +####################################################################[txi]### + +sub FindLDExtraDirs() +{ + my $ret; + + $ret=@conf{'LDExtraDirs'}; + if ($ret) + { + return $ret; + } + $ret=''; + $ret.='/usr/local/lib' if ($OSf eq 'FreeBSD'); + $ret.='/usr/pkg/lib' if ($OSf eq 'NetBSD'); + $conf{'LDExtraDirs'}=$ret; + $ret; +} + + +###[txh]#################################################################### +# +# Prototype: FindCXXFLAGS() +# Description: +# Determines the flags to be used for C++ compilation. Mechanism:@* +# 1) Cached CXXFLAGS key.@* +# 2) Environment variable CXXFLAGS.@* +# 3) Cached CFLAGS key.@* +# 4) Environment variable CFLAGS.@* +# 5) -O2 -gstabs+3 (-pipe if UNIX).@* +# The result is stored in the 'CXXFLAGS' configuration key. +# +# Return: The value determined. +# +####################################################################[txi]### + +sub FindCXXFLAGS +{ + my $ret; + + print 'C++ flags: '; + $ret=@conf{'CXXFLAGS'}; + if ($ret) + { + print "$ret (cached)\n"; + return $ret; + } + $ret=@ENV{'CXXFLAGS'}; + $ret=@conf{'CFLAGS'} unless $ret; + $ret=@ENV{'CFLAGS'} unless $ret; + if (!$ret) + { + $ret='-O2'; # -gstabs+3'; + $ret.=' -pipe' if $UsePipe; + $ret.=' -L/usr/local/include' if ($OSf eq 'FreeBSD'); + $conf{'EXTRA_INCLUDE_DIRS'}.=' /usr/local/include' if ($OSf eq 'FreeBSD'); + $ret.=' -Wno-long-double' if ($OSf eq 'Darwin'); + # QNX4 X11 is in /usr/X11R6 + # This should be automatic now. (EXTRA_INCLUDE_DIRS). + #$ret.=' -I/usr/X11R6/include' if ($OSf eq 'QNX4'); + } + print "$ret\n"; + $conf{'CXXFLAGS'}=$ret; + $ret; +} + + +###[txh]#################################################################### +# +# Prototype: FindXCFLAGS() +# Description: +# Determines the flags to be used for special compilation. Mechanism:@* +# 1) Cached XCFLAGS key.@* +# 2) -O3 -fomit-frame-pointer -ffast-math (-pipe if not DOS).@* +# The result is stored in the 'XCFLAGS' configuration key. +# +# Return: The value determined. +# +####################################################################[txi]### + +sub FindXCFLAGS +{ + my $ret; + + print 'Special C flags: '; + $ret=@conf{'XCFLAGS'}; + if ($ret) + { + print "$ret (cached/cmdline)\n"; + return $ret; + } + if (!$ret) + { + $ret='-O3 -fomit-frame-pointer -ffast-math'; + $ret.=' -pipe' if $UsePipe; + $ret.=' -Wno-long-double' if ($OSf eq 'Darwin'); + } + print "$ret\n"; + $conf{'XCFLAGS'}=$ret; + $ret; +} + + +###[txh]#################################################################### +# +# Prototype: FindXCXXFLAGS() +# Description: +# Determines the flags to be used for C++ compilation. Mechanism:@* +# 1) Cached XCXXFLAGS key.@* +# 2) -O3 -fomit-frame-pointer -ffast-math (-pipe if not DOS).@* +# The result is stored in the 'XCXXFLAGS' configuration key. +# +# Return: The value determined. +# +####################################################################[txi]### + +sub FindXCXXFLAGS +{ + my $ret; + + print 'Special C++ flags: '; + $ret=@conf{'XCXXFLAGS'}; + if ($ret) + { + print "$ret (cached/cmdline)\n"; + return $ret; + } + if (!$ret) + { + $ret='-O3 -fomit-frame-pointer -ffast-math'; + $ret.=' -pipe' if $UsePipe; + $ret.=' -Wno-long-double' if ($OSf eq 'Darwin'); + } + print "$ret\n"; + $conf{'XCXXFLAGS'}=$ret; + $ret; +} + + +###[txh]#################################################################### +# +# Prototype: DetectOS() +# Description: +# Determines the OS using the uname command. If it returns MS-DOS then dos +# is assumed, if Linux or linux is returned the linux is assumed. If none +# of these is returned the program dies. The following global variables are +# filled according to the OS:@* +# $OS: DOS, UNIX, Win32.@* +# $OSf: OS flavor i.e. Linux.@* +# $Comp: Compiler i.e. GCC.@* +# $Compf: Compiler flavor i.e. djgpp.@* +# $stdcxx: C++ library (stdcxx or stdc++).@* +# $defaultCXX: C++ compiler (gxx or g++).@* +# $supportDir: Directory to look for OS specific support (djgpp or linux).@* +# +# Return: The determined OS. +# +####################################################################[txi]### + +sub DetectOS +{ + my ($os,$release,$OS); + $os=`uname`; + if (!$os) + { + print "\n"; + print "* -------------------------------------- *\n"; + print " Please install the `uname' command.\n"; + print " DJGPP users: That's part of shell utils.\n"; + print "* -------------------------------------- *\n\n"; + die; + } + print 'Determining OS: '; + + $OSpr=0; + # Currently the configuration is oriented for GNU systems + # other systems should have a special configuration header + # created by hand. + $Comp='GCC'; + $ExeExt=''; + if ($os=~/MS\-DOS/) + { + $OS='DOS'; + $OSf=''; + $Compf='djgpp'; + $stdcxx='-lstdcxx'; + $defaultCXX='gpp:gxx'; + $supportDir='djgpp'; + $ExeExt='.exe'; + } + elsif ($os=~/[Ll]inux/) + { + $OS='UNIX'; + $OSf='Linux'; + $Compf=''; + $stdcxx='-lstdc++'; + $defaultCXX='g++'; + $supportDir='linux'; + } + elsif ($os=~/FreeBSD/) + { + $OS='UNIX'; + $OSf='FreeBSD'; + $Compf=''; + $stdcxx='-lstdc++'; + $defaultCXX='g++'; + $supportDir='linux'; + } + elsif ($os=~/CYGWIN/) + { + $OS='Win32'; + $OSf=''; + $Compf='Cygwin/MinGW'; + $stdcxx='-lstdc++'; + $defaultCXX='g++'; + $supportDir='win32'; + $ExeExt='.exe'; + } + elsif ($os=~/MINGW/) + { + $OS='Win32'; + $OSf=''; + $Compf='MinGW'; + $stdcxx='-lstdc++'; + $defaultCXX='g++'; + $supportDir='win32'; + $ExeExt='.exe'; + } + elsif ($os=~/SunOS/) + { + $OS='UNIX'; + $OSf='Solaris'; + $Compf=''; + $stdcxx='-lstdc++'; + $defaultCXX='g++'; + $supportDir='linux'; + } + elsif ($os=~/QNX/) + { + $release=`uname -r`; + if ($release =~ /^6/) + { + $OS='UNIX'; + $OSf='QNXRtP'; + $Compf=''; + $stdcxx='-lstdc++'; + $defaultCXX='qcc -Y_gpp'; + $supportDir='linux'; + } + else + { + $OS='UNIX'; + $OSf='QNX4'; + $Compf=''; + $stdcxx='-lstdc++'; + $defaultCXX='g++'; + $supportDir='linux'; + } + } + elsif ($os=~/HP-UX/) + { + $OS='UNIX'; + $OSf='HP-UX'; + $Compf=''; + $stdcxx='-lstdc++'; + $defaultCXX='g++'; + $supportDir='linux'; + } + elsif ($os=~/Darwin/) + { + $OS='UNIX'; + $OSf='Darwin'; + $Compf=''; + $stdcxx='-lstdc++'; + $defaultCXX='c++'; + $supportDir='linux'; + $conf{'GCC'}='cc'; + } + elsif ($os=~/NetBSD/) + { + $OS='UNIX'; + $OSf='NetBSD'; + $Compf=''; + $stdcxx='-lstdc++'; + $defaultCXX='g++'; + $supportDir='linux'; + } + elsif ($os=~/OpenBSD/) + { + $OS='UNIX'; + $OSf='OpenBSD'; + $Compf=''; + $stdcxx='-lstdc++'; + $defaultCXX='g++'; + $supportDir='linux'; + } + elsif ($os=~/OSF1/) + { + $OS='UNIX'; + $OSf='Tru64'; + $Compf=''; + $stdcxx='-lstdc++'; + $defaultCXX='g++'; + $supportDir='linux'; + } + else + { + die('Unknown OS, you must do things by yourself'); + } + # The gcc I found in an HP DS20E machine comes in a package called TWWfsw and + # doesn't support -pipe. (Dual EV67 667 MHz machine running OSF1 v5.1). + $UsePipe=($OS eq 'UNIX') && ($OSf ne 'Tru64'); + print "$OS"; + print " [$OSf]" if $OSf; + print " [$Compf]" if $Compf; + print "\n"; + $OS; +} + +sub DetectOS2 +{ + my $test; + # Most MinGW users have Cygwin tools + if ($Compf eq 'Cygwin/MinGW') + { + print 'Detecting compiler env. better: '; + if ($conf{'Cygwin/MinGW'}) + { + $Compf=$conf{'Cygwin/MinGW'}; + print "$Compf (cached)\n"; + } + else + { + $test=' +#include +int main(void) +{ + #ifdef __CYGWIN__ + printf("Cygwin\n"); + #else + printf("MinGW\n"); + #endif + return 0; +} +'; + $Compf=RunGCCTest($GCC,'c',$test,''); + chop($Compf); + $conf{'Cygwin/MinGW'}=$Compf; + print "$Compf\n"; + } + } +} + +###[txh]#################################################################### +# +# Prototype: ModifyMakefiles(@list) +# Description: +# Patches the listed RHIDE makefiles to use the detected C compiler, C++ +# compiler and compilation flags.@* +# +####################################################################[txi]### + +sub ModifyMakefiles +{ + my ($a,$text,$rep,$repv,$line,$name,$value); + + print 'Configuring makefiles: '; + foreach $a (@_) + { + print "$a "; + $text=cat($a); + if ($text) + { + $text=~s/RHIDE_GCC=(.*)\n/RHIDE_GCC=$GCC\n/g; + $text=~s/RHIDE_GXX=(.*)\n/RHIDE_GXX=$GXX\n/g; + $text=~s/RHIDE_LD=(.*)\n/RHIDE_LD=$GXX\n/g; + $text=~s/RHIDE_OS_CFLAGS=(.*)\n/RHIDE_OS_CFLAGS=$CFLAGS\n/g; + $text=~s/RHIDE_OS_CXXFLAGS=(.*)\n/RHIDE_OS_CXXFLAGS=$CXXFLAGS\n/g; + $text=~s/RHIDE_AR=(.*)\n/RHIDE_AR=$GAR\n/g if ($GAR); + $rep ='rc'; + $rep.='s' unless $conf{'UseRanLib'}; + $text=~s/RHIDE_ARFLAGS=(.*)\n/RHIDE_ARFLAGS=$rep\n/g; + foreach $rep (%ExtraModifyMakefiles) + { + $repv="$rep=@ExtraModifyMakefiles{$rep}\n"; + $text=~s/$rep=(.*)\n/$repv/; + } + foreach $line (@MakeDefsRHIDE) + { + if ($line=~/([\w_]*)(\s*)=(\s*)(.*)/) + { + $name=$1; + $value=$4; + #print "$name=$value\n"; + $rep="^$name"."=((.+\\\\\\n)+(.+))"; + if ($text=~/$rep/m) + { # Ok multiline + $text=~s/$rep/$name=$value/mg; + } + else + { # Single line + $rep="^$name"."=(.*)"; + if ($text=~/$rep/m) + { + $text=~s/$rep/$name=$value/mg; + } + } + } + } + replace($a,$text); + } + } + print "\n"; +} + +###[txh]#################################################################### +# +# Prototype: ModifySimpleMakefiles(@list) +# Description: +# Patches the listed makefiles to use the detected C compiler, C++ +# compiler and compilation flags.@* +# +####################################################################[txi]### + +sub ModifySimpleMakefiles +{ + my ($a,$text,$rep); + + print 'Configuring simple makefiles: '; + foreach $a (@_) + { + print "$a "; + $text=cat($a); + if ($text) + { + $text=~s/GCC=(.*)\n/GCC=$GCC\n/; + $text=~s/GXX=(.*)\n/GXX=$GXX\n/; + $text=~s/LD=(.*)\n/LD=$GXX\n/; + $text=~s/CFLAGS=(.*)\n/CFLAGS=$CFLAGS\n/; + $text=~s/CXXFLAGS=(.*)\n/CXXFLAGS=$CXXFLAGS\n/; + replace($a,$text); + } + } + print "\n"; +} + +###[txh]#################################################################### +# +# Prototype: CreateRHIDEenvs(@list) +# Description: +# Generates all the needed rhide.env files to configure RHIDE with the +# detected C compiler, C++ compiler and compilation flags.@* +# That's needed to use RHIDE after configuring. +# Projects that needs faster C/C++ options are indicated with a +. +# +####################################################################[txi]### + +sub CreateRHIDEenvs +{ + my ($a,$text,$rep,$useXtreme,$b,$old); + + print 'Configuring RHIDE: '; + foreach $a (@_) + { + if (substr($a,0,1) eq "+") + { + $b=substr($a,1); + $useXtreme=1; + } + else + { + $b=$a; + $useXtreme=0; + } + print "$b "; + $text ="# +# Automatically generated by configure script +# If you didn't configure this package please do it or edit this file +# + +"; + $text.="RHIDE_GCC=$GCC\n"; + $text.="RHIDE_GXX=$GXX\n"; + $text.="RHIDE_LD=$GXX\n"; + $text.="RHIDE_AR=$GAR\n" if ($GAR); + $rep ='rc'; + $rep.='s' unless $conf{'UseRanLib'}; + $text.="RHIDE_ARFLAGS=$rep\n"; + + if ($useXtreme) + { + $text.="RHIDE_OS_CFLAGS=@conf{'XCFLAGS'}\n"; + $text.="RHIDE_OS_CXXFLAGS=@conf{'XCXXFLAGS'}\n"; + } + else + { + $text.="RHIDE_OS_CFLAGS=$CFLAGS\n"; + $text.="RHIDE_OS_CXXFLAGS=$CXXFLAGS\n"; + } + foreach $rep (@MakeDefsRHIDE) + { + $text.="$rep\n"; + } + + $old=cat($b); + if ($text ne $old) + { + if ($text) + { + replace($b,$text); + } + else + { + unlink $b; + } + } + } + print "\n"; +} + + +###[txh]#################################################################### +# +# Prototype: ConfigIncDef($defVar,$defComment) +# Description: +# That's used to generate the config.h file and generates a line with +# /* $defComment */\n#define $defVar or not according to the existence of +# the $defVar configure key. +# +# Return: The string generated. +# +####################################################################[txi]### + +sub ConfigIncDef +{ + my $text; + + $text ="\n\n/* $_[1] */\n"; + $text.='/*' unless (@conf{$_[0]}); + $text.="#define $_[0] 1"; + $text.='*/' unless (@conf{$_[0]}); + $text; +} + +###[txh]#################################################################### +# +# Prototype: ConfigIncDefYes($defVar,$defComment) +# Description: +# That's similar to ConfigIncDef, but here the key must be 'yes'. +# +# Return: The string generated. +# +####################################################################[txi]### + +sub ConfigIncDefYes +{ + my $text; + + $text ="\n\n/* $_[1] */\n"; + $text.='/*' unless (@conf{$_[0]} eq 'yes'); + $text.="#define $_[0] 1"; + $text.='*/' unless (@conf{$_[0]} eq 'yes'); + $text; +} + +sub ParentDir +{ + my ($cur,$parent); + $cur=`pwd`; + chop $cur; + chdir('..'); + $parent=`pwd`; + chop $parent; + chdir($cur); + $parent; +} + +sub ReplaceText +{ + my ($Text,$Dest,$i,$se,$re,$ff); + + $Dest=$_[1]; + print "Processing $_[0] => $_[1]\n"; + $Text=cat($_[0]); + $ff=0; + foreach $i (%ReplaceTags) + { + $ff=!$ff; + if ($ff) + { + $se='@'.$i.'@'; + $re=$ReplaceTags{$i}; + $Text =~ s/$se/$re/g; + } + } + replace($Dest,$Text); +} + +###[txh]#################################################################### +# +# Prototype: ExtractItemsImk($makefile,\$column) +# Description: +# Extracts the list of project items from a .imk. +# +# Return: The list of items. +# +####################################################################[txi]### + +sub ExtractItemsImk +{ + my ($makefile,$col)=($_[0],\$_[1]); + my ($mak,@items,$file,$result,$path); + + $result=''; + $makefile=~/((.+)\/+)/; + $path=$1; + print "Extracting from $makefile: "; + $mak=cat($makefile); + if ($mak=~ /(.*)::(((.+)\\\n)+(.+)\n)/ || + $mak=~ /(.*):: ((.+)\n)/) + { + print "processing\n"; + @items=split(/[\\\s]+/,$2); + foreach $file (@items) + { + if ($file=~/\$\(ExOBJ\)/) + { + $file=~/((.+)\/+)(.*)/; + $file=$3; + $file=~s/\$\(ExOBJ\)/\.o/; + #print "$file\n"; + if ($$col!=0) + { + if ($$col+length($file)>76) + { + $result.="\\\n\t"; + $$col=8; + } + else + { + $result.=' '; + $$col++; + } + } + $$col+=length($file); + $result.="$file"; + } + } + } + else + { + print "nothing found!\n"; + } + $result; +} + + +###[txh]#################################################################### +# +# Prototype: ExtractItemsMak($makefile,\$column) +# Description: +# Extracts the list of project items from a .mak. Is recursive. +# +# Return: The list of items. +# +####################################################################[txi]### + +sub ExtractItemsMak +{ + my ($makefile,$col)=($_[0],\$_[1]); + my ($mak,@items,$file,$result,$path); + + $result=''; + $makefile=~/((.+)\/+)/; + $path=$1; + print "Extracting from $makefile\n"; + $mak=cat($makefile); + if ($mak=~ /PROJECT_ITEMS=(((.+)\\\r?\n)+(.+)\r?\n)/ || + $mak=~ /PROJECT_ITEMS=((.+)\r?\n)/) + { + #print "$1\n"; + @items=split(/[\\\s]+/,$1); + foreach $file (@items) + { + if ($file=~/\.gpr/) + { + $file=~s/\.gpr/\.mak/; + $result.=ExtractItemsMak($path.$file,$$col); + #print "**** Back ($path)\n"; + } + else + { + #print "$file\n"; + if ($$col!=0) + { + if ($$col+length($file)>76) + { + $result.="\\\n\t"; + $$col=8; + } + else + { + $result.=' '; + $$col++; + } + } + $$col+=length($file); + $result.="$file"; + } + } + } + $result; +} + +sub DetectCPU +{ + my $test; + + print 'Checking Architecture: '; + + if ($conf{'TV_CPU'}) + { + print "$conf{'TV_CPU'} (cached)\n"; + $CPU=$conf{'TV_CPU'}; + return; + } + $test=' +#include +int main(void) +{ + #ifdef __i386__ + printf("x86\n"); + #elif defined(__alpha__) || defined(__alpha) + printf("Alpha\n"); + #elif defined(__sparc_v9__) || defined(__sparcv9) + printf("SPARC64\n"); + #elif defined(__sparc__) || defined(sparc) + printf("SPARC\n"); + #elif defined(__PPC__) || defined(PPC) || defined(__ppc__) + printf("PPC\n"); + #elif defined(__hppa__) + printf("HPPA\n"); + #elif defined(__mips__) + printf("MIPS\n"); + #elif defined(__ia64__) + printf("Itanium\n"); + #elif defined(__amd64__) + printf("AMD64\n"); + #else + printf("Unknown\n"); + #endif + return 0; +} +'; + $test=RunGCCTest($GCC,'c',$test,''); + $test=~s/\W//g; + $CPU=$conf{'TV_CPU'}=$test; + print "$test\n"; +} + +sub LookForGNUMake +{ + my $test; + print 'Looking for GNU make: '; + + if ($conf{'GNU_Make'}) + { + print "$conf{'GNU_Make'} (cached)\n"; + return; + } + $test=RunRedirect('make --version',$ErrorLog); + if ($test=~/GNU Make/) + { + $conf{'GNU_Make'}='make'; + print "make\n"; + return; + } + $test=RunRedirect('gmake --version',$ErrorLog); + if ($test=~/GNU Make/) + { + $conf{'GNU_Make'}='gmake'; + print "gmake\n"; + return; + } + print "Unable to find GNU Make on this system.\n"; + print "Please install it and be sure it's in your path.\n"; + print "Also use `make' or `gmake' name for the binary.\n"; + die; +} + +sub LookForGNUar +{ + my $test; + print 'Looking for GNU ar: '; + + if ($conf{'GNU_AR'}) + { + print "$conf{'GNU_AR'} (cached)\n"; + return $conf{'GNU_AR'}; + } + $conf{'UseRanLib'}=0; + $test=RunRedirect('ar --version',$ErrorLog); + if ($test=~/GNU ar/) + { + $conf{'GNU_AR'}='ar'; + print "ar\n"; + return 'ar'; + } + $test=RunRedirect('gar --version',$ErrorLog); + if ($test=~/GNU ar/) + { + $conf{'GNU_AR'}='gar'; + print "gar\n"; + return 'gar'; + } + if (!LookForFileInPath('ar')) + { + print "Unable to find GNU ar on this system.\n"; + print "Please install it and be sure it's in your path.\n"; + print "Also use `ar' or `gar' name for the binary.\n"; + die; + } + # I think all ar tools are usable but ... + if (($OSf eq 'Darwin') || ($OSf eq 'HP-UX') || ($OSf eq 'Tru64') || + ($OSf eq 'Solaris')) + { + $conf{'GNU_AR'}='ar'; + $conf{'UseRanLib'}=1; + print "ar (not GNU but usable!)\n"; + return 'ar'; + } + if ($OSf eq 'QNX4') + { + $conf{'GNU_AR'}='ar'; + $conf{'UseRanLib'}=1; + print "ar (WATCOM)\n"; + return 'ar'; + } + print "Unable to find GNU ar on this system.\n"; + print "Please install it and be sure it's in your path.\n"; + print "Also use `ar' or `gar' name for the binary.\n"; + die; +} + +sub LookForGNUinstall +{ + my ($test,$test2,$res,$testErr); + + print 'Looking for install tool: '; + + if ($conf{'GNU_INSTALL'}) + { + print "$conf{'GNU_INSTALL'} (cached)\n"; + return $conf{'GNU_INSTALL'}; + } + $conf{'SOLARIS_INSTALL'}=0; + $test=RunRedirect('install --version',$ErrorLog); + if ($test=~/Free Software Foundation/) + { + $conf{'GNU_INSTALL'}='install'; + print "install\n"; + return 'install'; + } + $test2=RunRedirect('ginstall --version',$ErrorLog); + if ($test2=~/Free Software Foundation/) + { + $conf{'GNU_INSTALL'}='ginstall'; + print "ginstall\n"; + return 'ginstall'; + } + if (!LookForFileInPath('install'.$ExeExt)) + { + print "Unable to find 'install' on this system.\n"; + print "Please install it and be sure it's in your path.\n"; + print "Also use `install' or `ginstall' name for the binary.\n"; + die; + } + $res='install'; + # Solaris install is bizarre. + if ($OSf eq 'Solaris') + { + $conf{'SOLARIS_INSTALL'}=1; + } + # NetBSD install moves by default!! + elsif ($OSf eq 'NetBSD') + { + $res='install -c'; + } + $conf{'GNU_INSTALL'}=$res; + print "$res\n"; + return $res; +} + +sub GenInstallDir() +{ + my ($mode,$dir)=@_; + + return "\$(INSTALL) -d -m $mode $dir\n"; +} + +sub GenInstallFiles() +{ + my ($mode,$files,$dir)=@_; + my (@f,$fl,$ret,$first); + + if ($conf{'SOLARIS_INSTALL'}) + {# Silly, crappy one ;-) + @f=glob($files); + return "\$(INSTALL) -m $mode -f $dir $files\n" if scalar(@f)==1; + $ret=''; + $first=1; + foreach $fl (@f) + { + if ($first) + { + $first=0; + } + else + { + $ret.="\t"; + } + $ret.="\$(INSTALL) -m $mode -f $dir $fl\n"; + } + return $ret; + } + return "\$(INSTALL) -m $mode $files $dir\n"; +} + +1; diff --git a/tvision/copying b/tvision/copying new file mode 100644 index 0000000..a43ea21 --- /dev/null +++ b/tvision/copying @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: 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) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/tvision/copying.rh b/tvision/copying.rh new file mode 100644 index 0000000..54d0d07 --- /dev/null +++ b/tvision/copying.rh @@ -0,0 +1,46 @@ +RHIDE is copyright (C) 1996-1999 by Robert H”hne. It is distributed under +the terms of the GPL which is written in the file COPYING. + + 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +Additional permission: + + As a special additional permission, the library librhuti which is + in the source tree of the RHIDE sources in the librhuti/ + subdirectory can be distributed alone freely without any + restrictions. It is not limited to use under the terms of the GPL + or LGPL. For more information see the file COPYING.RHU in that + subdirectory. + + +Non-binding request +=================== + +If you distribute RHIDE together with other products it would be nice, +if you could give me a note about it so I'll be informed. Of course +you can send me a copy of the distribution medium but this is not +required. + + +For contacting the author send electronic mail to + +robert.hoehne@gmx.net + +or paper mail to + +Robert Hoehne +Am Berg 3 +D - 09573 Dittmannsdorf +Germany diff --git a/tvision/debian/.cvsignore b/tvision/debian/.cvsignore new file mode 100644 index 0000000..0e62b95 --- /dev/null +++ b/tvision/debian/.cvsignore @@ -0,0 +1,5 @@ +rhtvision1 +rhtvision1.substvars +files +tmp + diff --git a/tvision/debian/README b/tvision/debian/README new file mode 100644 index 0000000..74a3e3d --- /dev/null +++ b/tvision/debian/README @@ -0,0 +1,34 @@ + This directory contains scripts and helpers used to create DEB packages. + The name "debian" is because Debian created the DEB format. That's the +same reason why the directory to create the .rpm files is called "redhat" +even when a lot of distros based on RPMs are available. + + These scripts are maintained by Ivan Baldo so you +should ask Debian specific details to Ivan with Cc to me. + + Using the .deb files instead of just using "make install" you'll get a much +better integration of the library with your system. + + In order to create the .deb files you need to install: + +A) Some packages used to create .deb files. I don't have a complete list at +the moment but in my system I have: debianutils, debhelper, debconf-utils, +dpkg-dev and devscripts. + +B) Some development packages. They are listed in the "Build-Depends" section +of the debian/control file. If any of them is missing the Debian scripts will +inform it. + +C) The fakeroot package if you want to create the .deb files running as a +regular user (recommended). + + To create the .deb files just run: + +$ debian/buildpackage + + The resulting DEB files should be located in ../ (../rhtvision*.deb). + To remove the temporal files created by Debian scripts run: + +$ debian/rules clean + +$Id: README,v 1.2 2003/06/23 14:12:03 set Exp $ diff --git a/tvision/debian/README.debian b/tvision/debian/README.debian new file mode 100644 index 0000000..0214fa2 --- /dev/null +++ b/tvision/debian/README.debian @@ -0,0 +1,19 @@ +RHTVision for DEBIAN +-------------------- +This is an UNOFFICIAL package and IS NOT PART OF THE OFFICIAL DEBIAN +DISTRIBUTION. +Send bug reports to me directly and NOT to the DEBIAN BUG TRACKING SYSTEM. +The original files are available for download at Borland's site and are +provided gratis. It still not clear if the sources can be redistributed +freely and we didn't get any reply from Borland's legal department. + +There is an APT repository on http://setedit.sourceforge.net/debian/, +ofcourse you can manually download packages for installing with dpkg if you +are not using APT. +If using APT, add the following line to your /etc/apt/sources.list: + deb http://setedit.sourceforge.net/debian woody main +You can substitute woody with the name of your distribution, for example +potato, sarge or sid. The use of aliases like stable, testing or unstable is +discouraged. + +Ivan Baldo , Wed, 17 Feb 1999 13:05:15 -0300 diff --git a/tvision/debian/buildpackage b/tvision/debian/buildpackage new file mode 100644 index 0000000..a4d0494 --- /dev/null +++ b/tvision/debian/buildpackage @@ -0,0 +1,5 @@ +#!/bin/sh +dh_testdir || exit $? +chmod +x debian/rules +dpkg-buildpackage -rfakeroot + diff --git a/tvision/debian/changelog b/tvision/debian/changelog new file mode 100644 index 0000000..f5fc8ef --- /dev/null +++ b/tvision/debian/changelog @@ -0,0 +1,543 @@ +rhtvision (2.2.0-1) unstable; urgency=low + + * Added AlCon (Alegro conio emulation) driver. + + -- Salvador E. Tropea Tue, 23 Jun 2009 14:14:45 -0300 + +rhtvision (2.1.0-5) unstable; urgency=low + + * Modified to compile with Lenny (now stable) + + -- Salvador E. Tropea Thu, 26 Feb 2009 16:15:23 -0200 + +rhtvision (2.1.0-4) unstable; urgency=low + + * Accept Salvador changes in his 2.1.0-4 but fixed to depend first in the + current non-transitional-dummy package of the GPM library. + * Also put those changes in the control file in addition to the control.in + one. + + -- Ivan Baldo Wed, 27 Aug 2008 00:34:14 -0300 + +rhtvision (2.1.0-3) unstable; urgency=low + + * Added XBS-Bugs: mailto:ibaldo@adinet.com.uy fields to the control file + so that reportbug sends bug reports to me instead of the Debian Bug + Tracking System. + * Bumped Standards-Version to 3.7.2.2, no changes. + + -- Ivan Baldo Tue, 08 May 2007 16:13:42 -0300 + +rhtvision (2.1.0-2) unstable; urgency=low + + * No longer delete these files because they no longer exist or are deleted + by the upstream now: linuxso/gkeyli.cc, linuxso/instlib, + linuxso/rhide.env, linux/rhide.env, linuxso/Makefile, linuxso/compat.mak, + intl/es_iso.mo, intl/es_iso.po, intl/es.mo, intl/ru.mo, intl/pl.mo. + * If you want to compile with GCC 4.0.3 comment out #undef _LIBINTL_H and + #define _LIBINTL_H 1 in include/compatlayer.h. + + -- Ivan Baldo Wed, 25 Jan 2006 20:21:46 -0200 + +rhtvision (2.1.0-1) unstable; urgency=low + + * New upstream version, still unstable so we cannot guarantee that nothing + bad happens to your dog if you use this stuff! + * Updated Build-Depends: added "file" (but I am not sure it is used or + needed, dpkg-depcheck reported it though), instead + of xlibs-dev | xlib6g-dev now it has libxmu-dev | xlibs-dev | xlib6g-dev + and libx11-dev | xlibs-dev | xlib6g-dev, this should give backwards + compatibility for various old Debian versions. + * Changed Depends of rhtvision*-dev package: removed libc6-dev and + libstdc++-dev since they are build-essential and also if someone is going + to compile something like a hello world in C++ they should have them, + instead of xlibs-dev | xlib6g-dev now it has libxmu-dev | xlibs-dev | + xlib6g-dev and libx11-dev | xlibs-dev | xlib6g-dev. + * Remove on clean the generated intl/pl.mo file (doh! come on Salvador! + provide a complete clean target! distribution packagers shouldn't be doing + this stuff). + * Bumped Standards-Version to 3.6.2.0, we should rename this package + librhtv but I don't like it too much. + + -- Ivan Baldo Thu, 18 Aug 2005 22:50:33 -0300 + +rhtvision (2.0.4-1) unstable; urgency=low + + * New upstream version, this is unstable yet, beware! + + -- Ivan Baldo Thu, 23 Dec 2004 19:17:59 -0200 + +rhtvision (2.0.3-3) unstable; urgency=low + + * Salvador says this is it!, this is the version that will be officially + released! CVS release 2.599 2004/11/02 20:06:39. + Greetings to all my fans!!! (do I have one?) Anyway, I dedicate this + release to Enyunari!!! + + -- Ivan Baldo Sun, 21 Nov 2004 16:29:07 -0200 + +rhtvision (2.0.3-2) unstable; urgency=low + + * With a new version of lintian it complained that we should not + build-depend on make and gzip because the first is a build-essential + package and the second is an essential package. + + -- Ivan Baldo Tue, 5 Oct 2004 20:24:34 -0200 + +rhtvision (2.0.3-1) unstable; urgency=low + + * New upstream version! CVS release 2.573 2004/09/22 21:26:40. + * Its been so long... I don't remember almost anything about Debian + packaging; I was very quiet all this time, without doing testing releases + and without testing developer versions. I am extremely lazy since then, + not only for this but for many other things of life in general, my home + computer isn't very well maintained neither and I am not very aware about + Debian as I was before. Anyway, lets try to be a bit useful and at the + same time thankful of this superb software. + * Bumped Standards-Version to 3.6.1.0 (and I hope it complies!). + + -- Ivan Baldo Sun, 26 Sep 2004 21:12:11 -0200 + +rhtvision (2.0.2-1) unstable; urgency=low + + * Upstream released a new fixed version! CVS release 2.493 2003/07/30 + 19:43:18 with sticky tag r2_0_2-1. + * Upstream fixed the show-stoper bug regarding the not versioned tvision.mo + files. + + -- Ivan Baldo Sun, 10 Aug 2003 15:10:43 -0300 + +rhtvision (2.0.2-0.1) unstable; urgency=low + + * New upstream version! CVS release 2.487 2003/07/16 14:00:57. + * Sorry for the lateness, but I am very busy now, too much work, though I + don't regret! I finally got a good job!!! + * Salvador did changes to the Debian packaging: + - Don't build-depend on recode (not required anymore). + - Added README file, it is similar to maintainer.notes. + - Added --no-libs-here --real-prefix=/usr to ./configure. + - If tar fails when doing the backup of files modified doing the build it + doesn't stop the package generation, because some tar failings are due to + files not existing or silly errors. + - Added usr/bin directory to the -dev package, since it will contain the + rhtv-config program. + * Added doc/I18n.txt and doc/Streams.txt to the -dev package. + * Now sets the flags for the compiler in the environment instead of in the + make invocation. + * Specify explicitly -g and -Wall compiling options. + * Supports DEB_BUILD_OPTIONS as per Policy 3.5.7. + * Bumped Standards-Version to 3.5.8.0 (and I hope it complies!). + * Removed a lot of obsolete files in files_to_backup. + * Remove on clean makes/rhide.env, redhat/librhtv-*.spec and + makes/libtvfintl.a. + * The debian/copyright file references the GPL license text in the + /usr/share/common-licenses/ directory, thanks Lintian!!! + * Remove final dots in the single line description of the packages, thanks + Lintian!!! + * There is a pending bug with this library which forces this to not be an + official final release: the .mo files are called tvision.mo, thus if the + user wants to install 2 different versions of the library, one will + overwrite the other and dpkg will complain, and if we force dpkg to + continue anyway, the translations will be messed up for one version of + the library. This is not Debian specific though. + + -- Ivan Baldo Sun, 27 Jul 2003 19:00:47 -0300 + +rhtvision (2.0.1-1) unstable; urgency=low + + * Yeah!!! New upstream stable version!!! Great! Thanks to all the friends + working on this library, specially to Salvador! + * This Debian release is dedicated to the crew of the space shuttle + Columbia. + * Build-Depends on gettext and recode to ensure correct i18n support. + + -- Ivan Baldo Sat, 1 Feb 2003 16:57:54 -0300 + +rhtvision (2.0.1-0.2) unstable; urgency=low + + * New upstream version, not yet stable. CVS dated 13 Dec 2002. + * Added examples/bhelp/thelp.mak to files_to_backup. + + -- Ivan Baldo Sat, 14 Dec 2002 19:22:09 -0300 + +rhtvision (2.0.1-0.1) unstable; urgency=low + + * New upstream version, near to be stable. CVS dated 3 Dec 2002. + * Specify absolute path in the ./configure --prefix=foo, this fixes + problems with wrong installation of translation files (.mo). + * Remove intl/es_iso.mo, intl/es_iso.po, intl/es.mo and intl/ru.mo. + * Backup linux/libtvfintl.a. + * Add locale files to the runtime library package. + * I am looking for a job (a paid one) for a long time but things are really + dificult here in Uruguay, if you have a job for me, don't hesitate to + contact! + + -- Ivan Baldo Wed, 4 Dec 2002 12:21:54 -0300 + +rhtvision (2.0.0-1) unstable; urgency=low + + * Well, this could be the first stable version if there are no major + problems. CVS dated 30 Sep 2002. + * Someone stole my bicycle!!! + * Added new documentation: doc/CodePages.txt, doc/ConfigFile.txt, + doc/Eterm.txt, doc/Linux.txt, doc/TVReference.html, doc/XTerm.txt and + THANKS. + + -- Ivan Baldo Thu, 3 Oct 2002 18:26:22 -0300 + +rhtvision (2.0.0-0.5) unstable; urgency=low + + * New beta from CVS dated 11 Sep 2002. + * Now is on feature freeze and testing period!!! + * Installs doc/X11.txt document (noticed by Salvador). + * Added information about APT repository in README.Debian. + * README.Debian wasn't being installed on the shared library package, only + in the -dev (static library) package, I don't know why dh_installdocs + just installs it for the 1st. package mentioned in debian/control only, + instead of installing it for all packages. + * debian/maintainer.notes: it was very outdated, now contains accurate and + more useful information. + + -- Ivan Baldo Wed, 11 Sep 2002 15:00:44 -0300 + +rhtvision (2.0.0-0.4) unstable; urgency=low + + * New alpha from CVS dated 5 Sep 2002. + * Removed the add-log-mailing-address Emacs directive from the changelog + since the policy now prohibits it (detected by lintian). + * Implemented safe calls to ldconfig (detected by lintian), added file + debian/rhtvision.postrm for that (and remembered to update debian/rules + and lista). + + -- Ivan Baldo Thu, 5 Sep 2002 17:43:19 -0300 + +rhtvision (2.0.0-0.3) unstable; urgency=low + + * New alpha from CVS dated 25 jul 2002 (hey! that's my birthday!!!). + * Removed debian/manpage.1.ex since it is likely that this package will + never need it. + * I changed my email from lubaldo to ibaldo, so updated that everywhere. + * Backup the following files: examples/clipboard/test.mak, + examples/fonts/genraw.mak, examples/helpdemo/helpdemo.mak, + win32/Makefile. + * Added more comments to the debian/rules file, it seems that Salvador was + confused one time :). + * Removed some CVS files and directories that where appearing on the + rhtvision2.0.0 package. + * Changed dependencies a little on debian/control, to help Potato users and + making the package more robust when building (suggested by Salvador), not + depend on specific versions of libraries or use | operators. + + -- Ivan Baldo Mon, 29 Jul 2002 16:49:04 -0300 + +rhtvision (2.0.0-0.2) unstable; urgency=low + + * New alpha from CVS dated 5 Jun 2002. + * Backup examples/tvhc/tvhc.mak. + * Don't remove win32/rhide.env but instead backup it. + * Don't remove winnt/Makefile. + + -- Ivan Baldo Thu, 6 Jun 2002 15:47:59 -0300 + +rhtvision (2.0.0-0.1) unstable; urgency=low + + * New alpha upstream release with a lot of changes and improvements, + most notably: native X11 suport! + * Small changes to debian/rules and debian/files_to_backup regarding + removing and backup of some files. + * Remove CVS directories from packages. + * Use dh_installexamples to install the examples of the -dev package. + + -- Ivan Baldo Tue, 14 May 2002 21:34:46 -0300 + +rhtvision (1.1.4-1) unstable; urgency=low + + * The "Ivan hates computers after having good vacations" release. + Well, I was on Punta del Este, good beachs, good womans, some fun + at night, and no computers :). My hate for computers is temporary + and it happens everytime I have good vacations, so don't worry. + * New stable version, it fixes some memory leaks, improves + compilation, some other tiny things, etc. + * No need to remove the configure.cache file from debian/rules, it + is done by the upstream makefile now. + * Added linuxso/makemak.pl and win32/rhide.env to the files_to_backup. + * Remove linuxso/rhide.env symlink on clean. + + -- Ivan Baldo Tue, 8 Jan 2002 12:08:52 -0300 + +rhtvision (1.1.3-3) unstable; urgency=low + + * Finally! RHTVision 1.1.3 is officially stable now! + * There was an empty and useless usr/share/man/man3 directory on the + package, now is gone. + * Added compat/compat.mak to files_to_backup. + * Remove generated linuxso/instlib on clean. + * Don't remove linuxso/makemak.pl on clean. + + -- Ivan Baldo Sun, 11 Nov 2001 15:41:50 -0300 + +rhtvision (1.1.3-2) unstable; urgency=low + + * Now compiles with -D_REENTRANT as Debian Policy mandates. + * Now runs ./configure before make clean (reported by Salvador). + * Don't eliminate the ldconfig invocation of the upstream Makefile, + it seems that upstream has corrected its Makefile now (done after + Salvador reported that it didn't work on all systems, because I was + overwriting the Makefile while I was reading it, specially on + multiprocesor systems). + * Added include/tv/configtv.h to files_to_backup. + + -- Ivan Baldo Wed, 17 Oct 2001 16:29:17 -0300 + +rhtvision (1.1.3-1) unstable; urgency=low + + * New upstream version. + * Upstream added a "buildpackage" script, I don't see the point of + it but if it is of some use to Salvador or others, I will keep it. + * Modified the new debian/buildpackage script to check before trying + to do anything that it is being run from the right directory. + * Simplified the backup system by using a TAR archive instead of + copying and moving files around. Good idea from Salvador. At the + same time now timestamps are preserved so CVS checkins are faster. + * Uncommented out the binary-indep target, just in case. + + -- Ivan Baldo Sun, 14 Oct 2001 01:15:59 -0300 + +rhtvision (1.1.2-1) unstable; urgency=low + + * New upstream version. + * Upstream provides clean target!!! At last!!! Let's use it. + * No more *.bkpdeb files on the distribution. + * Upstream clean is not complete yet, so we still clean some files on + our own. + * Added to backup system: linuxso/compat.mak and win32/Makefile. + * We delete the line containing 'ldconfig' on the Makefile, this + causes a failure when compiling with fakeroot. + * Added clean-debian to the .PHONY list. + * Added Replaces: rhtvision-dev for more easy upgrades. + + -- Ivan Baldo Sun, 7 Oct 2001 18:18:56 -0300 + +rhtvision (1.1.1-1) unstable; urgency=low + + * New upstream release!!! + * Salvador (upstream) made minor changes to some descriptions on the + control file and README.Debian for better description of the + distribution issues. + * Salvador also made small modifications to debian/rules to adapt to + his changes of my previous patch for the -fPIC compilation of the + compat library. + * Now before building we backup upstream files that are regenerated + and on clean we restore that files from the backups, so you can + build, rebuild, clean, reclean and original files are maintained. + As a plus this allows me to do a diff file for the upstream without + hassles. + * Now removes all .cvsignore files from the packages. + * Added xlibs-dev to Build-Depends so that the library compiles with + enhanced support for Eterm 0.8.10+. + + -- Ivan Baldo Fri, 28 Sep 2001 21:26:36 -0300 + +rhtvision (1.1.0-1) unstable; urgency=low + + * New upstream version! Rejoice. + * Modified compat/ticks.c to include stdlib.h otherwise NULL is + undefined. + * Updated cleaning of generated files. + * Support for compiling the compatibility library with PIC code (thanks + Lintian for reporting this!). + + -- Ivan Baldo Fri, 10 Aug 2001 16:07:50 -0300 + +rhtvision (1.0.9-4) unstable; urgency=low + + * Long time ago, this package (and other depending package) had to be + removed from the Debian distribution because of yet unresolved legal + problems with Inprise, fortunately the package had not been distributed + with any official Debian release. + * Slight changes to upstream source to make it compile on current + unstable distribution. + * Debian control file updated for new dependencies. + * Standards version 3.5.2.0. + * Do not use now deprecated dh_testversion, use a versioned build-dependency + on DebHelper instead. + * Made it clear that this is not an official package and that it is not + redistributable (control file, copyright, README.Debian, etc.). + + -- Ivan Baldo Sun, 10 Jun 2001 19:05:26 -0300 + +rhtvision (1.0.9-3) unstable; urgency=low + + * Standards version 3.1.0. + * Added Build-Depends. + * Architecture set to "any" instead of "i386 alpha" as requested by + Roman Hodek. This library isn't tested on other architectures other + than i386 or alpha, so, testing is needed and reports of success or + failures will be apreciated. + See bug 50319. + + -- Ivan Baldo Wed, 1 Dec 1999 00:38:51 -0300 + +rhtvision (1.0.9-2) unstable; urgency=low + + * Don't install manpage (symlink to undocumented(7) manpage). + * Remove .cvsignore file in usr/share/doc/rhtvision-dev/examples + directory. + * Don't use install-stamp (in rules file) anymore, to avoid possible + duplicate strings in maintainer script fragment files (see + debhelper changelog of version 2.0.56). + + -- Ivan Baldo Mon, 1 Nov 1999 13:01:46 -0300 + +rhtvision (1.0.9-1) unstable; urgency=low + + * New upstream version: + - Better support for greek keyboards. + + -- Ivan Baldo Tue, 26 Oct 1999 11:24:14 -0300 + +rhtvision (1.0.8-3) unstable; urgency=low + + * Previous version had wrong shlibs file. + + -- Ivan Baldo Sun, 26 Sep 1999 17:53:59 -0300 + +rhtvision (1.0.8-2) unstable; urgency=low + + * Upstream sent newer compilation scripts (bugfixes, enhancements). + * Modified and bugfixed debian/maintainer.notes. + * Now shared library package Conflicts: rhtvision1. This is to force + the people who installed the previously broken library to uninstall + that library and its programs and upgrade everything. Sorry. + * Now rm -f linuxso/librhtv.so on clean. + + -- Ivan Baldo Tue, 21 Sep 1999 12:50:24 -0300 + +rhtvision (1.0.8-1) unstable; urgency=low + + * New upstream version: + - Various bugfixes. + - Various improvements. + - Building system changed! + - Soname changes with every version (since every version is binary + incompatible). + * Now the -dev package depends on libstdc++-dev. + * Architecture is now i386 and alpha. + * Changed the name of the package from rhtvision to rhtvision1.0.8. + This name will change for every version of the library, since + every version is binary incompatible with the others. + * Improved and updated debian/maintainer.notes, please read it. + * Not include debugging version of the static library anymore. + If someone needs this, then tell me and I will include it again. + * Now requires debhelper 2.0.40 or greater (FHS related). + * Added DH_COMPAT=1 to debian/rules. + * Don't use .dirs files anymore. + * Don't use .files files anymore. + * Don't use .docs files anymore. + * Various changes to debian/rules file. + + -- Ivan Baldo Wed, 8 Sep 1999 15:33:29 -0300 + +rhtvision (1.0.7-1) unstable; urgency=low + + * rhtvision1-dev now goes in the devel section instead of the libs + one. + * New upstream version: + - Enhancements to the menu bar. + - Now runs on the Alpha processors. + - Bugfixes. + - Works better under xterm. + - Shorter ESC delay. + - Enhancements to the documentation. + - Runs better when you have write only permission for the vcsa's. + - Disabled CTRL+Z because it is dangerous. + - Other minor enhancements. + * Added source dependencies to debian/maintainer.notes. + * Modified #!/bin/sh to #!/bin/sh -e for better error detection. + * Policy 3.0.0 compliant (FHS move). + + -- Ivan Baldo Mon, 26 Jul 1999 17:19:36 -0300 + +rhtvision (1.0.5-2) unstable; urgency=low + + * I don't use dh_installexamples anymore, since it doesn't work for + me, instead I install the examples manually. So, there isn't + anymore the /usr/doc/rhtvision1-dev/examples/examples directory, + instead, there's only one examples directory. + + -- Ivan Baldo Tue, 1 Jun 1999 19:02:12 -0300 + +rhtvision (1.0.5-1) unstable; urgency=low + + * New upstream version: + - Bugfixes. + - Debian diffs incorporated on upstream source. + - Renamed the name of the library from libtv to librhtv. + - Some more classes added. + * Standards version now is 2.5.0.0 (no changes). + * Instead of doing the symlinks manually, now I use dh_link. + * Now requires debhelpers >= 1.2.9. + * Mention in debian/maintainer.notes that debian/rules should be mode + 755. + + -- Ivan Baldo Tue, 6 Apr 1999 22:24:13 -0300 + +rhtvision (1.0.3-6) unstable; urgency=low + + * Removed postrm for rhtvision1-dev and rhtvision1, since it is not + necessary. + * Removed postinst for rhtvision1-dev since it is not necessary. + * Packages checked with Lintian, there are some warnings yet... + * Added maintainer.notes, gives usefull information for the + maintainer (hey, thats me!). + * I forgot about doing a symlink in the rhtvision1-dev package from + rhtvision1.so to rhtvision1.so.1.0.3 (Lintian not complained about + this!). + + -- Ivan Baldo Fri, 5 Mar 1999 16:04:23 -0300 + +rhtvision (1.0.3-5) unstable; urgency=low + + * Applied patches from upstream maintainer. Avoiding deleting some + files that should not be deleted, added a clean-debian rule to + clean Debian specific files, only headers files are copied from the + include directory, and corrected the copying of files in the + example directory (it seems that the author has some files there + that don't need to be copied, dh_installexamples doesn't help very + much...). + * Made the clean target to depend on clean-debian, to avoid + repetition of code. + + -- Ivan Baldo Mon, 1 Mar 1999 00:29:43 -0300 + +rhtvision (1.0.3-4) unstable; urgency=low + + * I don't remembered to add -lgpm on the upstream makemak.pl file. + * Now the symlink is forced (-f parameter to ln). + + -- Ivan Baldo Sun, 28 Feb 1999 23:37:46 -0300 + +rhtvision (1.0.3-3) unstable; urgency=low + + * Removed some .ex files that never will be necessary. + * Corrected upstream makemak.pl script to make a shared library that + has dependencies, also added -pipe switch to gcc (little faster). + + -- Ivan Baldo Sun, 28 Feb 1999 22:35:57 -0300 + +rhtvision (1.0.3-2) unstable; urgency=low + + * Lots of bugfixes and now it works. + * First version showed to the upstream authors. + + -- Ivan Baldo Fri, 19 Feb 1999 02:14:01 -0300 + +rhtvision (1.0.3-1) unstable; urgency=low + + * Initial Release. + + -- Ivan Baldo Wed, 17 Feb 1999 13:05:15 -0300 + +Local variables: +mode: debian-changelog +End: diff --git a/tvision/debian/control b/tvision/debian/control new file mode 100644 index 0000000..3178e52 --- /dev/null +++ b/tvision/debian/control @@ -0,0 +1,43 @@ +Source: rhtvision +Section: libs +Priority: optional +Maintainer: Ivan Baldo +Build-Depends: perl | perl5, libncurses-dev, libgpm-dev | libgpmg1-dev, debhelper (>=2.0.40), libx11-dev | xlibs-dev | xlib6g-dev, libxmu-dev | xlibs-dev | xlib6g-dev, gettext, file +Standards-Version: 3.7.2.2 + +Package: rhtvision2.2.0-dev +Architecture: any +Section: devel +Depends: rhtvision2.2.0, libncurses-dev, libgpm-dev | libgpmg1-dev, libx11-dev | xlibs-dev | xlib6g-dev, libxmu-dev | xlibs-dev | xlib6g-dev +Provides: rhtvision-dev +Conflicts: rhtvision-dev +Replaces: rhtvision-dev +XB-Bugs: mailto:ibaldo@adinet.com.uy +Description: Development files for the RHTVision library - a TUI interface + This is the statically linked library and header files for the development + of applications using the RHTVision library. You need to install this package + only if you want to develop or compile programs using the RHTVision library. + . + THIS IS NOT AN OFFICIAL PACKAGE AND IS NOT PART OF THE DEBIAN DISTRIBUTION. + +Package: rhtvision2.2.0 +Architecture: any +Section: libs +Depends: ${shlibs:Depends} +Conflicts: rhtvision1 +XB-Bugs: mailto:ibaldo@adinet.com.uy +Description: The RHTVision library - TUI interface for console applications + This is the shared library for programs using the RHTVision library. + . + The RHTVision library gives an intuitive and user friendly TUI (Textual User + Interface) for programs using this library and running in a text console. + . + This library is based on the Turbo Vision library made by Borland Corporation. + It was interpreted by its upstream authors that the original Turbo Vision + library was released by Borland (now Inprise) under a Public Domain license, + but this seems to not be true. + . + There's a DOS and Win32 version of this library and on GNU/Linux runs on Alpha + and i386 processors. + . + THIS IS NOT AN OFFICIAL PACKAGE AND IS NOT PART OF THE DEBIAN DISTRIBUTION. diff --git a/tvision/debian/control.in b/tvision/debian/control.in new file mode 100644 index 0000000..41f9794 --- /dev/null +++ b/tvision/debian/control.in @@ -0,0 +1,43 @@ +Source: rhtvision +Section: libs +Priority: optional +Maintainer: Ivan Baldo +Build-Depends: perl | perl5, libncurses-dev, libgpm-dev | libgpmg1-dev, debhelper (>=2.0.40), libx11-dev | xlibs-dev | xlib6g-dev, libxmu-dev | xlibs-dev | xlib6g-dev, gettext, file +Standards-Version: 3.7.2.2 + +Package: rhtvision@version@-dev +Architecture: any +Section: devel +Depends: rhtvision@version@, libncurses-dev, libgpm-dev | libgpmg1-dev, libx11-dev | xlibs-dev | xlib6g-dev, libxmu-dev | xlibs-dev | xlib6g-dev +Provides: rhtvision-dev +Conflicts: rhtvision-dev +Replaces: rhtvision-dev +XB-Bugs: mailto:ibaldo@adinet.com.uy +Description: Development files for the RHTVision library - a TUI interface + This is the statically linked library and header files for the development + of applications using the RHTVision library. You need to install this package + only if you want to develop or compile programs using the RHTVision library. + . + THIS IS NOT AN OFFICIAL PACKAGE AND IS NOT PART OF THE DEBIAN DISTRIBUTION. + +Package: rhtvision@version@ +Architecture: any +Section: libs +Depends: ${shlibs:Depends} +Conflicts: rhtvision1 +XB-Bugs: mailto:ibaldo@adinet.com.uy +Description: The RHTVision library - TUI interface for console applications + This is the shared library for programs using the RHTVision library. + . + The RHTVision library gives an intuitive and user friendly TUI (Textual User + Interface) for programs using this library and running in a text console. + . + This library is based on the Turbo Vision library made by Borland Corporation. + It was interpreted by its upstream authors that the original Turbo Vision + library was released by Borland (now Inprise) under a Public Domain license, + but this seems to not be true. + . + There's a DOS and Win32 version of this library and on GNU/Linux runs on Alpha + and i386 processors. + . + THIS IS NOT AN OFFICIAL PACKAGE AND IS NOT PART OF THE DEBIAN DISTRIBUTION. diff --git a/tvision/debian/copyright b/tvision/debian/copyright new file mode 100644 index 0000000..5972e80 --- /dev/null +++ b/tvision/debian/copyright @@ -0,0 +1,15 @@ +This package was debianized by Ivan Baldo ibaldo@adinet.com.uy on +Wed, 17 Feb 1999 13:05:15 -0300. + +For more information of the upstream source or if you want to obtain it, +visit 'http://www.geocities.com/SiliconValley/Vista/6552/tvision.html'. + +Upstream author/maintainer: Salvador Eduardo Tropea . +Upstream initial author: Robert Hoehne . + +Copyright: +GPL, but wide redistribution is questioned because of unresolved legal +problems with Borland, please, contact upstream authors for more information. +On Debian systems, the complete text of the GNU General Public License can be +found in `/usr/share/common-licenses/GPL'. + diff --git a/tvision/debian/diversions.ex b/tvision/debian/diversions.ex new file mode 100644 index 0000000..aebbbe5 --- /dev/null +++ b/tvision/debian/diversions.ex @@ -0,0 +1 @@ + diff --git a/tvision/debian/files_to_backup b/tvision/debian/files_to_backup new file mode 100644 index 0000000..c8383d3 --- /dev/null +++ b/tvision/debian/files_to_backup @@ -0,0 +1 @@ +linux/libtvfintl.a diff --git a/tvision/debian/info.ex b/tvision/debian/info.ex new file mode 100644 index 0000000..05a4bde --- /dev/null +++ b/tvision/debian/info.ex @@ -0,0 +1,15 @@ +# This is a configuration files for installing a .info menu +# The Description to be placed into the directory +DESCR="Description" + +# The section this info file should be placed in (Regexp) followed by +# the new section name to be created if the Regexp does not match +# (Optional. If not given the .info will be appended to the directory) +#SECTION_MATCH="Regexp" +#SECTION_NAME="New Section Name" + +# The file referred to from the Info directory +FILE=rhtvision.info + +# Optional. The files to be copied to /usr/info +#FILES=*.info diff --git a/tvision/debian/maintainer.notes b/tvision/debian/maintainer.notes new file mode 100644 index 0000000..03ded78 --- /dev/null +++ b/tvision/debian/maintainer.notes @@ -0,0 +1,30 @@ +How to unpack and prepare the files: + Make sure that the debian/rules file is executable +(chmod 755 debian/rules). + In the file called version.txt in the root directory where you unpacked +the library, is the version number. If the debian/changelog file has a +different version number in the topmost change, then add a new change by +running dch -v 1.0.8-0.1 -p "unofficial personal package" (replacing 1.0.8 by +the current version number. Then modify the versions in the debian/control +file to match those of the library. + +How to make the .deb, .tar.gz, .dsc and .changes files: + cd rhtvision-directory + dpkg-buildpackage -rfakeroot + +To check the package (binary and source): + cd .. + lintian -i *.deb *.dsc + +To clean everything after building: + cd rhtvision-directory + fakeroot debian/rules clean + +Other notes: + - There is a clean-debian target on the debian/rules file, it only cleans + Debian specific files and not upstream build files. It is useful when + you just want for example to rebuild the package without recompiling + the sources (use debian/rules clean-debian). + - To rebuild the packages without recompiling the sources, use the binary + target on the debian/rules file (debian/rules binary). + diff --git a/tvision/debian/rhtvision.postinst b/tvision/debian/rhtvision.postinst new file mode 100644 index 0000000..fbad76b --- /dev/null +++ b/tvision/debian/rhtvision.postinst @@ -0,0 +1,6 @@ +#!/bin/sh -e +if [ "$1" = "configure" ]; then + ldconfig +fi + +#DEBHELPER# diff --git a/tvision/debian/rhtvision.postrm b/tvision/debian/rhtvision.postrm new file mode 100644 index 0000000..7a49c1d --- /dev/null +++ b/tvision/debian/rhtvision.postrm @@ -0,0 +1,6 @@ +#!/bin/sh -e +if [ "$1" = "remove" ]; then + ldconfig +fi + +#DEBHELPER# \ No newline at end of file diff --git a/tvision/debian/rules b/tvision/debian/rules new file mode 100644 index 0000000..15849da --- /dev/null +++ b/tvision/debian/rules @@ -0,0 +1,138 @@ +#!/usr/bin/make -f +# Made with the aid of dh_make, by Craig Small +# Sample debian/rules that uses debhelper. GNU copyright 1997 by Joey Hess. +# This version is for a hypothetical package that builds an +# architecture-dependant package, as well as an architecture-independant +# package. + +version=$(shell cat version.txt) +package=rhtvision +destdir=$(shell pwd)/debian/tmp/usr + +# Uncomment this to turn on verbose mode: +#export DH_VERBOSE=1 + +# This is the debhelper compatibility version to use: +export DH_COMPAT=1 + +# Set CFLAGS according to the Debian Policy: +CFLAGS = -D_REENTRANT -g -Wall +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif +CXXFLAGS = $(CFLAGS) + + +# Compile the beast!: +build: build-stamp +build-stamp: debianbackup.tar + dh_testdir +# Rename debian/rhtvision.postinst file if it exists (and others): +ifneq ($(wildcard debian/rhtvision.postinst),) + mv debian/rhtvision.postinst debian/rhtvision$(version).postinst + mv debian/rhtvision.postrm debian/rhtvision$(version).postrm +endif + CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" ./configure \ + --prefix=$(destdir) --fhs --no-libs-here --real-prefix=/usr + CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" $(MAKE) + touch build-stamp + + +# Clean everything as if nothing happened :) : +clean: clean-debian debianbackup.tar +# If we don't configure there is no guarantee that we have a Makefile: + ./configure --prefix=$(destdir) --fhs --no-libs-here --real-prefix=/usr + $(MAKE) clean +# Restore upstream provided regenerated files: + test -e debianbackup.tar && tar -xf debianbackup.tar + rm -f debianbackup.tar +# FIXME: ask upstream about adding the next files to his clean target: + rm -f compat/rhide.env examples/rhide.env include/tv/configtv.h Makefile \ + makes/rhide.env redhat/librhtv-*.spec makes/libtvfintl.a + rm -f build-stamp + +# Use the following target when you just want for example to rebuild the +# package without recompiling the sources: +clean-debian: + dh_testdir + dh_testroot +# Rename rhtvision$(version).postinst file if it exists (and others): +ifneq ($(wildcard debian/rhtvision$(version).postinst),) + mv debian/rhtvision$(version).postinst debian/rhtvision.postinst + mv debian/rhtvision$(version).postrm debian/rhtvision.postrm +endif + dh_clean + +# Let's backup modified files to restore them later!: +debianbackup.tar: + dh_testdir +# Backup upstream provided regenerated files: + -tar -cf debianbackup.tar --files-from=debian/files_to_backup + + +# Copy needed files to the temporary directories for the packages: +install: build + dh_testdir + dh_testroot + dh_clean + dh_installdirs -p $(package)$(version)-dev usr/lib usr/bin \ + usr/include/$(package) usr/share/doc \ + usr/share/doc/$(package)$(version)-dev \ + usr/share/doc/$(package)$(version)-dev/examples + dh_installdirs -p $(package)$(version) usr/lib usr/share \ + usr/share/doc/$(package)$(version) \ + usr/share/doc/$(package)$(version)/eterm + $(MAKE) install +# We need to move files for other packages than the first one in the control file: + dh_movefiles -p $(package)$(version) usr/lib/librhtv.so.$(version) \ + usr/share/locale/ + + +# Build the packages for a specific architecture: +binary-arch: build install + dh_testdir + dh_testroot + dh_installdocs -A borland.txt copying copying.rh readme.txt \ + doc/CodePages.txt doc/ConfigFile.txt doc/Eterm.txt doc/Linux.txt \ + doc/X11.txt doc/XTerm.txt THANKS + dh_installdocs -p $(package)$(version)-dev doc/TVReference.html \ + doc/I18n.txt doc/Streams.txt + dh_installdocs -p $(package)$(version) extra/eterm/ debian/README.debian + mv debian/$(package)$(version)/usr/share/doc/$(package)$(version)/README.debian \ + debian/$(package)$(version)/usr/share/doc/$(package)$(version)/README.Debian + dh_installexamples -p $(package)$(version)-dev examples/* + find $(destdir) debian/$(package)$(version) \ + \( -name '.cvsignore' -o -name 'CVS' -prune \) -exec rm -rf '{}' \; +# dh_installmenu +# dh_installemacsen +# dh_installinit +# dh_installcron +# dh_installmanpages +# dh_undocumented -p $(package)$(version) rhtvision.3 + dh_installchangelogs change.log + dh_strip + dh_compress + dh_fixperms +# dh_suidregister + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_makeshlibs -m$(version) + dh_md5sums + dh_builddeb + + +# Build architecture-independent files here. +binary-indep: build install +#This package doesn't have architecture-independent files for the moment... + +source diff: + @echo >&2 'source and diff are obsolete - use dpkg-source -b'; false + +# Build all the packages: +binary: binary-indep binary-arch + +.PHONY: build clean binary-indep binary-arch binary clean-debian + diff --git a/tvision/debian/shlibs.local.ex b/tvision/debian/shlibs.local.ex new file mode 100644 index 0000000..c5cb1ba --- /dev/null +++ b/tvision/debian/shlibs.local.ex @@ -0,0 +1 @@ +librhtvision 1.0.5 rhtvision (>> 1.0.5-0), rhtvision (<< 1.0.5-99) diff --git a/tvision/debian/watch.ex b/tvision/debian/watch.ex new file mode 100644 index 0000000..3313fc8 --- /dev/null +++ b/tvision/debian/watch.ex @@ -0,0 +1,5 @@ +# Example watch control file for uscan +# Rename this file to "watch" and then you can run the "uscan" command +# to check for upstream updates and more. +# Site Directory Pattern Version Script +sunsite.unc.edu /pub/Linux/Incomingu rhtvision-*.tar.gz debian uupdate diff --git a/tvision/djgpp/compress.bat b/tvision/djgpp/compress.bat new file mode 100644 index 0000000..385a80f --- /dev/null +++ b/tvision/djgpp/compress.bat @@ -0,0 +1,2 @@ +@Echo off +@perl compress.pl diff --git a/tvision/djgpp/compress.pl b/tvision/djgpp/compress.pl new file mode 100644 index 0000000..9458b3f --- /dev/null +++ b/tvision/djgpp/compress.pl @@ -0,0 +1,111 @@ +#!/usr/bin/perl +# Copyright (C) 1999-2003 by Salvador E. Tropea (SET), +# see copyrigh file for details +# +# Creates a distribution zip file. +# +require "../miscperl.pl"; + +GetVersion('../'); + +$r=cat('../include/tv.h'); +if ($r!~/$Version/) + { + die "Error! inconsistent version in tv.h\n"; + } + +$doBinary=0; +foreach $i (@ARGV) + { + if ($i eq '--binary') + { + $doBinary=1; + } + else + { + print "Unknown command line option: $i\n"; + print "Usage: compres.pl [--binary]\n\n"; + } + } + +# BC++ 5.5 Makefile +chdir('..'); +`perl confignt.pl`; +chdir('djgpp'); +# Patch the version number in the readme.txt +print "Processing readme file\n"; +$r=cat('../readme.in'); +$r=~s/\@version\@/$Version/g; +replace('../readme.txt',$r); + +# Generate the manifest and version files +$nv=$Version; +$nv=~ s/\.//g; +$binmft="manifest/tv$nv".'b.mft'; +$binver="manifest/tv$nv".'b.ver'; +$srcmft="manifest/tv$nv".'s.mft'; +$srcver="manifest/tv$nv".'s.ver'; + +chdir('../../..'); + +open(FIL,'contrib/tvision/lista'); +@files=; +close(FIL); +$r=''; +foreach $i (@files) + { + if (($i =~ /debian\//) || ($i =~ /redhat\//)) + { + next; + } + if ((substr($i,0,1) eq '-') or (substr($i,0,1) eq '+')) + { + $i=substr($i,1); + } + $r.='contrib/tvision/'.$i; + } +# Add example makefiles +@files=glob('contrib/tvision/examples/*/*.?mk'); +$r.="\n".join("\n",@files); +@files=glob('contrib/tvision/examples/*/*/*.?mk'); +$r.="\n".join("\n",@files); +@files=glob('contrib/tvision/examples/*/*.mkf'); +$r.="\n".join("\n",@files); +@files=glob('contrib/tvision/examples/*/*/*.mkf'); +$r.="\n".join("\n",@files); +# Manifest and version +$r.="\n$srcmft\n$srcver\n"; +# Sort the list +@files=split(/\n/,$r); +@files=sort(@files); +$r=join("\n",@files); +replace($srcmft,$r); + +open(FIL,'contrib/tvision/djgpp/distlist') || die "Can't open distrib list"; +@files=; +close(FIL); +$r=''; +foreach $i (@files) + { + chop($i); + print 'contrib/'.$i."\n"; + $r.=join("\r",glob('contrib/'.$i))."\r"; + } +$r.="$binmft\n$binver\n"; +replace($binmft,$r); +replace($binver,"Turbo Vision - C++ Text User Interface library, binaries (version $Version)"); +replace($srcver,"Turbo Vision - C++ Text User Interface library, sources (version $Version)"); + +# Generate the zip files +$bindist="tv$nv".'b.zip'; +$srcdist="tv$nv".'s.zip'; +unlink($bindist,$srcdist); +print "\nGenerating source distribution\n\n"; +system("zip -9 $srcdist \@$srcmft"); +if ($doBinary) + { + print "\nGenerating binary distribution\n\n"; + system("zip -9 $bindist \@$binmft"); + } + +chdir('contrib/tvision/djgpp'); diff --git a/tvision/djgpp/distlist b/tvision/djgpp/distlist new file mode 100644 index 0000000..828bb85 --- /dev/null +++ b/tvision/djgpp/distlist @@ -0,0 +1,9 @@ +tvision/readme.txt +tvision/copying* +tvision/borland.txt +tvision/djgpp/librhtv.a +tvision/include/*.h +tvision/djgpp/sacadeb.bat +tvision/djgpp/tmp/delete.me +tvision/djgpp/obj/delete.me +tvision/change.log diff --git a/tvision/djgpp/sacadeb.bat b/tvision/djgpp/sacadeb.bat new file mode 100644 index 0000000..d9089f6 --- /dev/null +++ b/tvision/djgpp/sacadeb.bat @@ -0,0 +1,10 @@ +cp librhtv.a tmp +cd tmp +ar -x librhtv.a +strip --strip-debug *.o +ar -r librhtv.a *.o +mv ../librhtv.a ../libtvdb.a +mv librhtv.a .. +rm * +cd .. + diff --git a/tvision/djgpp/tmp/delete.me b/tvision/djgpp/tmp/delete.me new file mode 100644 index 0000000..13340a4 --- /dev/null +++ b/tvision/djgpp/tmp/delete.me @@ -0,0 +1,2 @@ +Delete this file, is here just to include this directory in the package. +I know that's need for some un/compressors and is needed by my scripts too. diff --git a/tvision/doc/Alcon.txt b/tvision/doc/Alcon.txt new file mode 100644 index 0000000..5887a20 --- /dev/null +++ b/tvision/doc/Alcon.txt @@ -0,0 +1,112 @@ +Driver: Alcon +Author: Grzegorz Adam Hankiewicz, Salvador E. Tropea +Status: Not complete +Revision: $Revision: 1.2 $ + +This is the driver used for various platforms using the Allegro +(a game programming library): http://alleg.sourceforge.net/. +It has the potential of running under the same platforms supported +by Allegro, but at the moment it is being tested only under Linux +(X11 driver precisely). + + +1. INTRODUCTION +2. FEATURES +3. CONFIGURATION VARIABLES SPECIFIC FOR THIS DRIVER + + +1. INTRODUCTION + + You will need a version of Allegro installed on your system. The + driver has the potential to work with a stable Allegro release + (4.0.x), but on my system I always have the latest unstable + branch (4.1.x), so you might need this to build the driver. In + the future I'll make sure it works with 4.0.x, at the moment I + don't really care as there are not many users (two?). + + Building of the examples/demo seems to work ok. Building of + Setedit is at the moment not automatic. In order to have + this driver built by TVision, you need to explicitly pass + "--with-alcon" to the configure script. And verify that Allegro + is OK in the output. + + Also, any TVision programs you build with this driver will now + need the END_OF_MAIN() macro at the end of your main entry point, + like this: + + #define Uses_TProgram + #include + + int main(int argc, char *argv[]) + { + ... + } + END_OF_MAIN(); + + That's needed for Allegro's internal machinery. In order to have + the END_OF_MAIN declaration you have to request TProgram class, + but that's usually requested by all sources declaring main. + + +2. FEATURES + + The driver supports (or rather will some day): + + * Fonts. + * Palette. + * Most keyboard combinations, as long as Allegro's driver allows. + * Mouse. + * Weird graphic cursor capabilities. + + +3. CONFIGURATION VARIABLES SPECIFIC FOR THIS DRIVER + + Please read the documentation about the configuration file first. + + This driver has by default a very low priority. It is in + development, so you will need to bump the priority integer to + see it working. If you can't see any graphical difference between + X11 and Alcon, that means Alcon might not have been selected as + output driver. Ctrl+Alt+End (standard Allegro shutdown keyboard + shortcut) to see if the program finishes. + + Example of configuration file ~/.tvrc: + + [TV] + { + [Alcon] + { + Priority=220 + KeyboardMapping="langcode" + CursorHideNormal=1 + CursorOnSquare=10 + CursorOnCross=15 + } + } + + The priority has to be an integer number. The higher it is, the + most likely the AlCon driver will be selected (or rather, tried + before others). + + The KeyboardMapping is a string specifying the keyboard mapping + that should be used. By default Allegro looks for an allegro.cfg + file with the correct keyboard specification. To avoid creating + one, you can use this variable, which overrides whatever selection + is used later by Allegro. langcode is a two letter string with + the iso name of the language. Note that the keyboard mapping + datafile (keyboard.dat) has to be available somewhere on your + system for this to have any effect at all. + + CursorHideNormal is an integer variable. If it is different than + zero, the normal cursor won't be drawn ever. + + CursorOnSquare is an integer variable. If it is different than + zero, a square will be drawn bordering the cell the cursor is at. + + CursorOnCross is an integer variable. If it is different than + zero, a cross will be drawn through the cell the cursor is at. + + Note: All the integer variables related to the cursor are + accumulative. This means you can set many at the same time and + get their combined effect. + diff --git a/tvision/doc/CodePages.txt b/tvision/doc/CodePages.txt new file mode 100644 index 0000000..9d5b258 --- /dev/null +++ b/tvision/doc/CodePages.txt @@ -0,0 +1,219 @@ +Topics: Code Pages, TVCodePage +Author: Salvador E. Tropea +Status: Complete +Revision: $Revision: 1.1 $ + +1. INTRODUCTION +2. CODE PAGES IN TURBO VISION +3. FROM THE POINT OF VIEW OF THE USER +4. SUPPORTED ENCODINGS +5. FROM THE POINT OF VIEW OF THE PROGRAMMER +5.1 START UP AND CHANGES ON THE FLY +5.2 OTHER USEFUL INFORMATION + + +1. INTRODUCTION + + Most applications, Turbo Vision applications included, uses 8 bits +characters. It gives 256 possible combinations, but: what exactly means each +one? it depends on the system. To avoid problems some standars exists. DOS +uses some IBM/ANSI encodings like code page 437, 850, 866, etc., Windows uses +another set of code pages created by Microsoft (code pages 1250, 1251, etc.) +and most UNIX systems uses enconding described in the ISO 8859 standard. + In this way a document is: + +1) Compact, each character/letter needs one byte. +2) Exchangeable, you can use documents from other system just knowing which +encoding is used. + + Linux users should also read the Linux driver documentation, it have a lot +of information about the problems found on Linux systems. + + +2. CODE PAGES IN TURBO VISION + + TV uses code pages for four things. Three of them are really important for +users so we will focus only these three. + The first is the "Application code page". This code page indicates how the +application is encoded. An example of "application" stuff is the text you +load in TV editor. + The second is the "Screen code page". This is how the screen is encoded. +That's usually the same used for the application, but not always. An +interesting case is Linux where the screen can have any arbitrary encoding. + And the third is the "Input code page". That's how is encoded the text from +the keyboard. That's usually the same as the screen. An interesting case is +Win32 console API, it supports a different code page for input, but I never +saw a system configured like this. + Note that the application code page is how things are encoded internally, +input code pages is the encoding of the input and screen code page is the +encoding of the output. The center is the application. If any of the other +two code pages doesn't match a translation table is created. So you could +have a system where the accented characters from the keyboard are encoded in +code page 850 (DOS), the application in 1252 (Windows) and the output in ISO +8859-1 (POSIX). All will work ok. + + +3. FROM THE POINT OF VIEW OF THE USER + + Usually user doesn't have to mess with it. Applications that offer big +flexibility, code page translations, etc. should do it using friendly +dialogs. An example is SETEdit text editor. But even in this case the user +have to know the concepts explained in the first sections of this doc. + A special case where users could need to do some configuration is when +using Linux. A long explanation about it is found in the Linux driver +documentation. In this documentation Linux users will find a list of +supported code pages. Please refer to the index. + + +4. SUPPORTED ENCODINGS + + That's a list of supported encodings and the number used for each encoding. +This number is what you need to use for configuration variables like AppCP. + +Name ID +PC 437 ASCII ext. 437 +PC 737 Greek 737 +PC 775 DOS Baltic Rim 775 +PC 850 Latin 1 850 +PC 852 Latin 2 852 +PC 855 Russian 2 855 +PC 857 Turkish 857 +PC 860 Portuguese 860 +PC 861 Icelandic 861 +PC 863 French 863 +PC 865 Nordic 865 +PC 866 Russian 866 +PC 869 Greek 2 869 +CP 1250 Win Latin 2 1250 +CP 1251 Win Russian 1251 +CP 1252 Win Latin 1 1252 +CP 1253 Win Greek 1253 +CP 1254 Win Turkish 1254 +CP 1257 Win Baltic 1257 +Mac Cyr. CP 10007 10007 +ISO 8859-1 Latin 1 88791 +ISO 8859-2 Latin 2 88792 +ISO 8859-3 Latin 3 88593 +ISO 8859-4 Latin 4 88594 +ISO 8859-5 Russian 88595 +ISO 8859-7 Greek 88597 +ISO 8859-9 88599 +ISO Latin 1 (Linux) 885901 +ISO Latin 1u(Linux) 885911 +ISO 8859-14 885914 +ISO 8859-15 Icelan. 885915 +ISO Latin 2 (Linux) 885920 +ISO Latin 2u(Linux) 885921 +ISO Latin 2 (Sun) 885922 +ISO Latin 2+Euro (Linux) 885923 +KOI-8r (Russian) 100000 +KOI-8 with CRL/NMSU 100001 +Mac OS Ukrainian 100072 +Osnovnoj Variant Russian 885951 +Alternativnyj Variant RU 885952 +U-code Russian 885953 +Mazovia (polish) 1000000 +ISO 5427 ISO-IR-37 KOI-7 3604494 +ECMA-Cyr.ISO-IR-111 17891342 +JUS_I.B1.003-SERB ISOIR146 21364750 +JUS_I.B1.003-MAC ISO-IR-147 21430286 +Cyrillic ISO-IR-153 22216718 + + +5. FROM THE POINT OF VIEW OF THE PROGRAMMER + + The program can force the encodings using the TVMainConfigFile::Add +mechanism even before the application object is created. Read the +configuration file documentation for more information. + The fourth encoding involved in the process is the code page used for the +secondary font. But this encoding doesn't really affect TV. + You can change the encodings at any time using the TVCodePage::SetCodePage +member. To use the TVCodePage class use the Uses_TVCodePage request. The +source file for it is codepage.cc. Read the header for more information. + This class also provides members to replace some ctype.h functions. They +are: toUpper, toLower, toLowerTable, isAlpha, isAlNum, isLower and isUpper. +Note these members uses information from the current application code page. +If the value is properly set this information is usually much better than the +information you can get from C locales system. Also have in mind that a TV +application could be using a very different application encoding, if things +are properly configured it will be transparent, but in this case the ctype.h +functions will fail. + +5.1 START UP AND CHANGES ON THE FLY + + The library itself is encoded in the 437 code page. That's only for +historic reasons (Borland code was for DOS and that's the most common case on +DOS). The encoding used at run time is selected by the current driver. It +can be forced from the configuration file or the application as already +explained. + If the library determines the needed code page is different than 437 all +the internal information is recoded. Applications that uses characters +outside the ASCII range should provide a call back to be called when a recode +is needed. You can see an example in the demo program. + Here is a basic explanation on how it works: + +1) You set a callback *before* creating the application object using + + TVCodePage::SetCallBack(call_back_function) + + A call back prototype could be: + + void cpCallBack(ushort *map) + + The SetCallBack function returns the previous call back you should save it. + +2) This call back will be called when an application code page is done. The +map argument is needed to be passed to the TVCodePage members that does the +remapping job. They are RemapChar (for a single char), RemapString (for an +ASCIIZ string) and RemapNString (for a generic buffer). + After remapping all the needed stuff you should call the previous call +back. Note it can be a NULL pointer. + + When you have dynamic text that needs to be recoded, that's text in TView +objects that are already created and for some reason doesn't use a static +buffer to hold the special characters, you have to handle a special broadcast +called cmUpdateCodePage in the handleEvent member. In this case the infoPtr +event field contains a pointer to the needed map. + +5.2 OTHER USEFUL INFORMATION + + You can also create your own code pages providing an unicode table. + The library currently supports encondings that covers languages using the +latin, cyrillic and greek alphabets. If you think you can help with other +alphabets, enhance the currently supported or add/fix code pages information +please contact us. Note the library doesn't support a lot of important +details needed for some languages like: bidirectional writing, vertical +writings, glyphs composition, variable spacing, encodings that use more than +256 characters, etc. + An internal 16 bits encoding is used for the code pages, you don't have to +mess with it but routines to convert from and to Unicode are provided. + + TVCodePage also provides a member to convert from any of the known code +pages to another. + + Is important to understand that the remapping done when input, application +and output doesn't match takes some CPU, but it is currently implemented in a +very fast way so the overhead shouldn't be even meassurable. What we +currently do is to create one to one tables when the code pages changes. +That's all, no searches are done during the drawing. That's quite different +to what Linux kernel does, in this case a table converts input values to +Unicode and then they are searched in some sort of hash to be converted into +the screen encoding. We still using a code page internally, not Unicode nor +our internal code, so we don't have to do such a slow thing. The tables uses +a simple algorithm to find similar symbols when a value can't be represented +in the target code page, this value is put in the table, so even in this case +we don't need to search anything. You can know if the remapping is enabled +and do it using OnTheFlyRemapNeeded(), OnTheFlyRemap(uchar val), +OnTheFlyRemapInpNeeded and OnTheFlyInpRemap. + + Another important detail is how the keyboard works, note that sometimes the +keyboard is just a QWERTY keyboard that somehow generates the other alphabet. +In this case a key usually means more than one symbol and users spect that +Alt+Key is mapped to *both* things for objects like the menu. This is +supported, by I need help and testing. Currently the support is only for DOS +code page 737 and Linux KOI8-R. + + This functionality was introduced in version 2.0.0 of our port. The Borland +library didn't have it nor any serious equivalent. It just provided a virtual +member to do some stuff at start up. + diff --git a/tvision/doc/ConfigFile.txt b/tvision/doc/ConfigFile.txt new file mode 100644 index 0000000..46c3985 --- /dev/null +++ b/tvision/doc/ConfigFile.txt @@ -0,0 +1,200 @@ +Topics: Configuration file, TVConfigFile, TVMainConfigFile +Author: Salvador E. Tropea +Status: Complete +Revision: $Revision: 1.4 $ + +1. INTRODUCTION +2. FROM THE POINT OF VIEW OF THE USER +2.1 NAME OF THE FILE +2.2 STRUCTURE OF THE FILE +2.3 VARIABLES TO CONTROL TV +2.4 VARIABLES COMMON TO ALL DRIVERS +3. FROM THE POINT OF VIEW OF THE PROGRAMMER + + +1. INTRODUCTION + + The Turbo Vision library uses what we call "drivers". They aren't pure +driver as you find in Windows or other programs, but are used for the same. +The main difference between real drivers and what TV uses is that our drivers +aren't separated files, intead they are inside the library. + These drivers helps to isolate the hardware and system dependent stuff. +With this and with the help of the "compatlayer" library we can support a +wide variety of systems (DOS, FreeBSD, Linux, Solaris, Win32, etc.). + The drivers defines how to access to the screen, keyboard, mouse and other +OS stuff. + As these drivers are quite different and complex users could need to +configure some details. These details range from very generic to really +driver specific. + To avoid duplicating code in all applications and simplify the applications +the configuration can be done using a text file. + + + +2. FROM THE POINT OF VIEW OF THE USER + + Here I'll explain things that users and programmers needs to know, but not +information that only programmers needs to know. + +2.1 NAME OF THE FILE + + The configuration file is called "tvrc". On systems where hidden files have +a name starting with a dot (i.e. Linux) the file can be named ".tvrc". +Applications can use another name, but if the application specific file can't +be loaded the tvrc file is tried. + The file is searched in the following places: +1) The current directory. +2) The directory indicated by the HOME environment variable. +3) The directory indicated by the HOMEDIR environment variable. +4) The /etc directory. +5) The /dev/env/DJDIR/etc directory. This is DOS specific and used in djgpp +environments. This is translated to %DJDIR%/etc, that's the etc directory +inside the place you installed djgpp. + +2.2 STRUCTURE OF THE FILE + + The file is some mix between .ini files and C code. Sections starts with +the name of the section enclosed with brackets (i.e. [TV]). All the contents +of a section is enclosed using braces. Sections can be nested. + The main section used for TV configuration is called TV. All the +configuration information related to TV must be inside this section. + Each driver have a short name, please read the documentation about the +drivers to know the names. Here is a the list of currently supported drivers: + +AlCon For the Allegro Conio emulator. +DOS For DOS or compatible systems. +Linux For GNU/Linux systems. +QNX For QNXRtP systems. +UNIX For FreeBSD and other generic UNIX terminals. +Win32 For Win32 (Windows 95 and newer) systems. +WinNT Also for Win32 systems, just a different approach. +WinGr For Win32, but uses a graphical approach. +X11 For X11R6 systems, like XFree86. +XTerm For XTerm and Eterm terminal emulators. + + All the settings for a driver must be inside a section named as the driver. + Inside the sections you can set the value of the variables that control the +behavior of the driver or TV itself. + The variables must be followed by an equal sign and the value. Integer +variables can be in decimal, hexadecimal or octal using the C notation. +String variables must be enclosed using double quotes. Avoid using extra +spaces others than indentation spaces. + Here is a small example: + +[TV] +{ + [Driver] + { + IntegerVariable=10 + StringVariable="Hello" + } +} + + Note that applications could have separated sections to define variables +specific for the application. + +2.3 VARIABLES TO CONTROL TV + + The following variables controls the behavior of TV and should be defined +inside the TV section. + +DontMoveHiddenCursor Integer Currently TV moves the cursor always, even when + hidden. This is a little bit slow but helps + Braille terminals. When using the library in + slow machines or through slow remote + connections you can set this value to anything + different than 0 and you'll gain a small + speedup. +ShowCursorEver Integer If the value isn't 0 the text cursor is always + visible. This is used for development so you + can see where the cursor is located. Braille + terminals use the cursor position to read + information. If you want to know what a Braille + terminal will show you can enable it and + look for changes that can help Braille + terminals. +AltKeysSetting Integer Controls how Alt keys are interpreted. The + default value is 0 and means that left and + right keys are different. Using 1 the keys are + interpreted in the reverse way: left as right + and viceversa. Using 2 both Alt keys are + reported as "Left Alt Key". This is important + for the menues because the shortcuts uses the + left Alt Key. When using 2 any of the Alt keys + can be used to access de menues. + + +2.4 VARIABLES COMMON TO ALL DRIVERS + + The following variables are common to all drivers. It doesn't mean all +drivers will use them, sometimes the driver can't take an action to reflect +the value. An example are the screen size variables, Linux driver can't +change the screen size. Most of these variables can be defined in the TV +section and drivers will use them. So them can be used as defaults for all +drivers. The Priority variable doesn't have any sense in the TV section. + +AppCP Integer Indicates in which code page is encoded the + application. +ExtProgVideoMode String Indicates which external program should be used to + set the video mode. Even when that's generic only + DOS benefits from it. +FontHeight Integer Desired font height in pixels. +FontWidth Integer Desired font width in pixels. +InpCP Integer Indicates in which code page is encoded the + input data from the OS. +Priority Integer It selects the priority of the driver. Drivers with + higher priority are tried first. Usually this value + is in the range of 0 to 100. You can use it to force + the use of a driver that currently have less + priority. +ScrCP Integer Indicates in which code page is encoded the + screen. +ScreenWidth Integer Desired screen width. +ScreenHeight Integer Desired screen height. +ScreenPalette String This is used to change the color palette. This + string should contain the red, green and blue + components of the sixteen colors used by TV. Values + must be comma separated. So you should provide 48 + values. If some values are omitted the default VGA + BIOS values are used for the rest. The default + palette is usually what the VGA BIOS defines, but + not always. +VideoMode Integer Indicates which video mode should be used for the + screen. This is useful for DOS, but other drivers can + translate the most common DOS modes into a size and + try using the size. +AvoidMoire Integer Indicates the display produces annoying moire effects + when drawing "dotted blocks". When enabled the + classes tries to avoid using these chars. + + + +3. FROM THE POINT OF VIEW OF THE PROGRAMMER + + The configuration file is loaded in the constructor of TProgInit. The +configuration file is controlled by a class called TVMainConfigFile defined +in the configfile.cc source. This is an specialization of the TVConfigFile +class. + You can define your own sections in the configuration file and look for +configuration information there. + To use the classes use the Uses_TVConfigFile request. + You can specify a name for the configuration file, it must be full +qualified (path included). Use the TVMainConfigFile::SetUserConfigFile member +for it. It must be called before the application constructor. If this file +can't be found the library will look for the tvrc/.tvrc file. + Is also possible to define variables from the application before loading +the configuration file. These variable have more priority than the ones from +the file. Use the TVMainConfigFile::Add members for it. Note this class is +static and you can use it even before TProgInit constructor. Also note you +currently can do it only for TV section. + The TVMainConfigFile provides a variety of search functions you can use to +look for settings defined in the configuration file. + TScreen provides some search members that looks for variables in the +section for the current driver, if it fails they search in the TV section. +That's how defaults for all drivers are implemented. + This functionality was introduced in version 2.0.0 of our port. The Borland +library didn't have it nor any equivalent. The main objetive was to remove +the need for command line switches in all applications and allow the user to +set default values for all TV applications. + + diff --git a/tvision/doc/DOS.txt b/tvision/doc/DOS.txt new file mode 100644 index 0000000..1cffd28 --- /dev/null +++ b/tvision/doc/DOS.txt @@ -0,0 +1,171 @@ +Driver: DOS +Author: Salvador E. Tropea, Robert Hoehne +Status: Not complete +Revision: $Revision: 1.2 $ + + This is the driver used for the djgpp compiled binaries. The driver works +on DOS systems and any compatible variants. It can be used for any Windows +system including 3.1 and Win32 systems (95, 98, Me, NT, 2000, XP, etc.) and +systems like OS/2 that provides DOS emulation. + +1. INTRODUCTION +2. FEATURES +3. CONFIGURATION VARIABLES SPECIFIC FOR THIS DRIVER +4. NOTES ABOUT WINDOWS + + +1. INTRODUCTION + + This driver is really complex and the only way to make it work properly is +to have a good ammount of testers and maintainers. As the driver is currently +maintained only by me (SET) this driver is in very bad shape. + The main complexity of this driver is the need to support the restore of +the graphic video modes. This is a complex task because BIOSes have a lot of +bugs in their save/restore state routines. I saw this bugs are becoming more +and more frequent. + We verified such a bug in Matrox boards, it was fixed, but some people +still have VGA BIOSes with this bug. Then we also saw a similar bug in nVidia +GeForce VGA BIOS, I think it wasn't fixed by nVidia. These are just two +examples of popular boards. As I can't have a collection of video boards and +test the code in each one to see if it works things become quite complex. + My policy for TV 2.0.0 is to release the driver with the current problems, +but disabling some advanced features. These features won't impact on regular +programs but will most probably be a bad thing for RHIDE. RHIDE is an IDE for +djgpp that uses TV as TUI. + I think the code should be splitted in at least two drivers. One really +simple driver that doesn't support restoring graphic modes and another more +complex driver. Then RHIDE could request the second driver when a user knows +that graphics are needed and the code works ok for the target system. I don't +plan to do it any time soon unless I get volunteers to help. + + +2. FEATURES + + The driver supports: + +* Video mode configuration. Various modes are known and you can provide your +own mode or use an external program. +* Palette. The speed for it is high. +* Window title set/restore when running on Win32 systems. +* Most keyboard combinations. Some are lost if you use the BIOS strategy. [1] +* Restore command.com screen. +* Fonts. Primary and secondary. +* Mouse. Full support for drivers compatible with MSMouse v6.0. + + Notes about the screen: + Any text mode fully supported by BIOS and that is compatible with +mode 3 (VGA color) is supported, VESA modes are supported too, if you have +problems please report it. If you use a program that sets the video mode by +tweaking the VGA registers it will also set the BIOS data area to reflect the +new screen size or it won't work. + Additionally the library supports some build in modes: 82x25, 80x28, 80x30, +90x30, 94x30, 80x34, 90x34, 94x34, 80x35, 80x40, 80x43 and 80x50. + Note: if you wonder why 82x25 that's a mode where the characters have 8 +pixels of width and is very good for fonts with strange layouts like +ISO-Latin-1 (from Linux). + The hercules monochrome mode should be supported but I didn't test it for +a long time so perhaps something is broken, please report your experience +if you try it. + + + +3. CONFIGURATION VARIABLES SPECIFIC FOR THIS DRIVER + + Please read the documentation about the configuration file first. + +BIOSKey Integer By default the driver reads the keystrokes from the + BIOS buffer directly. This is faster and gives more + information. On some systems it fails and you'll need + to enable it. If you have access to such a system + please contact us so we can look for a better + solution. Use a value different than 0 to enable it. +PollMouse Integer The mouse information can be obtained using a periodic + poll or asking the DOS mouse driver to call us when + the mouse is moved or a button is pressed. The second + option is faster and you can't lose information. The + first option is safer. Currently the driver uses a + poll strategy by default. You can try disabling this + option to get better mouse support. Note that it is + always disabled for Windows NT and similar systems + (2000, XP, etc.). Use 0 to disable it. +SaveVGAState Integer In order to save and restore graphic modes you must + save a lot of information. This is achieved using a + standard VGA BIOS call. Some buggy BIOSes doesn't + implement it or implements it wrongly and returns + success. When it happends the result is a mess with + the screen, it usually goes black. Currently the + default value for it is 0, it means the VGA state + isn't saved. If you need to save it try enabling it + using a value different than 0. +VGABIOSState Integer This is related to the SaveVGAState variable. When + enabled we use VGA BIOS for the job. If you disable it + the driver will do it manually. It works for the + boards with buggy BIOSes, but the board must be 100% + VGA compatible at registers level (also the Windows + driver if you are using Windows). This uses very low + level stuff. +FixKbdBuffer Integer When enabled we assume the start of the keyboard + buffer is at offset 0x1E and the end at offset 0x3D. + When disabled (default) the size is monitored all + the time. + + +4. NOTES ABOUT WINDOWS + + I strongly recommend using the Win32 drivers for Win32 platforms specially +if the application will run using Windows NT (note that Windows 2000 and XP +are Windows NT 5.x). Windows NT 4.x have a bad DOS emulation and it looks +like 5.x made it even worst. + Here are some notes I had in the main readme file about this topic: + +Windows 3.x: + I didn't test it for years so I don't know the current status. + +Windows 9x: + Keyboard: + Almost the same support as in plain DOS. The TSR works at least in + Windows '95. Some keys are used by the GUI so not all are available I + include a .pif example showing how to avoid W9x take control of Alt+Space + and other keys. The example is in extra/pifexamp. + Screen: + The support is similar to the one found in DOS, but I know some video + drivers have bugs in the VESA handling so perhaps it could make problems. + If you face such a problem please contact me, in the past I fixed VESA + problems with S3 boards thanks to the help of a user. + Usually isn't a good idea to run applications that change the video mode + inside a window, so if your program does it recommend not running in a + window to your users. One way to avoid it is using a .pif file, it will + prevent 98% of the people from "windowizing" the program. See the + extra/pifexamp example for it, it instructs W95 to run the program in full + screen and disable Alt+Enter, the example also gives up to 64Mb to the + application (the maximun W95 will give to a DOS task). + Mouse: + Full support. + Note: I think all of it applies to Windows 98, if you see any difference + please tell me. + +Windows NT: + This platform isn't fully supported by the DOS target. I think NT's support + for DOS applications is completly broken so I don't care about it. If you + have patches I'll receive it. + + + +----------------------------------------------------------------------------- +Foot notes: + + +[1] Note that the driver ever takes the keyboard keystrokes from BIOS, it +can be using the BIOS interrupt or simply removing the key from the BIOS' +buffer. + The last approach reports much more keys but not all, in particular: + +* Control + `1457890=;,./ +* Macro key (I have it in one of my keyboards) + + To workaround it I created a small TSR (hacking another TSR and rewriting +the code inside the ISR ;-). This TSR is included with the sources +distribution in the extra/doskeys directory, you can distribute it with +your program if you want, just don't remove my copyright. + + diff --git a/tvision/doc/Eterm.txt b/tvision/doc/Eterm.txt new file mode 100644 index 0000000..38ebb96 --- /dev/null +++ b/tvision/doc/Eterm.txt @@ -0,0 +1,59 @@ +Driver: Eterm (part of XTerm driver) +Author: Salvador E. Tropea +Status: Complete +Revision: $Revision: 1.3 $ + +1. INTRODUCTION +2. FEATURES +3. IMPORTANT DETAILS + + +1. INTRODUCTION + + This driver was designed for Eterm 0.9.x. Previous versions like 0.8.10 are +no longer supported. + Use this driver when you have X Window but you need to use a remote machine +and the connection isn't fast enough to use the native X11 mode. + The driver isn't a full driver but a special mode of XTerm driver. For this +reason most of the information fro XTerm driver applies. Please read about +the XTerm driver too. + This driver is enabled when the environment variable TERM indicates the +terminal is called Eterm. Old Linux distros, like Debian GNU/Linux Potato, +defined Eterm terminals as xterm, that's wrong because they aren't the same. + + +2. FEATURES + + The driver supports: + +* Window size. +* Fonts size (no restore). +* Palette. Eterm is relative fast for it but the screen flashes quickly. +* Window title set/restore. +* Most keyboard combinations when a special Eterm theme is used. +* Restore shell screen (limited, you can't nest) + + +3. IMPORTANT DETAILS + + In order to get the maximum of key combinations you must install and use an +Eterm theme specially designed for Turbo Vision applications. + If you have problems with the Alt key combinations please try using the +Eterm command line option --meta-mod. Traditionally UNIX terminals have a key +called Meta (Sun keyboards have it) and what you really need is this key, so +you must tell Eterm to use the Alt modifier as Meta modifier. + The files are stored in examples/eterm. Copy this files to +~/.Eterm/themes/tvapp or to /usr/share/Eterm/themes/tvapp if you want to +make this theme globally available. Then start Eterm with: + +$ Eterm -t tvapp + + Note this theme is specially configured for TV applications and isn't the +best for other tasks. I recommend to use at leat two connections to the +remote machine, one for general tasks and another from an Eterm with the +tvapp theme to run TV applications. + For instructions on how to test this driver locally, supported +configuration variables and other details read the XTerm driver +documentation. + + diff --git a/tvision/doc/I18n.txt b/tvision/doc/I18n.txt new file mode 100644 index 0000000..f944fe4 --- /dev/null +++ b/tvision/doc/I18n.txt @@ -0,0 +1,251 @@ +Topic: Internationalization messages +Author: Salvador E. Tropea +Status: Not complete +Revision: $Revision: 1.2 $ + + This document covers the use of TV facilities to translate messages. I call +it "internationalization for messages" and you'll find it as i18n in many +places of this docs and the library. + The library uses the gettext approach and you should reffer to GNU gettext +implementation for more information. For GNUished systems try: + +$ infview gettext +or +$ info gettext + +to get information about GNU gettext or try searching "GNU gettext +Introduction utilities" in Google. + From here I'll assume you know what gettext is and have some basic notions +about how to use it. I'll explain some stuff here anyways, but only to +refresh the concepts. + +Note: I used relative paths in all the references to files so you can load the +named file just pressing Alt+Enter if you are using SETEdit. + +1. HOW IT WORKS +1.1 FOR THE PROGRAMMER +1.2 FOR THE PROGRAM +1.3 INTERNALLY +1.4 MORE TVINTL MEMBERS AVAILABLE + +1. HOW IT WORKS + +1.1 FOR THE PROGRAMMER + + Here are the steps from the programmers point of view: + +1) You mark all the strings that will be translated in your code. We use +_(...) for strings that will be translated "in-situ" (it will call gettext) +and __(...) for strings that will be translated elsewhere (expands to +nothing, just marks the string). + +2) You call xgettext (to remmember it: eXtract for GETTEXT) indicating which +is the delimiter and which files should be scanned. It can be done from a +makefile or manually. The ../searchstrs.sh is an example, it parses a file +that contains the list of files distributed in TV package and extracts all +the C++ files, the list is passed to xgettext and it generates a file called +dummy.po. For a more automatic mechanism look in setedit package +(http://setedit.sf.net/). I use a makefile there. + + 3) The translators creates translation files from the extracted messages. +Examples of these files are: ../intl/es.po and ../intl/ru.po. Note these +files *must* contain a header indicating the encoding because gettext assumes +all is UTF-8 unless other thing is indicated. +4) You create the binary files containing the translations. They end with .mo +and are created using msgfmt (MeSsaGes ForMaT). This file is a hash +containing the untranslated messages as keys (msgids) associated with the +translated messages (msdstrs). They are usually created using a Makefile like +it: ../intl/Makefile. + +5) The user installs them when all binaries are installed. + + +1.2 FOR THE PROGRAM + + Now from the point of view of the code. + +1) We already marked the strings to translate. _(...) marks will be expanded +to calls to TVIntl::getText(...) and you'll get the translated message there. +The __(...) entries will be expanded to the string and you'll have to ensure +the TVIntl::getText(), or equivalent member, is called. +2) If you don't enable the translation at start-up, usually from main and +before creating the TApplication object, it won't be enabled and the routines +won't translate anything. So you have to put something like: + + TVIntl::textDomain("mi_program"); + +at the beggining of main. You should know what is "textdomain" from the +gettext docs ;-). That's the name of the .mo files, that's usually the name +of the program. I reffer to the file containing the translations as the +"catalog" and the name without the extension as "domain". So what you pass +here is the name of your domain and with it gettext will search in: + +BASE_DIR/LANGUAGE/LC_MESSAGES/domain.mo + + The "language" is selected with the LANG environment variable and the +BASE_DIR is system dependent. You can force BASE_DIR using: + + TVIntl::bindTextDomain("mi_program","base_dir"); + TVIntl::textDomain("mi_program"); + + Or just: + + TVIntl::autoInit("mi_program","base_dir"); + + If for some reason you must force the language just use putenv() like in +../examples/i18n/test.cc + So this line of code is the only thing needed to enable translations. + + +1.3 INTERNALLY + + Ok, here I'll explain some internal details. + +1) If the configure script doesn't detect gettext it will be enabled and a +library providing dummies will be created to satisfy the undefined +references. If that's your case the configure script will put a huge warning +explaining you must link with the dummies. + If you want to completly disable it use the --no-intl configuration option. + +2) The _(string) will be expanded to TVIntl::getText(string) unless --no-intl +was used, in the last case it will be just string. + This will be call the lintintl's gettext function, but if gettext can't +find a translation in the current domain (the one for your application) the +function will also try a search in the tvision domain. For this reason you +don't need to include translations for the TV strings in your catalogs. This +is a little bit slower but makes life easier. + +3) Currently most TV classes translates their messages. For this reason +you'll usually just need to use __() and not _(). Some classes also accepts +"caches" as arguments, more about them in 4. + +4) Even when most programs can live with it a big problem appears for TV +applications: the code page. TV applications supports over than 40 code pages +and they can be changed on-the-fly, they can also be changed so the +application and screen code pages doesn't match (see doc/CodePages.txt ). To +add more complexity the code pages doesn't really match the ones covered by +recode and iconv library. Another detail makes things even worst: iconv is +useless for DOS applications where dynamic libraries aren't used and it adds +about 800 KB to each executable. For these reasons, and others, TV uses their +own code page translation system. + This small detail complicates things a little bit. The problem is that we +must recode strings returned by gettext, but they are "const char *" (even +when the prototype doesn't make it explicit). The GNU gettext library solves +it internally using a "centralized cache". I don't like this approach because +it can waste space and is really bad for efficience. So I designed a +"distributed cache" approach. + When you have a string that will be translated often you have to create a +cache for it. To do it just declare a "stTVIntl *" variable and initialize it +to NULL indicating the cache is free (failing to do it will SIGSEGV). At the +point you have to translate it use "TVIntl::getText(msgid,cache)", it will +return the associated msgstr. When you don't need the cache anymore just use +TVIntl::freeSt(cache). + Here is where to put each thing in a TView class: + +class XXXX : public TView +{ +.... +protected: + stTVIntl *cache; +}; + +// Constructor +XXXX::XXXX() : TView(....) +{ + cache=NULL; +} + +// Point where you need the string +void XXXX:draw() +{ + const char *msgstr=TVIntl::getText(__("The string"),cache); + .... +} + +// Destructor +XXXX::~XXXX() +{ + TVIntl::freeSt(cache); +} + + Here is more about what it does: When you call getText it checks if the +cache is already in use or not. If the cache is in use the string will be +extracted from the cache and gettext won't be called. If the cache isn't in +use the library will fill it using gettext. If the cache is in use but the +last search returned that this string doesn't have translation it will return +the untranslated message. If the i18n system is disabled it will ever return +the de untranslated message. + The cache also holds which code page was used to recode the string, if this +changes the string is discarded and a fresh one is used memorizing the new +code page. + Note the chache knows nothing about the domain from where the string came +from, so avoid changing domains on the fly, it won't work well. + In this way the cache lives as long as you need it and not for the live of +all the program. Also note that a program that changes between code pages +back and forth doesn't have to invalidate all the cached strings. + When you need the string for a small time or just doesn't want to cache it +you should use: + + char *msgstr=TVIntl::getTextNew(__("The string")); + // Use it + DeleteArray(msgstr); // Release it + + This will return a newly allocated buffer (you can even modify it if you +like) and this buffer will be in encoded in the "application" code page. + Note that if you use: + + const char *msgstr=_("The string"); + + or + + const char *msgstr=TVIntl::getText(__("The string")); + + You'll get an string encoded in the catalog code page, no matters what's +the application and screen code page. So you can't be sure it will look ok. + +5) More about code pages: as TV can recode, and in fact recodes if you use +the above mentioned members, the best thing is to keep the catalogs in a +fixed encoding for a given language. For this reason TV assumes you encoded +the catalog using a fixed code page. Currently TV assumes it for german (de), +russian (ru) and spanish (es): + +DE: ISO 8859-1 +ES: ISO 8859-1 +RU: KOI8-R + + This is because I have catalogs only for those languages (german is very +incomplete). So you have to encode the .po files using those convetions for +all the OSs used. TV will do the rest of the work. + My test bed is SETEdit, in the past I had spanish catalogs encoded in CP850 +for DOS and ISO 8859-1 for Linux avoiding iconv. Now I have the catalog in +ISO 8859-1 and it works for all systems. + + +1.4 MORE TVINTL MEMBERS AVAILABLE + + Here are the rest of members that TVIntl offers: + +void setCatalogEncoding(int cp) +Use it to force the code page used for a catalog. + +void enableTranslations() +void disableTranslations() +You can use it to stop/start translating messages. + +stTVIntl *emptySt() +Returns an empty cache, it will be filled as soon as passed to getText. + +stTVIntl *dontTranslateSt() +Creates a special cache that prevents from even trying to translate the +message when passed to getText. Use it when you have to pass a string that's +already translated and the class accepts a cache. + +int snprintf(char *dest, size_t sz, const char *fmt, ...) +Like the standard snprintf but it translates the "fmt" string. Please use it +and also CLY_snprintf to avoid buffer overflows. + +int fprintf(FILE *f, const char *fmt, ...); +Must be requested defining "Uses_intl_fprintf". +Is just like fprintf but it translates fmt before using it. + + diff --git a/tvision/doc/Linux.txt b/tvision/doc/Linux.txt new file mode 100644 index 0000000..722d45b --- /dev/null +++ b/tvision/doc/Linux.txt @@ -0,0 +1,274 @@ +Driver: Linux +Author: Salvador E. Tropea, Robert Hoehne +Status: Complete +Revision: $Revision: 1.6 $ + + This is the driver for the Linux console. It can't be used for X or +other UNIX terminals. This driver is used when the terminal can be +identified as "console" or "linux*". + +1. INTRODUCTION +2. THE KEYBOARD +3. ENCODINGS AND FONTS +4. SECONDARY FONT AND SYSTEMS WITH 512 CHARACTERS +5. CONFIGURATION VARIABLES + +1. INTRODUCTION + + This driver is quite complex and you could need to configure your system +and/or Turbo Vision to get all the features or to even get it working. This +is a bad thing, but that's how Linux is implemented. + Two important things affects the behavior of this driver: + +1) If the user have rights to write to the /dev/vcsa* devices. Usually users +don't have access to these devices. This is because somebody logged in your +system could write to your screen to make you do something wrong or expose +important information. Lamentably these devices doesn't check if the owner is +who opened the device, a simple rights test is done. When the user can write +to this device the performance of the library is much better. I recommend +using it unless your system is used by a lot of untrusted persons. +2) If you are running the application in a real console or not. Note that +sometimes you can be using the real console but through a program that starts +their child processes in a way that they aren't really attached to the +console. A common case is the "midnight commander" program, it runs the +commands you type in something like /dev/pts/N. You can find it using the tty +command. Currently Turbo Vision can bypass applications like midnight +commander, but some stuff (like the keyboard) lose functionality. + + To solve the first point I recommend creating a group for the /dev/vcsa* +devices, something like: + + $ addgroup vcs + + Then add the user/s you want to give access to the device: + + $ addgroup user vcs + + Finally change the /dev/vcs* right and owner like this: + + $ chown root.vcs /dev/vcs* + $ chmod 0660 /dev/vcs* + + In this way you can control which users can read or write the screen using +these devices. + The second point is simple: run the application without using programs like +midnight commander. + When the application runs in the real console you can: + +1) Change the fonts. +2) Find information about the screen and input encoding. +3) Get good information about keyboard modifiers (shift, control, alt, etc.). + + +2. THE KEYBOARD + + The library uses the keyboard in "cook mode", this is much more safe than +using "raw mode" and in this way all the keyboard configuration is honored. +But this have a drawback: the information from the keyboard is incomplete and +some keys are used by the kernel. + To solve the first issue this driver uses a Linux IOCTL that return the +current state of keyboard modifiers (like shift). The IOCTLs only work if the +process owns the real console. It won't work if you run the application using +a remote connection (i.e. ssh) or something like midnight commander. + The second problem is more complex. Some common keys, like Shift+PgUp or +Alt+Function_key, are used for special purposes. IMHO this is a bad idea, but +is a fact. In order to solve this problem this driver modifies the kernel +tables a little bit. When you switch to another console or normally exit the +application this reverted. If it fails the solution is to reload the keyboard +map. Use the loadkeys command for it. + For this reason you can't switch to another console using Alt+Fx, use +Ctrl+Alt+Fx, as you do when running X. + Note that this driver *doesn't* uses ncurses nor parses the terminal +description. It means this: if you force Delete to report a strange escape +sequence and put this information in the terminfo database it won't work. It +will work for other applications, but not for this driver. + Why not ncurses? ncurses is bulky and unpredictable, we had too much +problems using ncurses. Currently ncurses is only used by the generic UNIX +driver. + Why not reading terminfo/termcap information? this information usually have +errors and needs a lot of code. + + +3. ENCODINGS AND FONTS + + Linux have a complex and flexible mechanism to support the different text +encondings (code pages). But this is wrongly used by the console-tools +(formerly kbd) tools and Linux distributions. This generates a lot of +problems. Another issue is that Linux kernel is wrongly designed, you have +services to setup things but you don't have the mechanism to know (and save) +the current state. It gets even worst when you use escape sequences and you +don't have access to the IOCTLs. + The first thing you must understand is that code pages concept doesn't +exist for the Linux kernel. This is quite different to DOS, Windows, MacOS, +etc. where you have fixed encodings with known names. What Linux understands +are just translation tables. Usually people uses some tables that are quite +common, but sometimes these tables changes or are just adjusted by a vendor. +A complete explanation about this topic is outside the scope of this +document, If you want to know more about this topic read the html +documentation included with console-tools. What I'll describe here is just a +simplification. + +3.1 TABLES TO TRANSLATE WHAT? + + Most applications, Turbo Vision applications included, uses 8 bits +characters. It gives 256 possible combinations, but: what exactly means each +one? it depends on the system. To avoid problems some standars exists. DOS +uses some IBM/ANSI encodings like code page 437, 850, 866, etc., Windows uses +another set of code pages created by Microsoft (code pages 1250, 1251, etc.) +and most UNIX systems uses enconding described in the ISO 8859 standard. + In this way a document is: + +1) Compact, each character/letter needs one byte. +2) Exchangeable, you can use documents from other system just knowing which +encoding is used. + + But this scheme isn't enough to represent all possible characters of +languages like chinese, japanese, etc. To represent these things you need an +extended system. Unicode is a really complex mechanism to achieve it. Unicode +implies a lot of complex things, but the most widely used thing is the +ability to reprsent the most common languages used in the world using a +standarized mechanism. + The Linux kernel currently uses Unicode (16 bits variant) for internal +purposes. You can also enter text using the UTF-8 mechanism, that's a special +way to encode Unicode using variable length characters. + What Linux does is: when a character is received by the kernel it is +converted into Unicode (first table), it is processed and when the kernel +needs to print it the value is converted to 1 byte (second table, this isn't +in fact a table). + The first conversion is from the application encoding to Unicode and the +second is from Unicode to the screen encoding. + Here you can see the first complexity: the application can be encoded in a +way and the screen in another. For stupid reasons is quite common to use it +in Linux systems. The reasons are all stupid and the result is a waste of +performance and added complexity. + You can skip this paragraph if you don't want to know about some of the +stupid things common to almost all Linux systems. One of the problems people +faced in the past was that VGA video controller uses 8 pixels width fonts, +but they are represented as 9 pixels in the screen. What's in the 9th column? +It depends on the value to represent, usually it is filled with a blank +column, it helps to keep the characters visually separated. But a particular +range of values uses the same information found in the 8th column. This range +corresponds to the graphics used for frames in the code page 437, that's +because the boards have a 437 encoding by default. This range is used by ISO +8859 standard and the result is that linux encodings have the frames in the +range where the 9th column is blanked. This generates ugly frames. The real +solution for that is to just modifiy the VGA registers to create a video mode +where characters have 8 pixels. It also have a plus: you gain a couple of +columns that could be used by the kernel and/or the user. But lamentably +people uses a wrong approach. Instead of it a tweaked encoding is used. This +is the difference between lat1 and lat1u fonts. Another lamentably fact is +that newer packages (Debian Potato and Woody for example) have files called +lat1* that are in fact the tweacked lat1u* files. Another stupid thing is the +fact that most Linux distros doesn't load a font, all of them should load ISO +8859-1 because that's what the applications uses by default. Usually distros +just let the 437 default BIOS encoding, it only generates confusion and +avoids the use of a bypass for the translations. The bypass is possible +because ISO 8859-1 is a subset of Unicode (the first 256 values). + Ok, again in the topic: the first table is what is called ACM (Application +Charset Map) and the second is called SFM (Screen Font Map). + The first is a real table, it maps one to one. A value from the application +(8 bits) is translated into an Unicode value (16 bits in this case). The +second isn't a real table because more than one Unicode value can be +represented by the same drawing (similar or identical, remmember Unicode is +much more than an encoding). Things are even more complex because a table +with 65536 entries isn't a good idea. For this reason this map is more +complex and the kernel doesn't use a table. + +3.2 WHY IS THAT A PROBLEM IF ALL LINUX APPLICATIONS WORKS OK? + + The main problem appears when you want to access to the screen using the +/dev/vcs* devices. In this case you are bypassing the kernel translation. + Another problem appears if you have to know more about the text you are +handling. The C locales mechanism is useless because it only covers really +standard code pages. + Most Linux applications: +1) Uses a slow screen output, after all most of them have a crappy look. +2) Doesn't really know much about encodings, just know how to draw the +frames. + +3.3 WHAT'S THE PROBLEM? + + At first sight it just looks complex, but not impossible. After all doesn't +really matters if these tables follows an standard or not if you can analyze +them. + But things are more complex. This information is only available using +IOCTLs so you can't do it when using a remote console. Currently the library +just does a guess using the contents of the LANG environment variable. If +this guess is wrongly done just use the the configuration file (tvrc). + Another problem is that some maps wrongly done. The KOI8-R is a good +example. Here the ACM doesn't translate the input into Unicode, instead the +text passes without change (or a very small change in some systems, to make +things even worst). It works because the SFM is also wrong and in fact is a +KOI-8R->Screen conversion and not Unicode->Screen. You get a table that is +supposed to be encoded in Unicode but it isn't. + The driver anlyze the code page and tries to figure out what encodings are +used but it can fail. If it doesn't work for your system please contact me +and we will try to find some solution. + +3.4 HOW TO FORCE THE ENCODINGS + + If you know how your system is encoded look for the closest code page +supported by Turbo Vision, they are defined in codepage.cc, and create a +configuration file indicating the encoding. + The configuration variables used for it are: AppCP and ScrCP. The first is +the equivalent to the ACM and the second is like the SFM. + To force KOI8-R you can use: + +[TV] +{ + [Linux] + { + AppCP=100000 + ScrCP=100000 + } +} + + +4. SECONDARY FONT AND SYSTEMS WITH 512 CHARACTERS + + Linux supports loading an extended font with 512 characters instead of 256. +This isn't currently supported by this driver because things are all 8 bits. +I don't really know the result. If you use such a system please contact me. + Turbo Vision now supports loading fonts and you can use it if you are +running in the Linux console. TV also supports loading a secondary font. This +can be used for very special cases. To achieve it the driver uses a 512 +characters font, the first 256 for the primary font and the other 256 for the +secondary. By default this is disabled because the kernel reduces the colors +to 8 when you load a 512 characters font. This is quite logical when the 512 +symbols belongs to one big encoding but really annoying when they are two +different fonts. To enable it use the UseSecondaryFont configuration +variable. + Note: The PC VGA controller uses eight bits for color attributes. Four are +used for the foreground color and the other four for the background color. It +gives sixteen colors. But the most significant bit of each color have a +second meaning that can be optionally enabled. The fourth bit of the +background is used for blinking and the fourth bit of the foreground is used +to select a second set of characters. This is why Linux reduces the colors to +eight, but the bit still working, you can still using sixteen colors. The +last is what TV uses. What Linux does is to redefine the colors to be the +same and disables any attempt to reprogram the palette entries to these +colors. + + +5. CONFIGURATION VARIABLES + + This driver supports the following variables: + +* AppCP, ScrCP and InpCP. The point 3 explains the first two. The InpCP is to +force the encoding of the keyboard and isn't usually needed. +* UseSecondaryFont explained in 4. +* LoadSecondaryFont: Request a secondary font to the application (must +provide a call back). +* UseVCS. This is one by default and can be used to disable the use of +/dev/vcsa* devices. +* UseMDA. This is one by default and can be used to disable the use of the +monochrome display. +* PatchKeys. This is one by default and can be used to disable the keyboard +patching explained in 2. +* BrokenCursorShape. This is one by default and can be used to indicate we +are using a broken console where the cursor shape can't be changed. This +happends with some frame buffer consoles that fails to implement it. + + An example of configuration file is shown in 3.4. + Read the ConfigFile.txt for more information about configuration files. + diff --git a/tvision/doc/QNX.txt b/tvision/doc/QNX.txt new file mode 100644 index 0000000..5daf815 --- /dev/null +++ b/tvision/doc/QNX.txt @@ -0,0 +1,31 @@ +Driver: QNXRtP (QNX6) +Author: Mike Gorchak +Status: Just a few words +Revision: $Revision: 1.5 $ + +1. Display characters + + Almost all characters are displayed, except for one character with +code 0x1B - ESC (small left arrow) - instead of this character symbol +'-' is displayed. Problem with 0x1B code appears in pterm and in raw +console mode. + +2. Input characters + + Symbols with codes from 0x80 upto 0xFF are reserved for national +characters support, that's why these symbols are not decoded. Event +structure in this case contains these character codes in keyDown. +charScan.charCode and field keyDown.keyCode is zero. + +3. Mouse support + + Mouse support in pure console mode was added. To use mouse you +need to run devi-hirun manually (it's true for QNX with versions 6.1, +6.2, 6.2.1). Run '/usr/photon/bin/devi-hirun -Pr [mouse options]' , +for example 'devi-hirun -Pr ps2 mousedev' for the generic ps2 mouses. +[-P] will prevent to connect devi-hirun as input manager to the +photon, [-r] will start devi-hirun in resource manager mode. Check +the /dev/devi/ directory it must contain the mouse0 device, if it +exists, that's mean all is ok. + +// Mike Gorchak. diff --git a/tvision/doc/Streams.txt b/tvision/doc/Streams.txt new file mode 100644 index 0000000..69cc00e --- /dev/null +++ b/tvision/doc/Streams.txt @@ -0,0 +1,88 @@ +Topic: TV Streams +Author: Salvador E. Tropea +Status: Just random data +Revision: $Revision: 1.3 $ + +This is an incomplete and inaccurate collection of data about TV streams. +Use it carefuly. + +Classes hierarchy: + +Note: Arrows are from parent to child, sorry if that's confusing. + + +--------------------------- pstream ----------------------------+ + | | | + v v v +opstream ---------+ +--------- fpbase ---------+ +------------ ipstream + | | | | | | | + | v v v v v | + | ofpstream fpstream ifpstream | + | | + +------------------------> iopstream <---------------------------+ + +pstream: Holds a streambuf (protected bp, readable with rdbuf()). These +stream buffers acts like streams but storing data in a memory buffer. +It also keeps the list of registered objects. + +opstream: defines all the output operations. + +ipstream: defines all the input operations. + +iopstream: it just joins the facilities from opstream and ipstream. + +fpbase: Holds a filebuf (private and readable with rdbuf()). It just adds to +pstream what's needed to handle file buffers instead of stream buffers, like +open. +A very important detail is that a filebuf is a class derived from streambuf +and hence all streambuf operations are valid. In fact fpbase constructors +sets the bp value to the filebuf using init(). + +ofpstream: just makes all the output operations available for files. + +ifpstream: just makes all the input operations available for files. + +fpstream: defines a read/write open. + +---------------- + +Why all of this? + +This was designed to provide "persistence". The idea is to create *binary* +files that can hold objects. For this the library keeps a list of registered +objects, each one have a name and function to be called to read the object +from disk. + +---------------- + +What's used by each class from the standard C++ lib: + +pstream: +Basically nothing, it have a streambuf pointer but never uses it. +The code uses some some ios flags: +ios::eofbit, ios::failbit and ios::badbit + +opstream: (seek, flush, put a char and put various chars) +* CLY_PubSeekOff (seek) attributes: CLY_std(ios::beg), CLY_std(ios::cur) and +all of type CLY_IOSSeekDir. +* CLY_PubSync() (flush) +* sputc (put a char) +* sputn (put chars) +* CLY_std(ios::out) + +ipstream: (seek, flush, get a char and get various chars) +* CLY_PubSeekOff (seek) attributes: CLY_std(ios::beg), CLY_std(ios::cur) and +all of type CLY_IOSSeekDir. +* sbumpc (read a char) +* sgetn (read chars) +* CLY_std(ios::in) +* CLY_std(ios::eofbit) + +fpbase: (open, close, open from file h, set buffer and attach) +* Create a filebuf from a file handle. +* open (CLY_OpenModeT modes) +* CLY_PubSetBuf (set the buffer) +* is_open +* attach [optional] +* close + + diff --git a/tvision/doc/TVReference.html b/tvision/doc/TVReference.html new file mode 100644 index 0000000..7c34e87 --- /dev/null +++ b/tvision/doc/TVReference.html @@ -0,0 +1,3862 @@ + + +Turbo Vision reference + + +

Turbo Vision reference

+ +This document describes the functions of Turbo Vision that didn't +exist in the original version of the library.
+Note that only a few things are documented here, I need help to populate +this file. + +

+ +This document applies to version 2.0.0 +of the Turbo Vision library. + +

+ + +

+
  • Alphabetical list of functions +
  • List by classes +
  • List by modules +
  • List by files +
  • + + + +


    + +

    Alphabetical List

    + + +
  • Add (TVMainConfigFile) +
  • Add (TVMainConfigFile) <1> +
  • AddCodePage (TVCodePage) +
  • AddInt (TVConfigFile) +
  • AddString (TVConfigFile) +
  • CheckForLines (TVFontCollection) +
  • CheckSignature (TVFontCollection) +
  • CodePageOfID (TVCodePage) +
  • CreateCodePagesCol (TVCodePage) +
  • CreateCPFromUnicode (TVCodePage) +
  • CreateFont (TVFontCollection) +
  • CreateListOfFonts (TVFontCollection) +
  • CreateOnTheFlyInpRemap (TVCodePage) +
  • CreateOnTheFlyRemap (TVCodePage) +
  • CreateRemap (TVCodePage) +
  • defaultCheckForWindowSize (TDisplay) +
  • defaultClearScreen (TDisplay) +
  • defaultGetBlinkState (TDisplay) +
  • defaultGetCols (TDisplay) +
  • defaultGetCrtMode (TDisplay) +
  • defaultGetCursorShape (TDisplay) +
  • defaultGetRows (TDisplay) +
  • defaultGetWindowTitle (TDisplay) +
  • defaultSetCrtMode (TDisplay) +
  • defaultSetCrtModeExt (TDisplay) +
  • defaultSetCrtModeRes (TDisplay) +
  • defaultSetCursorShape (TDisplay) +
  • defaultSetWindowTitle (TDisplay) +
  • EnlargeOne (TVFontCollection) +
  • FillTables (TVCodePage) +
  • FillTEvent (TGKeyXTerm) +
  • freeItem (TVFontCollection) +
  • GetFont (TVFontCollection) +
  • GetKeyParsed (TGKeyXTerm) +
  • GetList (TVCodePage) +
  • GetRaw (TGKeyXTerm) +
  • GetShiftState (TGKeyXTerm) +
  • GetTranslate (TVCodePage) +
  • GetWindowTitle (TDisplayDOS) +
  • GKey (TGKeyXTerm) +
  • IDToIndex (TVCodePage) +
  • IndexToID (TVCodePage) +
  • InitOnce (TGKeyXTerm) +
  • InternalCodeForUnicode (TVCodePage) +
  • Load (TVConfigFile) +
  • Load (TVMainConfigFile) +
  • LookSimilarInRange (TVCodePage) +
  • moveBuf (TDrawBuffer) +
  • moveChar (TDrawBuffer) +
  • moveCStr (TDrawBuffer) +
  • moveStr (TDrawBuffer) +
  • Print (TVConfigFile) +
  • Print (TVMainConfigFile) +
  • ProcessEscape (TGKeyXTerm) +
  • ReadFontInfo (TVFontCollection) +
  • ReadName (TVFontCollection) +
  • ReadVersionNum (TVFontCollection) +
  • ReduceOne (TVFontCollection) +
  • RemapBufferGeneric (TVCodePage) +
  • RemapChar (TVCodePage) +
  • RemapNString (TVCodePage) +
  • RemapString (TVCodePage) +
  • RemapTVStrings (TVCodePage) +
  • Resume (TGKeyXTerm) +
  • Search (TVConfigFile) +
  • Search (TVMainConfigFile) +
  • Search (TVMainConfigFile) <1> +
  • Search (TVMainConfigFile) <2> +
  • Search (TVMainConfigFile) <3> +
  • searchDOSModeInfo (TDisplay) +
  • SetCallBack (TVCodePage) +
  • SetCodePage (TVCodePage) +
  • SetCodePage (TVFontCollection) +
  • SetCrtMode (TDisplayDOS) +
  • setCursorType (TDisplay) +
  • SetUserConfigFile (TVMainConfigFile) +
  • SetWindowTitle (TDisplayDOS) +
  • Suspend (TGKeyXTerm) +
  • testForSupport (TDisplayDOS) +
  • TScreen (TScreen) +
  • TVCodePage (TVCodePage) +
  • TVConfigFile (TVConfigFile) +
  • TVFontCollection (TVFontCollection) +
  • TVMainConfigFile (TVMainConfigFile) +
  • UnicodeForInternalCode (TVCodePage) +
  • ~TVCodePage (TVCodePage) +
  • ~TVConfigFile (TVConfigFile) +
  • ~TVMainConfigFile (TVMainConfigFile) +
  • + + + +


    + +

    Classes

    + + +
  • TDisplay +
  • TDisplayDOS +
  • TDrawBuffer +
  • TGKeyXTerm +
  • TScreen +
  • TVCodePage +
  • TVConfigFile +
  • TVFontCollection +
  • TVMainConfigFile +
  • + + +


    + +

    TDisplay

    + + + + +
  • defaultCheckForWindowSize (TDisplay) +
  • defaultClearScreen (TDisplay) +
  • defaultGetBlinkState (TDisplay) +
  • defaultGetCols (TDisplay) +
  • defaultGetCrtMode (TDisplay) +
  • defaultGetCursorShape (TDisplay) +
  • defaultGetRows (TDisplay) +
  • defaultGetWindowTitle (TDisplay) +
  • defaultSetCrtMode (TDisplay) +
  • defaultSetCrtModeExt (TDisplay) +
  • defaultSetCrtModeRes (TDisplay) +
  • defaultSetCursorShape (TDisplay) +
  • defaultSetWindowTitle (TDisplay) +
  • searchDOSModeInfo (TDisplay) +
  • setCursorType (TDisplay) +
  • + + + +


    + +

    TDisplayDOS

    + + + + +
  • GetWindowTitle (TDisplayDOS) +
  • SetCrtMode (TDisplayDOS) +
  • SetWindowTitle (TDisplayDOS) +
  • testForSupport (TDisplayDOS) +
  • + + + +


    + +

    TDrawBuffer

    + + + + +
  • moveBuf (TDrawBuffer) +
  • moveChar (TDrawBuffer) +
  • moveCStr (TDrawBuffer) +
  • moveStr (TDrawBuffer) +
  • + + + +


    + +

    TGKeyXTerm

    + + + + +
  • FillTEvent (TGKeyXTerm) +
  • GetKeyParsed (TGKeyXTerm) +
  • GetRaw (TGKeyXTerm) +
  • GetShiftState (TGKeyXTerm) +
  • GKey (TGKeyXTerm) +
  • InitOnce (TGKeyXTerm) +
  • ProcessEscape (TGKeyXTerm) +
  • Resume (TGKeyXTerm) +
  • Suspend (TGKeyXTerm) +
  • + + + +


    + +

    TScreen

    + + + + +
  • TScreen (TScreen) +
  • + + + +


    + +

    TVCodePage

    + + + + +
  • AddCodePage (TVCodePage) +
  • CodePageOfID (TVCodePage) +
  • CreateCodePagesCol (TVCodePage) +
  • CreateCPFromUnicode (TVCodePage) +
  • CreateOnTheFlyInpRemap (TVCodePage) +
  • CreateOnTheFlyRemap (TVCodePage) +
  • CreateRemap (TVCodePage) +
  • FillTables (TVCodePage) +
  • GetList (TVCodePage) +
  • GetTranslate (TVCodePage) +
  • IDToIndex (TVCodePage) +
  • IndexToID (TVCodePage) +
  • InternalCodeForUnicode (TVCodePage) +
  • LookSimilarInRange (TVCodePage) +
  • RemapBufferGeneric (TVCodePage) +
  • RemapChar (TVCodePage) +
  • RemapNString (TVCodePage) +
  • RemapString (TVCodePage) +
  • RemapTVStrings (TVCodePage) +
  • SetCallBack (TVCodePage) +
  • SetCodePage (TVCodePage) +
  • TVCodePage (TVCodePage) +
  • UnicodeForInternalCode (TVCodePage) +
  • ~TVCodePage (TVCodePage) +
  • + + + +


    + +

    TVConfigFile

    + + + + +
  • AddInt (TVConfigFile) +
  • AddString (TVConfigFile) +
  • Load (TVConfigFile) +
  • Print (TVConfigFile) +
  • Search (TVConfigFile) +
  • TVConfigFile (TVConfigFile) +
  • ~TVConfigFile (TVConfigFile) +
  • + + + +


    + +

    TVFontCollection

    + + + + +
  • CheckForLines (TVFontCollection) +
  • CheckSignature (TVFontCollection) +
  • CreateFont (TVFontCollection) +
  • CreateListOfFonts (TVFontCollection) +
  • EnlargeOne (TVFontCollection) +
  • freeItem (TVFontCollection) +
  • GetFont (TVFontCollection) +
  • ReadFontInfo (TVFontCollection) +
  • ReadName (TVFontCollection) +
  • ReadVersionNum (TVFontCollection) +
  • ReduceOne (TVFontCollection) +
  • SetCodePage (TVFontCollection) +
  • TVFontCollection (TVFontCollection) +
  • + + + +


    + +

    TVMainConfigFile

    + + + + +
  • Add (TVMainConfigFile) +
  • Add (TVMainConfigFile) <1> +
  • Load (TVMainConfigFile) +
  • Print (TVMainConfigFile) +
  • Search (TVMainConfigFile) +
  • Search (TVMainConfigFile) <1> +
  • Search (TVMainConfigFile) <2> +
  • Search (TVMainConfigFile) <3> +
  • SetUserConfigFile (TVMainConfigFile) +
  • TVMainConfigFile (TVMainConfigFile) +
  • ~TVMainConfigFile (TVMainConfigFile) +
  • + + + +


    + +

    Modules

    + + +
  • Code Page +
  • Config File +
  • Display +
  • DOS Display +
  • OS Clipboard +
  • Screen +
  • TVFontCollection +
  • + + +


    + +

    Code Page

    + +This module provides code page remapping needed to adapt the special +character to all the supported terminals. +

    + + It was originally designed for SETEdit and moved to Turbo Vision in 2002. +

    + + The internal encoding system maps the first 256 to CP 437. +

    + + Important: The Turbo Vision never had such a thing and this is completly +new code that affects a lot of TV components. +

    + + The mechanism used is similar to what Linux kernel uses, why? simple:
    +1) That's the most complex mechanism I found in all the targets so far.
    +2) This is quite crazy but at the same time flexible.
    + What's similar?
    + We have two maps. The first map is what Linux calls SFM (Screen Font Map). +It defines which internal codes are rendered by each font character (which +unicodes in Linux kernel). This is basically a map that describes the font. +This is the only map I had in the editor. The curScrCP variable holds the +ID of this map. +

    + + The second map is what the Linux kernel calls ACM (Application Charset +Map). This map describes how is the application data encoded, as an example: +how is encoded the text. It doesn't have to map one to one with the font, +and that's the complex stuff. For this reason this map is used to do an +"on-the-fly" remap before sending the characters to the screen. If this map +is identical to the SFM (maps 1 to 1 => what Linux calls trivial mapping) +we don't do the remap. The OnTheFlyRemapNeeded() and OnTheFlyRemap(uchar val) +are used for the remap. The curAppCP holds the ID of this map. +

    + + Is important to note that we don't do 8-bits -> ACM -> Unicode -> SFM -> +8-bits Screen like the Linux kernel does. We recode the application using +the ACM and if ACM!=SFM we use a simple table that makes: 8-bits -> 8-bits +Screen and if it isn't needed we just send the code to the screen. +

    + + I added a new code page to this: the input code page. In Linux systems +the input is supposed to be encoded in the ACM code page. In Windows systems +they can be different and they are asked with different calls. It can be +useful if you want to use an encoding different than the currently used by +the OS. You can change the screen encoding and load an appropriate font for +it, then you change the application code page and you can properly see +documents encoded in the target code page. But in order to edit them you +need to translate the codes that come from keyboard to the target code page. +That's a good use for the input code page. + +

    +
  • AddCodePage (TVCodePage) +
  • CodePageOfID (TVCodePage) +
  • CreateCodePagesCol (TVCodePage) +
  • CreateCPFromUnicode (TVCodePage) +
  • CreateOnTheFlyInpRemap (TVCodePage) +
  • CreateOnTheFlyRemap (TVCodePage) +
  • CreateRemap (TVCodePage) +
  • FillTables (TVCodePage) +
  • GetList (TVCodePage) +
  • GetTranslate (TVCodePage) +
  • IDToIndex (TVCodePage) +
  • IndexToID (TVCodePage) +
  • InternalCodeForUnicode (TVCodePage) +
  • LookSimilarInRange (TVCodePage) +
  • RemapBufferGeneric (TVCodePage) +
  • RemapChar (TVCodePage) +
  • RemapNString (TVCodePage) +
  • RemapString (TVCodePage) +
  • RemapTVStrings (TVCodePage) +
  • SetCallBack (TVCodePage) +
  • SetCodePage (TVCodePage) +
  • TVCodePage (TVCodePage) +
  • UnicodeForInternalCode (TVCodePage) +
  • ~TVCodePage (TVCodePage) +
  • + + + +


    + +

    Config File

    + +This module provides the TVConfigFile class. This class can load a +configuration file containing sections and variables. Each section have +a name which is indicated using brackets [Name]. As sections can be nested +and my text editor can indent using the braces as reference (also jump to +the start/end of a block and highlight the pair) the section's body must +be enclosed using braces. Sections can be nested conforming an structure +that resembles a file system. Inside a section you can define variables. A +variable name must be composed of a-zA-Z_0-9 characters. After the name, and +in the same line, an equal sign must be put. The value after the equal sign +can be a number (decimal, octal or hexadecimal as in C) or a string enclosed +using double quotes. You can use spaces around the equal sign and after the +value but you must finish a definition in one line. Comments are started +with a # symbol and ends at the end of the line. +

    + + The information from a configuration file is stored in memory as a tree. +You can search in the tree some key indicating it as a you indicate a path +and file name. Just think it as a particular file system, just use forward +slashes. + +

    +
  • Add (TVMainConfigFile) +
  • Add (TVMainConfigFile) <1> +
  • AddInt (TVConfigFile) +
  • AddString (TVConfigFile) +
  • Load (TVConfigFile) +
  • Load (TVMainConfigFile) +
  • Print (TVConfigFile) +
  • Print (TVMainConfigFile) +
  • Search (TVConfigFile) +
  • Search (TVMainConfigFile) +
  • Search (TVMainConfigFile) <1> +
  • Search (TVMainConfigFile) <2> +
  • Search (TVMainConfigFile) <3> +
  • SetUserConfigFile (TVMainConfigFile) +
  • TVConfigFile (TVConfigFile) +
  • TVMainConfigFile (TVMainConfigFile) +
  • ~TVConfigFile (TVConfigFile) +
  • ~TVMainConfigFile (TVMainConfigFile) +
  • + + + +


    + +

    Display

    + +This is the base class for low level screen output. + Most members are pointers to functions defined by each platform dependent +driver. Default members are provided. + This is a complete new file created from concepts that José Angel Sanchez +Caso provide me and coded from scratch. The names of some members are the +same used in original Turbo Vision for compatibility purposes. + + +
  • defaultCheckForWindowSize (TDisplay) +
  • defaultClearScreen (TDisplay) +
  • defaultGetBlinkState (TDisplay) +
  • defaultGetCols (TDisplay) +
  • defaultGetCrtMode (TDisplay) +
  • defaultGetCursorShape (TDisplay) +
  • defaultGetRows (TDisplay) +
  • defaultGetWindowTitle (TDisplay) +
  • defaultSetCrtMode (TDisplay) +
  • defaultSetCrtModeExt (TDisplay) +
  • defaultSetCrtModeRes (TDisplay) +
  • defaultSetCursorShape (TDisplay) +
  • defaultSetWindowTitle (TDisplay) +
  • searchDOSModeInfo (TDisplay) +
  • setCursorType (TDisplay) +
  • + + + +


    + +

    DOS Display

    + +This module implements the low level DOS screen access. +

    + + + Todo:
    + * The palette map could be changed during suspend. Currently not + suported. But is a really bizarre case and is restored if VGA state saving + is used. + +

    +
  • GetWindowTitle (TDisplayDOS) +
  • SetCrtMode (TDisplayDOS) +
  • SetWindowTitle (TDisplayDOS) +
  • testForSupport (TDisplayDOS) +
  • + + + +


    + +

    OS Clipboard

    + +OS independent clipboard system class. Uses to access the OS clipboard.
    + It was created to abstract the X11 and Windows clipboards. + + + + + + +


    + +

    Screen

    + +This is the base class for medium level screen output. + Most members are pointers to functions defined by each platform dependent +driver. Default members are provided. + This is a complete new file created from concepts that José Angel Sanchez +Caso provide me and coded from scratch. The names of some members are the +same used in original Turbo Vision for compatibility purposes. + + +
  • TScreen (TScreen) +
  • + + + +


    + +

    TVFontCollection

    + +This module handles collections of 8xN bitmaped fonts useful for text +consoles. The collection is created from a fonts files. Each item is a font +of certain height. The collection can return interpolated and extrapolated +fonts in a range of +/- one from the available fonts. The fonts file should +contain fonts with all the supported symbols. +

    + + +

    +  SFT Files: This is currently platform dependent! It means SFT files should
    +  be generated in the same platform they are used. It will be fixed in the
    +  future.
    +
    +  17 bytes: SET's editor font
    +   1 byte:  26 (DOS EOF)
    +      int:  version (1 or 2)
    +      int:  number of fonts contained.
    +   2 bytes: size of name
    +            the name, the length includes the EOS, but this isn't stored on
    +            disk.
    +
    +  Here are the fonts, each one have this format:
    +  version 1:
    +  int: first symbol defined.
    +  int: last symbol defined.
    +  unsigned: height of the font.
    +  The width is assumed to be 8 pixels (1 byte)
    +
    +  version 2, the same but adds:
    +  unsigned: width of the font.
    +
    +  The fonts itself follows the internal code.
    +
    + + +
  • CheckForLines (TVFontCollection) +
  • CheckSignature (TVFontCollection) +
  • CreateFont (TVFontCollection) +
  • CreateListOfFonts (TVFontCollection) +
  • EnlargeOne (TVFontCollection) +
  • freeItem (TVFontCollection) +
  • GetFont (TVFontCollection) +
  • ReadFontInfo (TVFontCollection) +
  • ReadName (TVFontCollection) +
  • ReadVersionNum (TVFontCollection) +
  • ReduceOne (TVFontCollection) +
  • SetCodePage (TVFontCollection) +
  • TVFontCollection (TVFontCollection) +
  • + + + +


    + +

    Files

    + + +
  • codepage.cc +
  • configfile.cc +
  • dosdis.cc +
  • fontcoll.cc +
  • tdisplay.cc +
  • tdrawbuf.cc +
  • tscreen.cc +
  • xtermkey.cc +
  • + + +


    + +

    codepage.cc

    + + + + +
  • AddCodePage (TVCodePage) +
  • CodePageOfID (TVCodePage) +
  • CreateCodePagesCol (TVCodePage) +
  • CreateCPFromUnicode (TVCodePage) +
  • CreateOnTheFlyInpRemap (TVCodePage) +
  • CreateOnTheFlyRemap (TVCodePage) +
  • CreateRemap (TVCodePage) +
  • FillTables (TVCodePage) +
  • GetList (TVCodePage) +
  • GetTranslate (TVCodePage) +
  • IDToIndex (TVCodePage) +
  • IndexToID (TVCodePage) +
  • InternalCodeForUnicode (TVCodePage) +
  • LookSimilarInRange (TVCodePage) +
  • RemapBufferGeneric (TVCodePage) +
  • RemapChar (TVCodePage) +
  • RemapNString (TVCodePage) +
  • RemapString (TVCodePage) +
  • RemapTVStrings (TVCodePage) +
  • SetCallBack (TVCodePage) +
  • SetCodePage (TVCodePage) +
  • TVCodePage (TVCodePage) +
  • UnicodeForInternalCode (TVCodePage) +
  • ~TVCodePage (TVCodePage) +
  • + + + +


    + +

    configfile.cc

    + + + + +
  • Add (TVMainConfigFile) +
  • Add (TVMainConfigFile) <1> +
  • AddInt (TVConfigFile) +
  • AddString (TVConfigFile) +
  • Load (TVConfigFile) +
  • Load (TVMainConfigFile) +
  • Print (TVConfigFile) +
  • Print (TVMainConfigFile) +
  • Search (TVConfigFile) +
  • Search (TVMainConfigFile) +
  • Search (TVMainConfigFile) <1> +
  • Search (TVMainConfigFile) <2> +
  • Search (TVMainConfigFile) <3> +
  • SetUserConfigFile (TVMainConfigFile) +
  • TVConfigFile (TVConfigFile) +
  • TVMainConfigFile (TVMainConfigFile) +
  • ~TVConfigFile (TVConfigFile) +
  • ~TVMainConfigFile (TVMainConfigFile) +
  • + + + +


    + +

    dosdis.cc

    + + + + +
  • GetWindowTitle (TDisplayDOS) +
  • SetCrtMode (TDisplayDOS) +
  • SetWindowTitle (TDisplayDOS) +
  • testForSupport (TDisplayDOS) +
  • + + + +


    + +

    fontcoll.cc

    + + + + +
  • CheckForLines (TVFontCollection) +
  • CheckSignature (TVFontCollection) +
  • CreateFont (TVFontCollection) +
  • CreateListOfFonts (TVFontCollection) +
  • EnlargeOne (TVFontCollection) +
  • freeItem (TVFontCollection) +
  • GetFont (TVFontCollection) +
  • ReadFontInfo (TVFontCollection) +
  • ReadName (TVFontCollection) +
  • ReadVersionNum (TVFontCollection) +
  • ReduceOne (TVFontCollection) +
  • SetCodePage (TVFontCollection) +
  • TVFontCollection (TVFontCollection) +
  • + + + +


    + +

    tdisplay.cc

    + + + + +
  • defaultCheckForWindowSize (TDisplay) +
  • defaultClearScreen (TDisplay) +
  • defaultGetBlinkState (TDisplay) +
  • defaultGetCols (TDisplay) +
  • defaultGetCrtMode (TDisplay) +
  • defaultGetCursorShape (TDisplay) +
  • defaultGetRows (TDisplay) +
  • defaultGetWindowTitle (TDisplay) +
  • defaultSetCrtMode (TDisplay) +
  • defaultSetCrtModeExt (TDisplay) +
  • defaultSetCrtModeRes (TDisplay) +
  • defaultSetCursorShape (TDisplay) +
  • defaultSetWindowTitle (TDisplay) +
  • searchDOSModeInfo (TDisplay) +
  • setCursorType (TDisplay) +
  • + + + +


    + +

    tdrawbuf.cc

    + + + + +
  • moveBuf (TDrawBuffer) +
  • moveChar (TDrawBuffer) +
  • moveCStr (TDrawBuffer) +
  • moveStr (TDrawBuffer) +
  • + + + +


    + +

    tscreen.cc

    + + + + +
  • TScreen (TScreen) +
  • + + + +


    + +

    xtermkey.cc

    + + + + +
  • FillTEvent (TGKeyXTerm) +
  • GetKeyParsed (TGKeyXTerm) +
  • GetRaw (TGKeyXTerm) +
  • GetShiftState (TGKeyXTerm) +
  • GKey (TGKeyXTerm) +
  • InitOnce (TGKeyXTerm) +
  • ProcessEscape (TGKeyXTerm) +
  • Resume (TGKeyXTerm) +
  • Suspend (TGKeyXTerm) +
  • + + + + + +


    + +
    CreateCodePagesCol (codepage.cc 1265)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::CreateCodePagesCol();
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Protected member used to create the list of known code pages stored in +CodePages. +

    + + + + +


    + +
    TVCodePage (codepage.cc 1332)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::TVCodePage(int idApp, int idScr, int idInp);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Initializes the code page system selecting the indicated code pages. This +is only used iternally. SetCodePage. +

    + + + + +


    + +
    CreateRemap (codepage.cc 1358)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::CreateRemap(int idSource, int idDest, uchar *table);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Protected member used to create a one to one table to convert from one +code page to another. Used to create the input to application and application +to screen on the fly convertion tables. +

    + + + + +


    + +
    CreateOnTheFlyRemap (codepage.cc 1416)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::CreateOnTheFlyRemap(int idApp, int idScr);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Protected member used to create the application to screen map when we have +to translate values on the fly. CreateRemap. +

    + + + + +


    + +
    CreateOnTheFlyInpRemap (codepage.cc 1444)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::CreateOnTheFlyInpRemap(int idInp, int idApp);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Protected member used to create the input to application map when we have +to translate values on the fly. CreateRemap. +

    + + + + +


    + +
    SetCodePage (codepage.cc 1467)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::SetCodePage(int idApp, int idScr, int idInp);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Selects the current code page used for toupper, tolower, etc. operations +and internal encodings, the code page used for the screen and the one used +for input. +

    + + If any of the arguments is -1 the current value is used. If the code pages +aren't the same the remap on the fly is enabled. The application code page +is used to remap the application, only if it changed. +

    + + + + +


    + +
    FillTables (codepage.cc 1497)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::FillTables(int id);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Protected member used to create the toupper, tolower and isalpha tables. +

    + + + + +


    + +
    ~TVCodePage (codepage.cc 1566)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::~TVCodePage();
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Deallocates memory used by TVCodePage. +

    + + + + +


    + +
    IDToIndex (codepage.cc 1582)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::IDToIndex(int id);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Converts a code page id into an index in the code page collection. +

    + + +Return Value

    + +The index of the code page with this id. If error the index for +PC 437 code page is returned. +

    + + + +


    + +
    IndexToID (codepage.cc 1606)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::IndexToID(ccIndex index);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Converts an index in the code page collection into a code page id. No +check of range is done. +

    + + +Return Value

    + +The code page id for the indicated index. +

    + + + +


    + +
    GetTranslate (codepage.cc 1626)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::GetTranslate(int id);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Used to get a map to translate code page symbols into internal symbols for +the indicated code page id. +

    + + +Return Value

    + +A pointer to a static buffer containing the translation values. Or +NULL if not initialized. The index 256 indicates 128 if only the upper 128 +values are really different from CP 437 or 256 if all the values are +different. In any case all the values are usable. +

    + + + +


    + +
    GetList (codepage.cc 1657)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::GetList(void);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Used to get a TStringCollection listing all the available code pages. +Useful to make the user choose one. This is a read-only value, don't modify +it. +

    + + +Return Value

    + +The internal collection casted to TStringCollection. +

    + + + +


    + +
    RemapChar (codepage.cc 1673)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::RemapChar(uchar c, ushort *map);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Remaps the desired character using the provided map. The original character +should be in CP437 encoding. GetTranslate. +

    + + +Return Value

    + +The remapped character. It can be a direct translation or the +closest found. +

    + + + +


    + +
    RemapString (codepage.cc 1703)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::RemapString(uchar *n, uchar *o, ushort *map);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Remaps the o string using the provided map and storing it in the +n string. The string should be terminated by a 0. RemapChar. +

    + + + + +


    + +
    RemapNString (codepage.cc 1719)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::RemapNString(uchar *n, uchar *o, ushort *map, int len);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Remaps the @var{o} string using the provided map and storing it in the +@var{n} string. The number of items to remap is indicated with @var{len}. +RemapChar. +

    + + + + +


    + +
    RemapBufferGeneric (codepage.cc 1734)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::RemapBufferGeneric(int sourID, int destID, uchar *buffer, unsigned len, unsigned ops);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Used to remap a buffer from any of the supported code pages into another. +The process doesn't have to be reversible. +

    + + Tabs, carriage returns, new lines and the null code aren't remapped. +

    + + + + +


    + +
    RemapTVStrings (codepage.cc 1815)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::RemapTVStrings(ushort *map);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Protected member used internally to remap all the TV stuff that isn't +ASCII. +

    + + + + +


    + +
    SetCallBack (codepage.cc 1873)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::SetCallBack(TVCodePageCallBack cb);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Sets the function to be called after changing the code page. This should +remap the special strings used by the application. +

    + + +Return Value

    + +The previous function. If it's != NULL you should call it. +

    + + + +


    + +
    CodePageOfID (codepage.cc 1889)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::CodePageOfID(int id);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Protected member used to find the code page structure for a provided id. +

    + + +Return Value

    + +A CodePage structure pointer. +

    + + + +


    + +
    UnicodeForInternalCode (codepage.cc 2567)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::UnicodeForInternalCode(uint16 value);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Finds which unicode is represented by the specified internal code. +Currently that's an slow search because isn't very. +

    + + +Return Value

    + +The first unicode found. +

    + + + +


    + +
    InternalCodeForUnicode (codepage.cc 2593)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::InternalCodeForUnicode(ushort unicode);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Finds which internal code can render an Unicode value. +

    + + +Return Value

    + +The internal or -1 if none can do it. +

    + + + +


    + +
    CreateCPFromUnicode (codepage.cc 2610)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::CreateCPFromUnicode(CodePage *cp, int id, const char *name, ushort *unicodes);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Creates a new code page from an arry containing the unicodes for each +symbol. Use an id over than 0x7FFF8000 to avoid collisions. This is used by +the Linux driver when the unicodes maps doesn't match with known cp. +

    + + + + +


    + +
    AddCodePage (codepage.cc 2649)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::AddCodePage(CodePage *cp);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +Adds a custom code page to the list. You can create a new one from an +array containing the Unicodes for each symbol. CreateCPFromUnicode. +

    + + +Return Value

    + +The index of the new code page in the collection. +

    + + + +


    + +
    LookSimilarInRange (codepage.cc 2668)
    + +Syntax

    + + +

    + #define Uses_TVCodePage
    + #include <tv.h>
    + 
    +
    + + +
    + TVCodePage::LookSimilarInRange(int code, int last);
    +
    + + +Member of the class: +TVCodePage +

    + + + +Description

    + +This is a helper for the TVFontCollection class the parameters of this +function could change in the future.
    + Basically it finds a replacement for a missing symbol in a font. It allows +using incomplete font. +

    + + +Return Value

    + +The replacement or -1 if none known. +

    + + + +


    + +
    TVConfigFile (configfile.cc 66)
    + +Syntax

    + + +

    + #define Uses_TVConfigFile
    + #include <tv.h>
    + 
    +
    + + +
    + TVConfigFile::TVConfigFile();
    +
    + + +Member of the class: +TVConfigFile +

    + + + +Description

    + +Initializes the class and reads the contents of the specified file to a +tree in memory. +

    + + + + +


    + +
    Search (configfile.cc 86)
    + +Syntax

    + + +

    + #define Uses_TVConfigFile
    + #include <tv.h>
    + 
    +
    + + +
    + TVConfigFile::Search(const char *key, char *&p, long &n);
    +
    + + +Member of the class: +TVConfigFile +

    + + + +Description

    + +Searchs for the indicated key in the tree. Separate nested sections using +forward slashes. +

    + + +Return Value

    + +not 0 if the key was found, the return value is in p if +the key is an string. Otherwise p is NULL and the value is in +n. +

    + + + +


    + +
    AddInt (configfile.cc 530)
    + +Syntax

    + + +

    + #define Uses_TVConfigFile
    + #include <tv.h>
    + 
    +
    + + +
    + TVConfigFile::AddInt(const char *key, const char *name, long value, int priority);
    +
    + + +Member of the class: +TVConfigFile +

    + + + +Description

    + +Adds a new variable to the tree. The type of the variable is integer. The +name variable is added to the section indicated by key. +Possible priority values are justHint (25), fromFile (50) or fromApplication +(75). It is used to determine if a current value should be replaced by the +new value. The name is copied. +

    + + +Return Value

    + +!=0 if the variable was added. +

    + + +Example

    + +TVConfigFile::AddInt("TV/X11","ScreenWidth",90, +TVConfigFile::fromFile) +

    + + +


    + +
    AddString (configfile.cc 562)
    + +Syntax

    + + +

    + #define Uses_TVConfigFile
    + #include <tv.h>
    + 
    +
    + + +
    + TVConfigFile::AddString(const char *key, const char *name, const char *value, int priority);
    +
    + + +Member of the class: +TVConfigFile +

    + + + +Description

    + +Adds a new variable to the tree. The type of the variable is string. The +name variable is added to the section indicated by key. +Possible priority values are justHint (25), fromFile (50) or fromApplication +(75). It is used to determine if a current value should be replaced by the +new value. The name and the content are copied. +

    + + +Return Value

    + +!=0 if the variable was added. +

    + + +Example

    + +TVConfigFile::AddInt("TV/X11","ExtProgVideoMode","A_Program", +TVConfigFile::fromFile) +

    + + +


    + +
    Print (configfile.cc 651)
    + +Syntax

    + + +

    + #define Uses_TVConfigFile
    + #include <tv.h>
    + 
    +
    + + +
    + TVConfigFile::Print(FILE *f);
    +
    + + +Member of the class: +TVConfigFile +

    + + + +Description

    + +Prints the current tree to the specified file. It's main purpose is to +debug programs, but you can use it to generate valid configuration files +from data found in memory. +

    + + + + +


    + +
    ~TVConfigFile (configfile.cc 665)
    + +Syntax

    + + +

    + #define Uses_TVConfigFile
    + #include <tv.h>
    + 
    +
    + + +
    + ~TVConfigFile();
    +
    + + +Member of the class: +TVConfigFile +

    + + + +Description

    + +This is the destructor and just releases the tree that contains the +variables. +

    + + + + +


    + +
    Load (configfile.cc 672)
    + +Syntax

    + + +

    + #define Uses_TVConfigFile
    + #include <tv.h>
    + 
    +
    + + +
    + int Load(const char *file);
    +
    + + +Member of the class: +TVConfigFile +

    + + + +Description

    + +Reads the specified configuration file. +

    + + +Return Value

    + +The read status, 0 means no error. The Errors data member +contains descriptions for the errors. +

    + + + +


    + +
    TVMainConfigFile (configfile.cc 694)
    + +Syntax

    + + +

    + #define Uses_TVConfigFile
    + #include <tv.h>
    + 
    +
    + + +
    + TVMainConfigFile::TVMainConfigFile();
    +
    + + +Member of the class: +TVMainConfigFile +

    + + + +Description

    + +This is the constructor for TVMainConfigFile. This class is a special case +of TVConfigFile used for the Turbo Vision configuration file. Note you can +store application specific information in the configuration file using a +section different than TV. +

    + + + + +


    + +
    Load (configfile.cc 713)
    + +Syntax

    + + +

    + #define Uses_TVConfigFile
    + #include <tv.h>
    + 
    +
    + + +
    + TVMainConfigFile::Load();
    +
    + + +Member of the class: +TVMainConfigFile +

    + + + +Description

    + +Loads the configuration file. First we try using the application provided +name, then we search in the current directory, the path indicated by the +HOME environment variable, the path indicated by the HOMEDIR environment +variable, /etc and /dev/env/DJDIR/etc (%DJDIR%/etc). The default name for +the file is tvrc, if the OS uses a point in the name to make it a hidden file +the library also tries with .tvrc. +

    + + +Return Value

    + +The error status. 0 is OK. +

    + + + +


    + +
    ~TVMainConfigFile (configfile.cc 764)
    + +Syntax

    + + +

    + #define Uses_TVConfigFile
    + #include <tv.h>
    + 
    +
    + + +
    + TVMainConfigFile::~TVMainConfigFile();
    +
    + + +Member of the class: +TVMainConfigFile +

    + + + +Description

    + +Destroys the global TVConfigFile that contains the configuration. +

    + + + + +


    + +
    Search (configfile.cc 802)
    + +Syntax

    + + +

    + #define Uses_TVConfigFile
    + #include <tv.h>
    + 
    +
    + + +
    + TVMainConfigFile::Search(const char *key, long &val);
    +
    + + +Member of the class: +TVMainConfigFile +

    + + + +Description

    + +Looks for the specified key in the TV section. If found the result is +stored in val, but only if that's an integer. +

    + + +Return Value

    + +True if the key exists, even when that's an string. +

    + + + +


    + +
    Search (configfile.cc 823)
    + +Syntax

    + + +

    + #define Uses_TVConfigFile
    + #include <tv.h>
    + 
    +
    + + +
    + TVMainConfigFile::Search(const char *section, const char *variable, long &val);
    +
    + + +Member of the class: +TVMainConfigFile +

    + + + +Description

    + +Looks for the specified @var{variable} in the TV section using the +specified @var{section} as subsection. If found the result is +stored in val, but only if that's an integer. +

    + + +Return Value

    + +True if the key exists, even when that's an string. +

    + + + +


    + +
    Search (configfile.cc 845)
    + +Syntax

    + + +

    + #define Uses_TVConfigFile
    + #include <tv.h>
    + 
    +
    + + +
    + TVMainConfigFile::Search(const char *key);
    +
    + + +Member of the class: +TVMainConfigFile +

    + + + +Description

    + +Looks for the specified key in the TV section. If found the result is +returned but only if that's a string. +

    + + +Return Value

    + +The string or NULL. +

    + + + +


    + +
    Search (configfile.cc 867)
    + +Syntax

    + + +

    + #define Uses_TVConfigFile
    + #include <tv.h>
    + 
    +
    + + +
    + TVMainConfigFile::Search(const char *section, const char *variable);
    +
    + + +Member of the class: +TVMainConfigFile +

    + + + +Description

    + +Looks for the specified @var{variable} in the TV section using the +specified @var{section} as subsection. If found the result is returned but +only if that's a string. +

    + + +Return Value

    + +The string or NULL. +

    + + + +


    + +
    Add (configfile.cc 891)
    + +Syntax

    + + +

    + #define Uses_TVConfigFile
    + #include <tv.h>
    + 
    +
    + + +
    + TVMainConfigFile::Add(const char *section, const char *name, long value);
    +
    + + +Member of the class: +TVMainConfigFile +

    + + + +Description

    + +Adds a new variable of integer type to the TV subtree in the specified +section and using the specified name. The priority for this +variable is TVConfigFile::fromApplication. AddInt. +

    + + +Return Value

    + +!=0 if added. +

    + + + +


    + +
    Add (configfile.cc 916)
    + +Syntax

    + + +

    + #define Uses_TVConfigFile
    + #include <tv.h>
    + 
    +
    + + +
    + TVMainConfigFile::Add(const char *section, const char *name, const char *value);
    +
    + + +Member of the class: +TVMainConfigFile +

    + + + +Description

    + +Adds a new variable of string type to the TV subtree in the specified +section and using the specified name. The priority for this +variable is TVConfigFile::fromApplication. The string is copied. +AddInt. +

    + + +Return Value

    + +!=0 if added. +

    + + + +


    + +
    Print (configfile.cc 941)
    + +Syntax

    + + +

    + #define Uses_TVConfigFile
    + #include <tv.h>
    + 
    +
    + + +
    + void TVMainConfigFile::Print(FILE *f);
    +
    + + +Member of the class: +TVMainConfigFile +

    + + + +Description

    + +Prints the current tree to the specified file. It's main purpose is to +debug programs, but you can use it to generate valid configuration files +from data found in memory. +

    + + + + +


    + +
    SetUserConfigFile (configfile.cc 949)
    + +Syntax

    + + +

    + #define Uses_TVConfigFile
    + #include <tv.h>
    + 
    +
    + + +
    + void TVMainConfigFile::SetUserConfigFile(const char *name);
    +
    + + +Member of the class: +TVMainConfigFile +

    + + + +Description

    + +Specifies a name and path for the configuration file. Use it +if your application needs special settings different than the rest of the +TV applications. +

    + + + + +


    + +
    testForSupport (dosdis.cc 506)
    + +Syntax

    + + + +

    + TDisplayDOS::testForSupport();
    +
    + + +Member of the class: +TDisplayDOS +

    + + + +Description

    + +Used to test if a mode that we don't know can be handled by the driver +or not. If the mode uses an unknown memory region we just assume that's +a graphics mode and revert to 80x25. It could be enhanced a lot specially to +support VESA video modes when implemented in a way that the video memory +isn't located at the usual address. +

    + + + + +


    + +
    SetCrtMode (dosdis.cc 549)
    + +Syntax

    + + + +

    + TDisplayDOS::SetCrtMode(ushort mode);
    +
    + + +Member of the class: +TDisplayDOS +

    + + + +Description

    + +Sets a video mode from the video mode number. Video modes with the low +nibble equal 3 are used to encode extended and tweacked video modes. Note +that VESA 800x600x256 mode is 0x103 and here it is assumed to be extended +mode 1, that's 80x28. Also note that regular VGA 80x25 mode is the +"extended mode 0".
    + Any other value is assumed to be a user provided video mode and is +accepted only if we are sure that's really text mode and we know how to +handle it. +

    + + + + +


    + +
    GetWindowTitle (dosdis.cc 633)
    + +Syntax

    + + + +

    + TDisplayDOS::GetWindowTitle(void);
    +
    + + +Member of the class: +TDisplayDOS +

    + + + +Description

    + +Finds the main window title if we are running under W95 and windowed. +

    + + +Return Value

    + +A pointer to a newly allocated string (new[]). Or 0 if fail. by SET. +

    + + + +


    + +
    SetWindowTitle (dosdis.cc 673)
    + +Syntax

    + + + +

    + TDisplayDOS::SetWindowTitle(const char *name);
    +
    + + +Member of the class: +TDisplayDOS +

    + + + +Description

    + +Sets the main window title if we are running under W95 and windowed. +

    + + +Return Value

    + +1 successful. by SET. +

    + + + +


    + +
    freeItem (fontcoll.cc 74)
    + +Syntax

    + + + +

    + TVFontCollection::freeItem(void *item);
    +
    + + +Member of the class: +TVFontCollection +

    + + + +Description

    + +A specialized free to free the memory used by the font structure. +

    + + + + +


    + +
    CheckForLines (fontcoll.cc 93)
    + +Syntax

    + + + +

    + TVFontCollection::CheckForLines(void *item, void *arg);
    +
    + + +Member of the class: +TVFontCollection +

    + + + +Description

    + +Internally used during searchs to look for a font that matchs a specified +size. +

    + + + + +


    + +
    ReduceOne (fontcoll.cc 111)
    + +Syntax

    + + + +

    + TVFontCollection::ReduceOne(uchar *dest, uchar *ori, int height, int wBytes, int num);
    +
    + + +Member of the class: +TVFontCollection +

    + + + +Description

    + +Creates a font of the specified height from another of the same height +plus one. The destination buffer should be large enough (num*height bytes). +Special care is taked for letters. +

    + + + + +


    + +
    EnlargeOne (fontcoll.cc 144)
    + +Syntax

    + + + +

    + TVFontCollection::EnlargeOne(uchar *dest, uchar *ori, int height, int wBytes, int num);
    +
    + + +Member of the class: +TVFontCollection +

    + + + +Description

    + +Creates a font of the specified height from another of the same height +minus one. The destination buffer should be large enough (num*height bytes). +The last line is filled with 0. +

    + + + + +


    + +
    GetFont (fontcoll.cc 174)
    + +Syntax

    + + + +

    + TVFontCollection::GetFont(int width, int height);
    +
    + + +Member of the class: +TVFontCollection +

    + + + +Description

    + + +

    + + +Return Value

    + +NULL if the font isn't available. +

    + + + +


    + +
    CheckSignature (fontcoll.cc 218)
    + +Syntax

    + + + +

    + TVFontCollection::CheckSignature(FILE *f);
    +
    + + +Member of the class: +TVFontCollection +

    + + + +Description

    + +Internally used to check if we opened a fonts file. +

    + + + + +


    + +
    ReadName (fontcoll.cc 233)
    + +Syntax

    + + + +

    + TVFontCollection::ReadName(FILE *f);
    +
    + + +Member of the class: +TVFontCollection +

    + + + +Description

    + +Internally used to get the font's name. +

    + + + + +


    + +
    ReadVersionNum (fontcoll.cc 268)
    + +Syntax

    + + + +

    + TVFontCollection::ReadVersionNum(FILE *f, int *version, int *numfonts);
    +
    + + +Member of the class: +TVFontCollection +

    + + + +Description

    + +Internally used to read the version and number of fonts in the file. +

    + + + + +


    + +
    ReadFontInfo (fontcoll.cc 288)
    + +Syntax

    + + + +

    + TVFontCollection::ReadFontInfo(FILE *f, int version, TVBitmapFont *p);
    +
    + + +Member of the class: +TVFontCollection +

    + + + +Description

    + +Internally used to read the information about a font contained in an SFT +file. +

    + + +Return Value

    + +Size of the data font. +

    + + + +


    + +
    CreateFont (fontcoll.cc 315)
    + +Syntax

    + + + +

    + TVFontCollection::CreateFont(void *item, void *arg);
    +
    + + +Member of the class: +TVFontCollection +

    + + + +Description

    + +Internally used to create a font for a desired code page. +

    + + + + +


    + +
    SetCodePage (fontcoll.cc 360)
    + +Syntax

    + + + +

    + TVFontCollection::SetCodePage(int id);
    +
    + + +Member of the class: +TVFontCollection +

    + + + +Description

    + +Sets the encoding of the fonts returned by GetFont. +

    + + + + +


    + +
    TVFontCollection (fontcoll.cc 382)
    + +Syntax

    + + + +

    + TVFontCollection::TVFontCollection(const char *file, int cp);
    +
    + + +Member of the class: +TVFontCollection +

    + + + +Description

    + +Creates a font collection from the specified file and using the specified +code page. You must check the error status with GetError before using the +collection. +

    + + + + +


    + +
    CreateListOfFonts (fontcoll.cc 449)
    + +Syntax

    + + + +

    + TVFontCollection::CreateListOfFonts(const char *dir, unsigned wmin, unsigned wmax, unsigned hmin, unsigned hmax);
    +
    + + +Member of the class: +TVFontCollection +

    + + + +Description

    + +Constructs a string collection of fonts files that provides shapes inside +the specified range. The fonts are searched in the specified directory. If +you specify NULL as directory then the search is done in the current +directory. Each element in the collection is a string that contains two +ASCIIZ strings. The first is the fantasy name of the font and the second is +the name of the file containing it. It is useful to display the name in +a TSortedListBox and easilly locate which file contains it using strlen.
    + This is an static member. +

    + + +Return Value

    + +The collection of available fonts or NULL if none. +

    + + + +


    + +
    defaultGetCols (tdisplay.cc 139)
    + +Syntax

    + + +

    + #define Uses_TDisplay
    + #include <tv.h>
    + 
    +
    + + +
    + TDisplay::defaultGetCols();
    +
    + + +Member of the class: +TDisplay +

    + + + +Description

    + +Number of columns of the physical screen. +

    + + + + +


    + +
    defaultGetRows (tdisplay.cc 148)
    + +Syntax

    + + +

    + #define Uses_TDisplay
    + #include <tv.h>
    + 
    +
    + + +
    + TDisplay::defaultGetRows();
    +
    + + +Member of the class: +TDisplay +

    + + + +Description

    + +Number of rows of the physical screen. +

    + + + + +


    + +
    defaultClearScreen (tdisplay.cc 157)
    + +Syntax

    + + +

    + #define Uses_TDisplay
    + #include <tv.h>
    + 
    +
    + + +
    + TDisplay::defaultClearScreen(uchar, uchar);
    +
    + + +Member of the class: +TDisplay +

    + + + +Description

    + +Erase the screen using this width and height. +

    + + + + +


    + +
    defaultSetCursorShape (tdisplay.cc 165)
    + +Syntax

    + + +

    + #define Uses_TDisplay
    + #include <tv.h>
    + 
    +
    + + +
    + TDisplay::defaultSetCursorShape(unsigned, unsigned);
    +
    + + +Member of the class: +TDisplay +

    + + + +Description

    + +Sets the cursor shape, values in percent. +

    + + + + +


    + +
    defaultGetCursorShape (tdisplay.cc 173)
    + +Syntax

    + + +

    + #define Uses_TDisplay
    + #include <tv.h>
    + 
    +
    + + +
    + TDisplay::defaultGetCursorShape(unsigned &start, unsigned &end);
    +
    + + +Member of the class: +TDisplay +

    + + + +Description

    + +Gets the cursor shape, values in percent. +

    + + + + +


    + +
    searchDOSModeInfo (tdisplay.cc 184)
    + +Syntax

    + + +

    + #define Uses_TDisplay
    + #include <tv.h>
    + 
    +
    + + +
    + TDisplay::searchDOSModeInfo(ushort mode, unsigned &w, unsigned &h, int &fW, int &fH);
    +
    + + +Member of the class: +TDisplay +

    + + + +Description

    + + +

    + + +Return Value

    + +True if the mode is known. +

    + + + +


    + +
    defaultSetCrtMode (tdisplay.cc 204)
    + +Syntax

    + + +

    + #define Uses_TDisplay
    + #include <tv.h>
    + 
    +
    + + +
    + TDisplay::defaultSetCrtMode(ushort mode);
    +
    + + +Member of the class: +TDisplay +

    + + + +Description

    + +Sets the video mode. +

    + + + + +


    + +
    defaultSetCrtModeExt (tdisplay.cc 218)
    + +Syntax

    + + +

    + #define Uses_TDisplay
    + #include <tv.h>
    + 
    +
    + + +
    + TDisplay::defaultSetCrtModeExt(char *command);
    +
    + + +Member of the class: +TDisplay +

    + + + +Description

    + +Sets the video mode using a string. It could be an external +program or other information that doesn't fit in an ushort. +

    + + + + +


    + +
    defaultSetCrtModeRes (tdisplay.cc 231)
    + +Syntax

    + + +

    + #define Uses_TDisplay
    + #include <tv.h>
    + 
    +
    + + +
    + TDisplay::defaultSetCrtModeRes(unsigned, unsigned, int, int);
    +
    + + +Member of the class: +TDisplay +

    + + + +Description

    + +Selects the mode that's closest to the sepcified width and +height. The optional font size can be specified. +

    + + +Return Value

    + +0 no change done, 1 change done with all the requested parameters, +2 change done but just to get closer. +

    + + + +


    + +
    defaultGetCrtMode (tdisplay.cc 241)
    + +Syntax

    + + +

    + #define Uses_TDisplay
    + #include <tv.h>
    + 
    +
    + + +
    + TDisplay::defaultGetCrtMode();
    +
    + + +Member of the class: +TDisplay +

    + + + +Description

    + +Returns current video mode. +

    + + + + +


    + +
    defaultCheckForWindowSize (tdisplay.cc 251)
    + +Syntax

    + + +

    + #define Uses_TDisplay
    + #include <tv.h>
    + 
    +
    + + +
    + TDisplay::defaultCheckForWindowSize(void);
    +
    + + +Member of the class: +TDisplay +

    + + + +Description

    + +Returns !=0 if the screen size changed externally. Usually +when we are in a window, but isn't the only case. +

    + + + + +


    + +
    defaultGetWindowTitle (tdisplay.cc 261)
    + +Syntax

    + + +

    + #define Uses_TDisplay
    + #include <tv.h>
    + 
    +
    + + +
    + TDisplay::defaultGetWindowTitle(void);
    +
    + + +Member of the class: +TDisplay +

    + + + +Description

    + +Gets the visible title of the screen, usually the window +title. +

    + + + + +


    + +
    defaultSetWindowTitle (tdisplay.cc 272)
    + +Syntax

    + + +

    + #define Uses_TDisplay
    + #include <tv.h>
    + 
    +
    + + +
    + TDisplay::defaultSetWindowTitle(const char *);
    +
    + + +Member of the class: +TDisplay +

    + + + +Description

    + +Sets the visible title of the screen, usually the window +title. +

    + + +Return Value

    + +!=0 success. +

    + + + +


    + +
    defaultGetBlinkState (tdisplay.cc 282)
    + +Syntax

    + + +

    + #define Uses_TDisplay
    + #include <tv.h>
    + 
    +
    + + +
    + TDisplay::defaultGetBlinkState();
    +
    + + +Member of the class: +TDisplay +

    + + + +Description

    + +Finds if the MSB of the attribute is for blinking. +

    + + +Return Value

    + +0 no, 1 yes, 2 no but is used for other thing. +

    + + + +


    + +
    setCursorType (tdisplay.cc 326)
    + +Syntax

    + + +

    + #define Uses_TDisplay
    + #include <tv.h>
    + 
    +
    + + +
    + TDisplay::setCursorType(ushort val);
    +
    + + +Member of the class: +TDisplay +

    + + + +Description

    + +Sets the cursor shape. I take the TV 2.0 convention: the low 8 bits is +the start and the high 8 bits the end. Values can be between 0 and 99. To +disable the cursor a value of 0 is used. +

    + + + + +


    + +
    moveBuf (tdrawbuf.cc 22)
    + +Syntax

    + + + +

    + TDrawBuffer::moveBuf(unsigned indent, const void *source, unsigned attr, unsigned count);
    +
    + + +Member of the class: +TDrawBuffer +

    + + + +Description

    + +Copies count bytes from source to the data buffer starting at indent. The +function uses the provided attribute, but if the attribute is 0 the attribute +in the buffer is unmodified. +

    + + Added a check to avoid writings passing the end of the buffer. +

    + +

    + + + + +


    + +
    moveChar (tdrawbuf.cc 60)
    + +Syntax

    + + + +

    + TDrawBuffer::moveChar(unsigned indent, char c, unsigned attr, unsigned count);
    +
    + + +Member of the class: +TDrawBuffer +

    + + + +Description

    + +Fills count bytes in the buffer starting at the indent position. If the +attribute is 0 the original is left unchanged. If the character is 0 only +the attribute is used. +

    + + Added a check to avoid writings passing the end of the buffer. +

    + +

    + + + + +


    + +
    moveCStr (tdrawbuf.cc 110)
    + +Syntax

    + + + +

    + TDrawBuffer::moveCStr(unsigned indent, const char *str, unsigned attrs);
    +
    + + +Member of the class: +TDrawBuffer +

    + + + +Description

    + +That's the same as moveStr but the attrs parameter holds two attributes +the lower 8 bits are the normal value and the upper 8 bits define the +attribute to be used for text enclosed by ASCII 126. moveStr. +

    + + The routine was modified to avoid writes passing the end of the buffer. +Additionally was re-writed in assembler (I guess the Borland's original code +was assembler, but I didn't take a look to it) because the check slow downs +the routine so I wanted to avoid a lose in performance. SET. +

    + + + + +


    + +
    moveStr (tdrawbuf.cc 207)
    + +Syntax

    + + + +

    + TDrawBuffer::moveStr(unsigned indent, const char *str, unsigned attr);
    +
    + + +Member of the class: +TDrawBuffer +

    + + + +Description

    + +Writes a string in the buffer with the provided attribute. The routine +copies until the EOS is found or the buffer is filled. +

    + + Modified to avoid writes passing the end of the buffer. Optimized for +32 bits. Translated to asm just for fun, I think is a little bit faster. +SET. +

    + + + + +


    + +
    TScreen (tscreen.cc 247)
    + +Syntax

    + + +

    + #define Uses_TScreen
    + #include <tv.h>
    + 
    +
    + + +
    + TScreen::TScreen();
    +
    + + +Member of the class: +TScreen +

    + + + +Description

    + +This constructor is called when the TApplication object is created. The +TProgramInit constructor creates a dynamic copy instance of a TScreen +object.
    + Actually it calls the detection routines to determine the best driver +available. If non is found prints and error to the stderr output and aborts +the execution. +

    + + + + +


    + +
    InitOnce (xtermkey.cc 72)
    + +Syntax

    + + + +

    + TGKeyXTerm::InitOnce();
    +
    + + +Member of the class: +TGKeyXTerm +

    + + + +Description

    + +Does initialization tasks performed only once. +

    + + +Return Value

    + +0 if success, !=0 if an error ocurred. In the last case the error member +points to a descriptive error. +

    + + + +


    + +
    Suspend (xtermkey.cc 138)
    + +Syntax

    + + + +

    + TGKeyXTerm::Suspend();
    +
    + + +Member of the class: +TGKeyXTerm +

    + + + +Description

    + +Restore the original console state. +

    + + + + +


    + +
    Resume (xtermkey.cc 152)
    + +Syntax

    + + + +

    + TGKeyXTerm::Resume();
    +
    + + +Member of the class: +TGKeyXTerm +

    + + + +Description

    + +Memorize current console state and setup the one needed for us. +

    + + + + +


    + +
    ProcessEscape (xtermkey.cc 611)
    + +Syntax

    + + + +

    + TGKeyXTerm::ProcessEscape();
    +
    + + +Member of the class: +TGKeyXTerm +

    + + + +Description

    + +Parse a escape sequence. +

    + + +Return Value

    + +: 1 if the sequence found, 0 if not and the keys are stored in the +buffer. +

    + + + +


    + +
    GetKeyParsed (xtermkey.cc 677)
    + +Syntax

    + + + +

    + TGKeyXTerm::GetKeyParsed();
    +
    + + +Member of the class: +TGKeyXTerm +

    + + + +Description

    + +Gets a key from the buffer, waiting value or fIn and if needed calls +the escape sequence parser. +

    + + + + +


    + +
    GetRaw (xtermkey.cc 717)
    + +Syntax

    + + + +

    + TGKeyXTerm::GetRaw();
    +
    + + +Member of the class: +TGKeyXTerm +

    + + + +Description

    + +Gets the next key, their modifiers and ASCII. Is a postprocessor for +GetKeyParsed. +

    + + + + +


    + +
    GKey (xtermkey.cc 750)
    + +Syntax

    + + + +

    + TGKeyXTerm::GKey();
    +
    + + +Member of the class: +TGKeyXTerm +

    + + + +Description

    + +Gets a key from the input and converts it into the TV format. +

    + + + + +


    + +
    GetShiftState (xtermkey.cc 783)
    + +Syntax

    + + + +

    + TGKeyXTerm::GetShiftState();
    +
    + + +Member of the class: +TGKeyXTerm +

    + + + +Description

    + +Finds the value of the modifiers in TV format. +

    + + + + +


    + +
    FillTEvent (xtermkey.cc 809)
    + +Syntax

    + + + +

    + TGKeyXTerm::FillTEvent(TEvent &e);
    +
    + + +Member of the class: +TGKeyXTerm +

    + + + +Description

    + +Fills the TV event structure for a key. +

    + + + + + + + + diff --git a/tvision/doc/Win32.txt b/tvision/doc/Win32.txt new file mode 100644 index 0000000..5aef910 --- /dev/null +++ b/tvision/doc/Win32.txt @@ -0,0 +1,103 @@ +Driver: Win32 and WinNT +Author: Vadim Beloborodov, Anatoli Soltan, Salvador E. Tropea +Status: Complete +$Revision: 1.1 $ + + This file documents details specific to the Win32 and WinNT drivers. Both +drivers can be used for Win32 systems, this means the WinNT driver is also ok +for Windows 95. When we say "Win32" we refer to the 32 bits versions of +Windows. The first Win32 version of Windows released to the market was +Windows 95. You can divide Win32 platforms in two big groups: The Windows 95 +and other Win32 versions that runs on top of DOS, they are Windows 95, 98 and +Me (Millenium). And the Windows NT and others that doesn't run on top of DOS, +they are Windows NT, 2000 and XP. These are the names upto year 2002, newer +releases are supposed to be all in the Windows NT family. + +1. INTRODUCTION +2. FEATURES +3. IMPORTANT DETAILS +4. CONFIGURATION VARIABLES + + +1. INTRODUCTION + + Currently you'll find two different drivers, they are quite similar and +will converge in the future. Currently the differences are really small +because I (SET) recoded both drivers and added a lot of important things. In +the process I made them more similar. + The differences are: + +Win32: It uses a separated thread to read the input events, all the keyboard + and mouse events are stored in a queue. The screen update is simpler + but slower. +WinNT: Uses only one execution thread, events are polled and the queue is + maintained by the OS. The screen is updated using a buffer to assemble + the text and then it's sent in one call. It seems to be faster. + + Which driver have more priority depends on the compiler you used to create +the application. If Borland compiler was used the WinNT driver will have more +priority and if MinGW/Cygwin was used Win32 will have more priority. This is +just because Vadim contributed the first Win32 code that compiled only with +MinGW and Anatoli contributed the first WinNT driver that compiled only with +Borland C++ compiler and only worked for Windows NT family. With the time +they became more and more similar. + You can change which driver is used using a configuration file. + These are a simple drivers that uses the Win32 console API. That's the set +of services offered by Win32 OS to use text mode. I must admit the API is +well documented and quite clean. Lamentably is not hard to hit bugs and +stupid limitations that you can do nothing to overcome. + + +2. FEATURES + + The drivers supports: + +* Window size. Note the size must fit in the screen, if the screen isn't big +enough you'll get the bigger posible size. Also note this depends on some +things you can't control: screen resolution, font size and window position. +Only the third could be controlled. Also note it ever fails if the +application is running in full screen and resized applications won't be able +to go fullscreen. +* Window title set/restore. +* Most keyboard combinations. +* Restore user screen. In some cases the text cursor seems to be lost after +running the application, this seems to be a bug in Win32 API triggered by +some missuse from my part. If you minimize the window and restore it, or just +hide it under another window and then make it visible again the cursor +appears. It doesn't happend in all situations and the code specifically +restores it. + + +3. IMPORTANT DETAILS + + These drivers seems to be slower on Windows 9x family and faster on Windows +NT family when compared to the DOS driver running windowed. I think that's +because Windows NT doesn't draw all the information sent to the screen, +instead the content is refreshed periodically. It doesn't apply to the +Windows 9x version running fullscreen where the speed is really slow, this is +even worst for the Win32 driver. I would like to get feedback about it. + When you try to resize an application that's windowed using the mouse what +you do is change the size of the font. It only works when the font size is +set to "Auto". If the value is fixed you can just reduce the size of the +window and get scroll bars. At least that's how Windows 98 SE works. + At least on my system the window can go to full screen only when the size +is 80x25 or 80x50. Otherwise the color palette changes and the application +must remain windowed. I don't know why the palette changes and you can't +control the color palette. + + +4. CONFIGURATION VARIABLES + + Only a few configuration variables are supported, none specific for these +drivers. The supported variables are: ScreenWidth, ScreenHeight, AppCP, ScrCP +and InpCP. + Note that ScreenWidth and ScreenHeight are limited as explained in +"Features" and the code page shouldn't be forced because: + +1) The API supports a very limited set of code pages. +2) The fonts are fixed and encoded as the OS reports. +3) The API have mechanisms to inform the current code page. This code page is +hard to change for Windows 95 family. + + For more information about configuration files read the corresponding doc. + diff --git a/tvision/doc/WinGr.txt b/tvision/doc/WinGr.txt new file mode 100644 index 0000000..f69b77e --- /dev/null +++ b/tvision/doc/WinGr.txt @@ -0,0 +1,11 @@ +Driver: WinGr +Author: Jose Angel Sanchez Caso (JASC) +Status: Not complete, random suggestions and details +$Revision: 1.1 $ + + This driver isn't finished yet. + That's a graphical Win32 driver. Note that graphical just means we emulate +the text drawing it. It doesn't mean the application will use Windows GUI for +buttons, menues, etc. + If you want to test this driver use a configuration file to chnage the +priority of the driver, use something like 200. diff --git a/tvision/doc/X11.txt b/tvision/doc/X11.txt new file mode 100644 index 0000000..8579e09 --- /dev/null +++ b/tvision/doc/X11.txt @@ -0,0 +1,177 @@ +Driver: X11 +Author: Salvador E. Tropea +Status: Not complete, random suggestions and details +Revision: $Revision: 1.10 $ + + This file documents details specific to the X11 driver. By X11 I mean the X +Window system version 11 release 6 also known as X11R6. The driver was tested +with XFree86 and Solaris. + Currently this file isn't organized and just contains things I think +somebody could need to know. + +* The X11 driver was tested using Debian GNU/Linux Potato and Woody and +Solaris 2.7 (Sun Ultra 60 machine). + +* The driver was tested in True Color modes, I didn't have the time to check +it in palette modes (256 colors usually) and I'm almost sure nothing works +for monochrome mode. If you need it working for 8 bpp depths please contact +me and we will try to see a way to solve any issue. I don't have any +motivation to expend my time working on 8 bpp modes if nobody needs it. + +* The approach used is slow in favor of portability and features. A lot of +enhancements can be done. If you know about X11 programming and have some +time please consider helping with it. + +* The driver uses 8x16 and 10x20 fixed fonts, no X fonts. In the future I +plan to code a driver supporting X11 fonts. Why? simple: because in this way +I can change the screen encoding on the fly and I know all the needed symbols +will be available. The library supports over than 40 encodings which needs +over than 580 symbols in the fonts. They cover the latin variants, cyrillics +and greek alphabets. Not all X fonts supports all the needed symbols, in fact +True Types usually have only ASCII characters. Additionally we need fixed +width fonts. + Currently the fonts provided by SETEdit project have more variety than the +XFree86 fixed font, which in fact are included. + +* I use monochromatic XImage objects for the fonts and I let X to expand the +colors. XFree86 seems to be quite ineficient doing it, while Solaris' X is +much faster. I think we can get much more speed by expanding the colors to an +internal bitmap and then doing the blit in one operation. But this needs +special care about different color depths and colors organizations. I guess +the color values returned by X can make it easy, but never tried. + +* The implemented clipboards are XA_CLIPBOARD and XA_PRIMARY. Only XA_STRING +format is supported. + +* I don't have a default icon, if you can create one please send it to me. + +* Debian GNU/Linux Potato specific (maybe others too): +The Shift+Tab combination doesn't work. The problem seems to be related to +the following key binding found in /usr/X11R6/lib/X11/xkb/symbols/us + + key { [ Tab, ISO_Left_Tab ] }; + +For some reason, didn't investigate it, the ISO_Left_Tab doesn't emit a +keycode and hence Shift+Tab never reachs the code. May be I'm wrong but my +way to fix that is by defining it like this: + + key { [ Tab ] }; + +If you know about a better solution just let me know. + +* To quickly disable this driver when starting an application from a terminal +emulator just define DISPLAY variable to nothing. Bash example: + +export DISPLAY= + +You can achive the same using a .tvrc file and giving a low priority to the +X11 driver. Example: + +[TV] +{ + [X11] + { + Priority=1 + } +} + +The bigger the number the more important the driver. The default value is +100, bigger than Linux, XTerm and UNIX drivers. + +* Window Manager/Desktop keys: In my opinion no WM/Dekstop should use simple +key combinations for their own purposes interfering with applications. +I don't know how to tell X11 to send the keystrokes to my application instead +of the WM. I know an application can drag the keyboard focus but I also know +it makes quite difficult to debug such an application. If you know about a +way to tell X11 something like: Alt+F1 is mine, send it to me when I have the +focus, please contact me. +My suggestion is to configure your WM/Desktop to use more convenient +keystrokes. +I use Enlightenment as WM and Desktop here is what I do to avoid interference +with TV applications: +a) Debian GNU/Linux Potato: That's version 0.16.3 and I don't know about any +Debian tool to configure the keyboard. So I edited +/usr/share/enlightenment/config/keybindings.cfg changing all the Alt+Fx to +Shift+Alt+Fx (__ALT to __ALT_SHIFT in Function keys). +b) Debian GNU/Linux Woody: That's version 0.16.4. A very nice package called +e16keyedit is available (I think it can be backported to Potato). It makes +easier to redefine the keys used by E. + +* The ScreenWidth and ScreenHeight configuration variables are supported. +They are very important because using them the window will be created with +the desired size. If you change the size after initialization the window +resize will be visible and part of the window could become outside the +screen. + +* The driver is probably the most complete and flexible of all available +drivers. All the TScreen things are supported: + + * Window size. + * Window title. + * Font size, but you must provide the fonts. + * Secondary font. + * Color palette. + * Busy indicator. + +* The standard configuration options are supported: + +ScreenWidth Columns of the window. +ScreenHeight Rows of the window. +ScreenPalette Color palette, that's a string containing the 16 RGB + values. + "0,0,0,0,0,168,..." +FontWidth Width of the font in pixels. +FontHeight Height of the font in pixels. +LoadSecondaryFont Request a secondary font to the application (must provide a + call back). +AppCP Application encoding. +ScrCP Screen encoding, this should be 885901. +InpCP Input encoding. + + Plus the following options: + +Font10x20 Selects the 10x20 font instead of 8x16. +HideCursorWhenNoFocus By default enabled +DontResizeToCells Don't resize the window to a cells multiple size if the WM + fails to follow the hints. This helps to avoid problems found + in KDE 3.1 alpha. +InternalBusyCursor When enabled we use our own mouse cursor for it. +UseUpdateThread When this option is enabled the driver updates the + window content even if the TV application is blocking + the CPU. That's very useful when the application + blocks and the window becomes "exposed". If this isn't + enabled X will fill the exposed area with black and + the user won't see the window content until the + application collects events. + It is available using two mechanisms selected at + compilation time: + 1) Using setitimer and signals: + It seems to be stable but the TV application must + avoid using setitimer and SIGALRM. + I only tested it for Linux but I'm using concepts I + successfuly used for Solaris in older versions of the + driver. + That's the default compilation option. + 2) Using POSIX threads (preemptive) + Only available for Linux. + When enabled the driver uses a separated thread to + collect the "expose" events and update the screen. + That's good because even when the application is + blocking (calling system, performing a long + calculation, etc.) the window can be exposed and the + contents of the screen will be updated (you don't get + a black window). But the problem is that Linux + implementation of POSIX threads is quite poor and + mixing threads with fork/exec doesn't work for big + applications. The driver implements it using + fork/system (system function is "thread protected") + but you must avoid killing your child or the update + thread will most probably die. The driver have a watch + dog timer and if the update thread dies will revert to + manual screen update in less than 2 seconds (>=1s & + <2s aprox.). + +* I don't know if anybody can be interested on it, but this driver compiles +and run for Windows. You need to use Cygwin with the XFree86 port installed +and run the applications from X. The result is quite slow, but works. + diff --git a/tvision/doc/XTerm.txt b/tvision/doc/XTerm.txt new file mode 100644 index 0000000..b84a98f --- /dev/null +++ b/tvision/doc/XTerm.txt @@ -0,0 +1,95 @@ +Driver: XTerm +Author: Salvador E. Tropea +Status: Complete +Revision: $Revision: 1.2 $ + +1. INTRODUCTION +2. FEATURES +3. IMPORTANT DETAILS +4. CONFIGURATION VARIABLES + +1. INTRODUCTION + + This driver was designed for the XTerm included in XFree86 v4.x. Previous +versions like the one included in XFree86 v3.3.6 are supported but then the +provided script must be used. I don't have access to other implementations of +XTerm if you have contact me. + The Eterm is also supported by this driver, for details specific to Eterm +please consult the documentation for the Eterm driver. + Use this driver when you have X Window but you need to use a remote machine +and the connection isn't fast enough to use the native X11 mode. + This driver is enabled when the environment variable TERM indicates the +terminal is called xterm. Most Linux distributions have other terminal +emulators that also reports xterm in the TERM variable. This is a pretty bad +idea and most of these terminal emulators are much less functional than +xterm. Even when people have the idea that XTerm is a simple and limited +terminal emulator I think XTerm is one of the most complete. I personally +like the aspect of Eterm, but XTerm is far more configurable. + + +2. FEATURES + + The driver supports: + +* Window size. +* Fonts size (set and restore). +* Palette. XTerm is quite slow on it. +* Window title set/restore. +* Most keyboard combinations when using XTerm from XFree86 v4.x, for older +versions use the provided script. +* Restore shell screen (limited, you can't nest). + + +3. IMPORTANT DETAILS + + In order to get the maximum of key combinations you must start XTerm using +a special script. This script defines some key combinations not supported by +XTerm, makes old XTerm versions to report keys as the new one and changes the +palette to be identical to the VGA BIOS palette (same used in Linux console +for example). + Note this configuration is specially configured for TV applications and +isn't the best for other tasks. I recommend to use at leat two connections to +the remote machine, one for general tasks and another from an XTerm with this +configuration to run TV applications. + One important thing about this script is that it defines the Alt+Key +combinations as Meta+Key combinations, this is really important for keyboards +without a Meta key. I personally have the left key that comes with a nasty +symbols similar to a flag as Meta key. + The script is called XTerm.res and is located in the examples/xterm +directory. + If you want to test this driver locally just export the DISPLAY variable +with a null content like this (bash syntax): + +$ export DISPLAY= + + +4. CONFIGURATION VARIABLES + + For more information read the configuration documentation. + This driver supports the following standard configuration variables: + +ScreenWidth Columns of the window. +ScreenHeight Rows of the window. +ScreenPalette Color palette, that's a string containing the 16 RGB values. + "0,0,0,0,0,168,..." +FontWidth Width of the font in pixels. +FontHeight Height of the font in pixels. +AppCP Application encoding. +ScrCP Screen encoding, this should be 885901. +InpCP Input encoding. + + Plus the special option: + +UseShellScreen If that's different than 0 the shell screen is used for output + and not the secondary buffer. This option is mainly only + useful when the application will run as a child of other + application that's already using the secondary buffer. This + can be the case of a debugger. + + Note that the font sizes are limited to a known set of sizes that +correspond to the fonts included in XFree86: + +5x7, 5x8, 6x10, 6x12, 6x13, 7x13, 7x14, 8x13, 8x16, 9x15, 9x18, 10x20, 10x24 + + If you specify another size the closest will be used. + diff --git a/tvision/doc/html.frt b/tvision/doc/html.frt new file mode 100644 index 0000000..ba962d1 --- /dev/null +++ b/tvision/doc/html.frt @@ -0,0 +1,272 @@ +# +# This file sets the behavior of the txh generator +# +# Lines starting with # or spaces are skiped except in strings or in [Generate] +# Be carefull with [ it delimits sections! +# + +[Configuration] +# +# No external program is needed! +# @.html means: Copy the temporal file to xxxxx.html +# +CommandLine=@.html +Name="Direct HTML 3.X format" + +[Delimiters] +# Up to 11 characters +SectionStart=/**[txh]** +# Up to 11 characters +SectionEnd=*********/ + +[Variables] +# +# Up to 16 definitions +# +# Codes for the behavior of the definitions: +# 1 Normal, put the content if found. +# 2 Repeat, use the last value found in the file, ~no is an exeption, ~clear stops +# 3 If not found replace by the prototype. +# 4 If not found replace by the class. +# 5 If not found replace by the name of the function +# 6 It disables the node generation for this comment. The variable is +# stored in the first variable that have associations and is in the comment. +# +# Additionally there are 2 special variables: +# 90 Name of the file +# 91 Line number of the end of the comment +# 92 Name of the var 0 in the format: ~0 ~~Distinguish{(~Distinguish)~} (node name) +# +# 0 The first variable is the main index variable +# +AddDefinition=Function,5 +# 1 +AddDefinition=Class,4 +# 2 +AddDefinition=Include,2 +# 3 +AddDefinition=Module,2 +# 4 +AddDefinition=Prototype,3 +# 5 +AddDefinition=Description,1 +# 6 +AddDefinition=Return,1 +# 7 +AddDefinition=Example,1 +# 8 +AddDefinition=Comments,6 +# +# It says what variable is added to distinguish between 2 vars 0 that are equal +# +Distinguish=1 + +[Associations] +# +# Up to 8 associations +# +# The associations are between the 0 variable and another variable. +# +# Name in main menu, node, variable, optional to add to each node +# +AddAssoc=List by classes,Classes,1,(class) +AddAssoc=List by modules,Modules,3 +AddAssoc=List by files,Files,90 + +[Replace] +# +# All must be delimited by ", they can be used in the GenMain section +# +# Title of the HTML +Constant="Turbo Vision reference" + +# Description for the help +Constant="This document describes the functions of Turbo Vision that didn't +exist in the original version of the library.@* +Note that only a few things are documented here, I need help to populate +this file. +@p +This document applies to version 2.0.0 +of the Turbo Vision library. +@p" + +[Commands] +# +# You can enclose these values between " to make more clear where +# they start and end. Use \n,\r,\t and \" like in C. Use \ at the +# end to concatenate like in C. +# +# @p = end of paragraph +# +EndOfPar="

    " +# +# @* = break line +# +BreakLine="
    " +# +# @{value} is the special cross ref. +# ~0 Is the visible name of a reference +# ~1 Is the real name of a reference +# +CrossRef="~0" +# +# What we must get from a @@ sequence +# +Double@="@" + +[DefinedCommands] +# +# The format is @{parameters ...} +# +var="~0" +subtitle="~0

    " +pre=

    +/pre=
    +link="~1" +mailto="~1" + +# +# This section says how to translate ASCIIs +# +[ASCIIConvert] +á=á +é=é +í=í +ó=ó +ú=ú +ñ=ñ +Ñ=Ñ +¡=¡ +¿=¿ +ä=ä +ë=ë +ï=ï +ö=ö +ü=ü +Ü=Ü +à=à +è=è +ì=ì +ò=ò +ù=ù +<=< +>=> + +# +# Use ~number to use one variable +# Use ~~number{} for conditional, all the code inside {} will become +# conditional +# This section isn't passed for the macro expansion so here you are +# free to use special commands for the formater. +# +[GenNode] +


    + +
    ~0 (~90 ~91)
    + +Syntax

    + +~~2{ +

    +# This line is a comment, but the next is code
    + #define Uses_~2
    + #include <tv.h>
    + 
    +
    +~} +~~4{ +
    + ~4;
    +
    +~} +~~1{ +Member of the class: +~1 +

    +~} + +~~5{ +Description

    + +~5 +

    +~} +~~6{ +Return Value

    + +~6 +

    +~} +~~7{ +Example

    + +~7 +

    +~} + +[GenMenu] +Start="

    " +# +# ~1 is the visible name +# ~2 is the name of the node +# +Entry="
  • ~1" +End="
  • " + +# +# ~1 is the name of the association +# ~2 is the menu for it +# +[GenAssoMain] +


    + +

    ~1

    + +~2 +# +# ~1 is the name of the association +# ~2 is the name without the distinguish +# ~3 is the comment for it +# ~4 is the menu for it +# +[GenAssoRest] +


    + +

    ~2

    + +~3 + +~4 + +# +# ~1 Main menu +# ~2 Name of the function list node +# ~3 Menu for all the functions +# ~4 All the associations code +# ~5 All the function nodes +# ~50+ Values from section Replace +# +[GenMain] + + +~50 + + +

    ~50

    + +~51 + +~1 + +


    + +

    ~2

    + +~3 + +~4 + +~5 + + + diff --git a/tvision/doc/install/bcc.txt b/tvision/doc/install/bcc.txt new file mode 100644 index 0000000..c0378e1 --- /dev/null +++ b/tvision/doc/install/bcc.txt @@ -0,0 +1,70 @@ + This file describes how to compile the package for Win32 systems using +Borland C++ 5.5 free command line tools. Optionally you can use the BorlandC +Builder 6 for it, that's compiler version 5.6. But I can do periodical tests +only with the former. If you want to volunteer to periodically test the code +with other versions please let me know. + +$Id: bcc.txt,v 1.3 2003/06/26 19:15:58 set Exp $ + +1. INTRODUCTION +2. HOW TO COMPILE +3. INSTALLATION + + + +1. INTRODUCTION + + The tools can be downloaded from internet without charge. Note: BorlandC +Builder 6 also have a trial I used to fix some issues, but it have a limited +time usage. + This target is periodically tested for compilation but not much tested for +functionality. + You can compile the editor to run under Win32 platforms using various +compilers, for this reason I explain the dis/advantages of using BC++ 5.5 for +it. + +Advantages: + +* Unlike djgpp it generates a Win32 executable, so it integrates better with +Windows NT incarnations (NT, 2000, XP, etc.). +* The resulting binary doesn't need special DLLs. +* BC++ 5.5 compiles really fast. +* You don't need a lot of GNU tools, just the BC++ package distributed by +Borland. +* The environment is very well controlled. If you have BC++ 5.5 free command +line tools it should compile without any problems. + +Disadvantages: + +* I don't use the resulting binary too much so it is more probable to find +bugs not found in the same version compiled with other compilers. +* BC++ 5.5 is quite inferior when compared with gcc in terms of code +optimization. +* This target can't run the configure script so you can't fine tune the +process. +* The installation isn't automated. + + + +2. HOW TO COMPILE + + Currently I'm in a middle of a transition between an old mechanism and a +new one (may 2003) so I'll give information about both mechanism. + +A) The new mechanism: + + Run "make -f Makefile.bcc" this should create the library in the makes +directory. The name is librhtv.lib. + +B) The old mechanism: + + Instructions about it are contained in the WinNT directory. +See: winnt/readme.txt + + + +3. INSTALLATION + + Currently this target needs manual installation. You can also use the files +without installing just providing the paths to the compiler. + diff --git a/tvision/doc/install/cygwin.txt b/tvision/doc/install/cygwin.txt new file mode 100644 index 0000000..988ce23 --- /dev/null +++ b/tvision/doc/install/cygwin.txt @@ -0,0 +1,54 @@ + This file describes how to compile the package for Win32 systems using +GNU tools as provided by Cygnus' Cygwin package (Cygnus is currently part of +Red Hat). + +$Id: cygwin.txt,v 1.3 2003/06/26 19:15:58 set Exp $ + +1. INTRODUCTION +2. COMPILING AND INSTALLING + + +1. INTRODUCTION + + Cygwin provides a POSIX environment for Win32 systems based on GNU tools. +It makes quite easy to compile programs adapted for GNU tools. In order to +compile this package you have to install the tools listed in +doc/install/tools.txt + A short list of the needed tools is: + bash, binutils, fileutils, gcc, gpp, gettext, make, perl, shellutils, +texinfo and textutils. + I experimented some bizarre problems while using Perl from Cygwin +distribution so I switched to the version distributed by djgpp package. You +can find information about djgpp in: http://www.delorie.com/djgpp/ + I hope the problems are fixed in a newer version of Cygwin tools but +lamentably I don't have time to test it. Volunteers will be welcome. + Some users reported success using the UNIX tarball instead of the .zip +file. But I think it depends on the way you configured Cygwin. + You can compile the library to run under Win32 platforms using various +compilers, for this reason I explain the dis/advantages of using Cygwin for +it. + +Advantages: + +* Unlike djgpp it generates a Win32 executable, so it integrates better with +Windows NT incarnations (NT, 2000, XP, etc.). +* GCC is very good optimizing code. +* You can use the configure script to fine tune the compilation process. +* The installation is automated. + +Disadvantages: + +* The resulting binary needs a special DLLs provided by Cygwin. +* The available compiler and the whole tools are really slow. GCC 3.x is too +slow to compile C++ and the Win32 port is even worst. +* I don't use the resulting binary too much so it is more probable to find +bugs not found in the same version compiled with other compilers. + + +2. COMPILING & INSTALLING + + Once you installed all the needed tools your system will become some kind +of GNU/Win32 system. For this reason you can just follow the instructions found +in doc/install/unix.txt + I tested this process using Cygwin 1.3.3-2. + diff --git a/tvision/doc/install/djgpp.txt b/tvision/doc/install/djgpp.txt new file mode 100644 index 0000000..9ed45dd --- /dev/null +++ b/tvision/doc/install/djgpp.txt @@ -0,0 +1,84 @@ + This file describes how to compile the package for DOS (djgpp) systems using +GNU tools. You have to install a quite complete djgpp environment, you can +download it from: http://www.delorie.com/djgpp/ + +$Id: djgpp.txt,v 1.4 2004/11/29 16:23:17 set Exp $ + +1. INTRODUCTION +2. GETTEXT COLLISION +3. COMPILING AND INSTALLING +4. LAST DJGPP ENVIRONMENT TESTED + + +1. INTRODUCTION + + DJGPP provides a quite POSIX compliant environment for DOS systems. It is +based on GNU tools. In order to compile this package you have to install the +tools listed in doc/install/tools.txt + A short list of the needed tools is: + binutils, fileutils, gcc, gpp, gettext, make, perl, shellutils, texinfo and +textutils. + + We compiled the library using DJGPP 2.01, 2.02 and 2.03. Older versions +won't work. The 2.01 version have some bugs that affect this package so I +suggest a newer version. + +2. GETTEXT COLLISION + + DJGPP versions older than 2.04 contains a collision between conio's gettext +function and libintl's gettext function. Both are named "gettext". The +documentation included in the gettext (libintl) package (i.e. gtxt040b.zip) +explains how to solve this collision. You'll need to replace conio.o from +libc.a and change conio.h. + Without it you'll get errors from the linker. Older versions of the linker +didn't complain about it. + +3. COMPILING + + Once you installed all the needed tools your system will become some kind +of GNU/DOS system. For this reason you can just follow the instructions found +in doc/install/unix.txt The only difference is that you'll have to invoke the +configure.bat file instead of configure script, but as you don't have to type +the extension it looks almost the same as in UNIX: + +c:\djgpp\contrib\tvision>configure + +4. LAST DJGPP ENVIRONMENT TESTED + + The last compilation test was performed in the following system: + +OS: Windows 98 SE + +Core utils: +djdev203 Development Kit and Runtime (June 2002 Refresh) +gcc343b.zip : GCC 3.4.3 C compiler binaries for DJGPP +gpp343b.zip : GCC 3.4.3 C++ compiler binaries for DJGPP +bnu215b.zip : GNU binutils-2.15 binaries for DJGPP +gtxt040b GNU Gettext 0.10.40 binaries for DJGPP V2 +licv192b GNU libiconv 1.9.2 for DJGPP V2 +mak3791b GNU Make 3.79.1 binaries for DJGPP V2 +fil41b GNU Fileutils 4.1 for DJGPP 2.x, release 7 (binaries) +perl561b Perl 5.6.1b release 3 for DJGPP V2 (binaries) + +Other utils: +bsh204d GNU Bash 2.04 binary for DJGPP +bz2-102b bzip2 1.0.2 for DJGPP V2 +CVS 1.10 for DJGPP (local only) - Binary Distribution (patchlevel 3 - 05/2000) +dif281b GNU Diffutils 2.8.1 for DJGPP V2 +djtzn203 Extra Timezone Support Files +faq230b DJGPP FAQ List edition 2.30 for DJGPP v2.03 +find41b GNU findutils 4.1 for DJGPP V2 +gdb611b.zip - gdb-6.1.1 (binary archive for DJGPP) +gdb611.zip - gdb-6.1.1 (source archive for DJGPP) +grep24b GNU grep 2.4 binaries for DJGPP V2 +gzip13b GNU gzip 1.3 binaries for DJGPP V2 +lss374b GNU Less v374 binaries (DJGPP v2) +pat254b GNU Patch 2.5.4 binaries for DJGPP v2 +rcode35b.zip GNU Recode 3.5 binaries for DJGPP V2 +Sh-utils 2.0.11 Apr 18, 2002 - Prashant TR +tar112ab GNU tar 1.12a binaries for DJGPP V2 +txi47b GNU Texinfo 4.7 binaries for DJGPP V2 +txt20b GNU Textutils 2.0 binaries for DJGPP V2 +Which version 2.11 modified to work with DJGPP by David Cullen + + diff --git a/tvision/doc/install/linux.txt b/tvision/doc/install/linux.txt new file mode 100644 index 0000000..a0cfb53 --- /dev/null +++ b/tvision/doc/install/linux.txt @@ -0,0 +1,41 @@ + This file describes how to compile the package for Linux systems using +GNU tools. So you need a GNU/Linux environment, this is provided by all Linux +distributions I know even when their name doesn't clearly denote they are +GNU/Linux distros. + +$Id: linux.txt,v 1.2 2003/06/23 14:12:03 set Exp $ + +1. INTRODUCTION +2. MANUAL MECHANISM +3. SYSTEMS BASED ON .DEB FILES (DEBIAN GNU/LINUX) +4. SYSTEMS BASED ON .RPM FILES (REDHAT, SUSE, MANDRAKE) + + +1. INTRODUCTION + + Most Linux distributions have some package system, is much better if you +create the packages first and then install them. This is because then you can +uninstall the files or install the binaries in another machine that runs the +same distribution. + Currently the library have scripts to generate packages for distributions +based on .deb and .rpm packages. For other distributions you should follow +the "manual" mechanism. + For a list of tools and libraries you should have in your system please read +the doc/install/tools.txt file. + +2. MANUAL MECHANISM + + Follow the instructions found in the doc/install/unix.txt file. + +3. SYSTEMS BASED ON .DEB FILES (DEBIAN GNU/LINUX) + + Follow the instructions found in the debian/README file. + +4. SYSTEMS BASED ON .RPM FILES (REDHAT, SUSE, MANDRAKE) + + Follow the instructions found in the redhat/README file. + Note: As the script to generate the RPM files doesn't check for errors I +recommend trying to follow the "manual" mechanism but skip the installation +procedure. Once you are sure all compiles perfectly for your system then try +this procedure. + diff --git a/tvision/doc/install/mingwin.txt b/tvision/doc/install/mingwin.txt new file mode 100644 index 0000000..9b133c2 --- /dev/null +++ b/tvision/doc/install/mingwin.txt @@ -0,0 +1,51 @@ + This file describes how to compile the package for Win32 systems using +GNU tools as provided by MinGW package (aka MingWin, MinGW32, etc.). + +$Id: mingwin.txt,v 1.4 2004/10/15 23:38:25 set Exp $ + +1. INTRODUCTION +2. COMPILING AND INSTALLING + + +1. INTRODUCTION + + MinGW needs the help of MSys and a Perl interpreter to compile this +package. I tested it using MinGW 2.0.0/3.1.0, MSys 1.0.8/1.0.10 and the +Siemens Perl port (SiePerl). This provides a good environment for compilation. +You must ensure that MSys' make is used because MinGW 1.1 ships a make +command that fails. Newer versions doesn't have this problem. + IMPORTANT! the resulting application can't be run from the MSys console +(rxvt), use a DOS console or just start it as any Windows application. + For old versions you have to ensure that /bin/sh exists or at least create +a symlink to bash there. If it isn't there you won't be able to run the shell +scripts. + You can compile the library to run under Win32 platforms using various +compilers, for this reason I explain the dis/advantages of using Cygwin for +it. + +Advantages: + +* Unlike djgpp it generates a Win32 executable, so it integrates better with +Windows NT incarnations (NT, 2000, XP, etc.). +* GCC is very good optimizing code. +* You can use the configure script to fine tune the compilation process. +* The installation is automated. +* The resulting binary doesn't need special DLLs. +* All the needed tools are concentrated in a few packages you have to +download. + +Disadvantages: + +* The available compiler and the whole tools are really slow. GCC 3.x is too +slow to compile C++ and the Win32 port is even worst. +* I don't use the resulting binary too much so it is more probable to find +bugs not found in the same version compiled with other compilers. + + +2. COMPILING AND INSTALLING + + Once you installed all the needed tools your system will become some kind +of GNU/Win32 system. For this reason you can just follow the instructions found +in doc/install/unix.txt + I recommed configuring the package with --no-intl. + diff --git a/tvision/doc/install/msvc.txt b/tvision/doc/install/msvc.txt new file mode 100644 index 0000000..c2d2ddd --- /dev/null +++ b/tvision/doc/install/msvc.txt @@ -0,0 +1,105 @@ + This file describes how to compile the package for Win32 systems using +Microsoft Visual C compiler. Note that I don't have it and Microsoft doesn't +offer reduced versions for free like Borland does. For this reason this +target ever lags behind. I need volunteer to test this target periodically. + Note: Some time after writing it Microsoft released a reduced and free +version of the compiler, but only for Windows 2000 and newer systems. I +don't have access to such a version of Windows. + +$Id: msvc.txt,v 1.7 2009/01/06 12:39:22 set Exp $ + +1. INTRODUCTION +2. HOW TO COMPILE +3. INSTALLING +4. MSVC TARGET CONTRIBUTORS +5. USING VISUAL STUDIO AND NOT NMAKE + + + +1. INTRODUCTION + + This target is supported because users helped to make it possible. If you +find any problem just do the same the other users did: help to fix them. + You can also create Win32 versions of this package using BorlandC Builder, +Cygwin, Open Watcom or MinGW. + Versions 5.0, 6.0, 7.0 and 7.1 compiled the code. + Modern versions of Visual Studio doesn't seem to include nmake tool. A quick +and incomplete, but useful, method to compile the code is in the section 5. + + +2. HOW TO COMPILE + + You can use the unified make system: + +nmake -f Makefile.nmk + + If it fails you can try using the old mechanism explained in +winnt/readme.txt + + +3. INSTALLATION + + Currently this target needs manual installation. You can also use the files +without installing just providing the paths to the compiler. + + +4. MSVC TARGET CONTRIBUTORS + +Chronologically sorted: + +Drivers: [Shared with other Win32 targets] + +WinNT: Anatoli Soltan +Win32: Vadim Beloborodov +WinGr: José Ángel Sánchez Caso + +Compilation: + +WintiX + Help to get it working with MSVC 5.0. +Sergey Krivulja + Compilation issue. +Mike Gorchak + Adaptation to MSVC 7.0 and 7.1. +Grzegorz Adam Hankiewicz + Debug options and help with unified mechanism. +David Doubrava (ddoubrava/volny/cz) + Compilation issue. +Arnold Wiegert + Help with the free version of MSVC (7.1). + Adaptation to MSVC 6.0. + Hints about MSVC 4.0. +Christian Kirches . + Compilation issues related to Visual Studio .NET 2005 Express Beta. +Eddie (K.Blacha) + Compilation issues related to MSVC 7.1. +Harry Sack + Compilation using Visual Studio 2008 without nmake. + + +5. USING VISUAL STUDIO AND NOT NMAKE + +1) create a new project: 'Visual C++' -> 'General' -> 'Empty Project' + +2) add to 'Source Files' folder in your VS Project: + +\tvision => *.cc +\tvision\classes => *.cc and *.cc of all its subdirs +\tvision\compat => *.cc and *.c +\tvision\names => *.cc +\tvision\stream => *.cc + +3) go to 'Project' -> 'Properties'. Choose 'All Configurations'. Go to +'C/C++' -> 'General' -> 'Additional Include Directories'. Add the following +directories there: + +\tvision\include and all its subdirs +\tvision\winnt\include\msvc + +4) copy the file \tvision\winnt\include\tv\configtv.h to \tvision\include\tv + +5) now you can build the library in Debug and Release mode + +6) now just add your source file with your main() function to your VS project +and compile it. + diff --git a/tvision/doc/install/tools.txt b/tvision/doc/install/tools.txt new file mode 100644 index 0000000..7e4d763 --- /dev/null +++ b/tvision/doc/install/tools.txt @@ -0,0 +1,137 @@ + This file gives a list of tools and libraries you used by the package. The +list isn't complete so please report any missing stuff. + The list is oriented to systems using the GNU tools, not for Borland and +Miscrosoft environments. + IMPORTANT! most Linux systems have the needed libraries installed but +rarely have the headers installed. They are provided in separated packages +intended for development (XXXX-dev). + +TOOLS +===== + +Binutils: +--------- + + They include the linker and assembler. They must be the GNU versions. + +Compiler: +--------- + + The code was compiled with GCC 2.7.x, 2.8.x, 2.95.x, egcs 1.x, 3.x and may +be other versions. As I can't have systems with all of them I can't be sure +all of them can be currently used. + I suggest gcc 2.8.1 or newer because 2.7.2 had some bugs in the C++ library +and its workaround could go away soon. + I don't recommend gcc 2.9.6 nor egcs 1.x because these compilers have too +much bugs. Workarounds for these problems were created but as I don't have +these compilers new code could break. I recommend using a more stable +compiler. + The gcc 2.95.x compilers gave me very good results. + The code cleanly compiled with gcc 3.0, 3.1.x, 3.2.x and 3.3 but each +release of gcc 3.x likes to break something in the C++ stuff so be patient +and report any problems. One particular detail is that gcc 3.x is much more +slower than gcc 2.95.x when compiling C++ code. This is because the standard +C++ library now follows the ISO 1998 standard much more closely and hence +does a heavy use of templates, it looks like gcc 3.x performance to compile +such a code is really bad. + At the moment of this writing (june 2003) my recommendation is gcc 2.95.4. + +bzip2: +------ + + Optionally (configuration option) used to create the tarball distributions. + +fileutils: +---------- + + They are rm, cp, mv, etc. and all UNIX systems have them. DJGPP users must +install them. + +gettext: +-------- + + Needed for internationalization. They aren't mandatory. Note: this is one +of those packages that likes to break its API. + Note: Solaris provides its own implementation but it isn't supported. + +gzip: +----- + + Used only to create the tarball distributions. + +make: +----- + + Obviously mandatory. You must install GNU make, other make tools aren't +enough. The executable can be called gmake to avoid collisions with the +native make tool. + +Perl: +----- + + The configuration script and others are Perl scripts, you'll need Perl +5.x. I strongly recommend using it even when the tarball and zip files +usually contains preconfigured sources that will compile out-of-the-box in +many systems. + +RHIDE: +------ + + RHIDE users can configure the package and the compile it using the RHIDE +projects. But you'll need a really new RHIDE, some times even from CVS. So I +no longer recommend using RHIDE unless you are going to debug or modify the +code. + At the moment of this writing (june 2003) I use RHIDE 1.5 from CVS. + +shellutils: +----------- + + They are pwd, uname, etc. and all UNIX systems have them. DJGPP users must +install them. + +tar: +---- + + Used only to create the tarball distributions. + Note: not all tar implementations are usable, get GNU tar if you have +problems with it. + +textutils: +---------- + + They are cat, split, etc. and all UNIX systems have them. DJGPP users must +install them. + + +LIBRARIES +========= + +gpm: +---- + + It provides mouse functionality for the Linux console. I tested versions +1.13, 1.14, 1.17.x and 1.19.x. + Note: binaries compiled with a version usually fails to work if you change +the gpm daemon version. + +ncurses: +-------- + + This is mandatory for UNIX systems where the X11 isn't available. But is +recommended for all UNIX systems because it is used when the terminal isn't +known. Versions 3.4 and newer were used. I remmember also testing with 4.2, +5.0, 5.2 and 5.3. + Note: none of the listed versions compiles ok using gcc 3.3 and -Wall +because the headers contains chars as array indexes. + +X libraries: +------------ + + They are needed to create a UNIX application that can connect to an X +server and provide a good text emulation. It works even better than the +ncurses driver. That's a must for UNIX systems with X11 installed. + CygWin also provides X11 under Win32 systems. This is just a curiosity. +When I tested it the performance was really poor but the test application +was functional. + + diff --git a/tvision/doc/install/unix.txt b/tvision/doc/install/unix.txt new file mode 100644 index 0000000..5b30b00 --- /dev/null +++ b/tvision/doc/install/unix.txt @@ -0,0 +1,113 @@ + This file describes how to compile the package for UNIX systems using +GNU tools. I personaly use "Debian GNU/Linux" but the code successfuly +compiled for Darwin, FreeBSD, NetBSD, OpenBSD, QNX, Solaris and Tru64. +Instructions specific for Linux systems can be found in the +doc/install/linux.txt but this instructions are also valid for Linux and +in fact the Linux file refers to this one for the "manual" installation +mechanism. + +$Id: unix.txt,v 1.3 2004/10/08 15:05:36 set Exp $ + +1. INTRODUCTION +2. IMPORTANT NOTE +3. CONFIGURING +4. COMPILING +5. INSTALLING + + +1. INTRODUCTION + + FreeBSD systems seems to have all the needed GNU tools (GNU/FreeBSD ;-). +FreeBSD details were contributed by Andrew 'Onyx' Shevtsov (miniEleph) +. + NetBSD and OpenBSD machines that I tested at Source Forge Compile Farm +also have GNU tools available. + Darwin is the core of MacOS X 10.x, it have some bizarre GNU tools modified +by Apple. So even when Darwin is an *BSD system it is a little bit +complicated. The code included in the 2.0.3 release compiled ok. + QNX systems are a little bit more problematic but they also contain the +needed tools. QNX details were contributed by Mike Gorchak . + Solaris doesn't have all the needed GNU tools so you must get them from +internet. You should get at least make, gcc/g++ and perl, I'm not sure what +else is needed. I have a Solaris 2.7 (Ultra 60 machine) at work with the +needed tools installed. I also succeed using Solaris 9 at Source Forge. + A user reported success using HP-UX, but I couldn't verify it (HP Test +Drive problems). + I also succeed to compile using Tru64 (OSF1) v5.1b. But the installed GNU +tools (from a package identified as TWWfsw) have some major limitations. + If you are dealing with other UNIX box the first step will be to get the +most common GNU tools used for development and then start trying. Contact me +if you need help or want to contribute changes needed to compile for your +UNIX box. + For a list of tools and libraries you should have in your system please read +the doc/install/tools.txt file. + +2. IMPORTANT NOTE + + I noticed that a lot of UNIX machines that have GNU tools installed are +wrongly configured. Here are some details you must check: + +A) The PATH must include the directory where GNU tools are installed. Some +times the tools aren't installed in the same directory. So you have to +double check that all the tools can be started without specifying its full +path. Example (bash): +$ export PATH=$PATH:/usr/local/bin + +B) All the support libraries must be in the linker path. This can be +configured at system level or just using the LD_LIBRARY_PATH environment +variable. I saw too much systems where you can't even create a simple C++ +program because the libraries aren't in the linker path. Example (bash): +$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib:/opt/TWWfsw/gcc33r/lib + +3. CONFIGURING + + The first step is the configuration, this is a Perl script so you must have +Perl in your system: + +$ ./configure + + This script will inform you what was found in your system and what wasn't. +If the missing component is vital the script will stop. Read the output of +the script carefuly. Unlike the traditional configure scripts created by GNU +autoconf this script doesn't print useless information (like if your system +have 20 of the string functions needed), so the output is not too big. + If your system and/or CPU can't be detected please take a look at the +conflib.pl file. The DetectOS function determines the OS using the output of +uname command. The DetectCPU function determines the CPU by actually +compiling a small program with conditionals for all the architectures I +currently tested. If you need to add something there just contact me. + If the script fails install the missing component and run it again. If +optional components are missing the script will suggest installing them. + Once you successfuly configured the package you can go to the next step. + If you want to change any of the default compilation options run: + +$ ./configure --help + + It will inform all the available options. The --prefix=... is something you +could want to use. + If you want to make changes to the code and contribute to the project I +recommend configuring the package using the same options I use: + +$ ./configset + + This enables some maintainance stuff that you'll need for development. The +most important detail are header dependencies. + +4. COMPILING + + Just use the make command. If your system must use gmake the configuration +will inform it. + +5. INSTALLING + + Use the install target, you'll most probably need to switch to "root" to +run this step: + +# make install + + You can change the destination prefix using: + +# make prefix=/path_you_want install + + But I recommend doing it during the configuration step. + diff --git a/tvision/doc/install/watcom.txt b/tvision/doc/install/watcom.txt new file mode 100644 index 0000000..43c8b59 --- /dev/null +++ b/tvision/doc/install/watcom.txt @@ -0,0 +1,54 @@ + This file describes how to compile the package for Win32 systems using +Open Watcom compiler. (http://www.openwatcom.org). + +$Id: watcom.txt,v 1.3 2005/09/20 14:48:37 set Exp $ + +1. INTRODUCTION +2. HOW TO COMPILE +3. INSTALLING +4. OPEN WATCOM TARGET CONTRIBUTORS + + + +1. INTRODUCTION + + This target is supported because users helped to make it possible. If you +find any problem just do the same the other users did: help to fix them. + You can also create Win32 versions of this package using BorlandC Builder, +Cygwin, MSVC or MinGW. + Version 1.3 compiled the code for 2005/09/20 CVS snapshot. + + +2. HOW TO COMPILE + + You can use the unified make system: + +wmake -f Makefile.wat + + This will generate makes/librhtv.dll + + +3. INSTALLATION + + Currently this target needs manual installation. You can also use the files +without installing just providing the paths to the compiler. + + +4. OPEN WATCOM TARGET CONTRIBUTORS + +Chronologically sorted: + +Drivers: [Shared with other Win32 targets] + +WinNT: Anatoli Soltan +Win32: Vadim Beloborodov +WinGr: José Ángel Sánchez Caso + +Compilation: + +Lothar Behrens + Help to get it working. + DLL stuff. + Compilation rules. + + diff --git a/tvision/doc/libdocs.epr b/tvision/doc/libdocs.epr new file mode 100644 index 0000000..509340a Binary files /dev/null and b/tvision/doc/libdocs.epr differ diff --git a/tvision/doc/troubleshooting/Linux/1/code.cc b/tvision/doc/troubleshooting/Linux/1/code.cc new file mode 100755 index 0000000..83468d8 --- /dev/null +++ b/tvision/doc/troubleshooting/Linux/1/code.cc @@ -0,0 +1,10 @@ +#include + +#define ENTER_UTF8 "\e%G" +#define EXIT_UTF8 "\e%@" + +int main(int argc, char *argv[]) +{ + fputs(EXIT_UTF8,stdout); + return 0; +} diff --git a/tvision/doc/troubleshooting/Linux/1/readme.txt b/tvision/doc/troubleshooting/Linux/1/readme.txt new file mode 100755 index 0000000..ae01097 --- /dev/null +++ b/tvision/doc/troubleshooting/Linux/1/readme.txt @@ -0,0 +1,42 @@ +Introduction: +------------- + +My Debian GNU/Linux Woody starts in code page mode, as Red Hat < 8.0 also +does. But some people told me Red Hat 8.0 starts in UTF-8 mode. +I tried setting the UTF-8 mode and starting SETEdit the result wasn't +really bad: +* When using /dev/vcs*: All worked perfectly and at exit the console was +in UTF-8. +* When using only escape sequences: Some drawings failed at the beggining +but it got normal quite soon. At exit the console was in code page mode. + +This test will determine: +------------------------- + +I) Is the console in UTF-8 mode? +II) If that's the case: Can we exit from UTF-8 mode? + +Steps: +------ + +1) Compile code.cc and utf8.cc: +g++ -o code code.cc +g++ -o utf8 utf8.cc + +2) Run "cat test.txt" +a) If you can see the accented vowels then this console is in normal mode. +b) If nothing is displayed then the console is in UTF-8 mode. + +3) Run "cat test-utf8.txt" +This will confirm step 2: +a) Normal console: Displays a mix between A with ~ and other chars. +b) UTF-8 console: Displayes the accented vowels. + +4) If the console is in UTF-8 mode try: +a) Run ./code +b) Do the steps 2 and 3. It should work as points 2a and 3a +c) Run ./utf8 +d) Do the steps 2 and 3. It should work as the for the firt try. + +Comment me about the results for each step. + diff --git a/tvision/doc/troubleshooting/Linux/1/test-utf8.txt b/tvision/doc/troubleshooting/Linux/1/test-utf8.txt new file mode 100755 index 0000000..8967aba --- /dev/null +++ b/tvision/doc/troubleshooting/Linux/1/test-utf8.txt @@ -0,0 +1,3 @@ +ÃÉÃÓÚ +áéíóú + diff --git a/tvision/doc/troubleshooting/Linux/1/test.txt b/tvision/doc/troubleshooting/Linux/1/test.txt new file mode 100755 index 0000000..a30391b --- /dev/null +++ b/tvision/doc/troubleshooting/Linux/1/test.txt @@ -0,0 +1,3 @@ +ÁÉÍÓÚ +áéíóú + diff --git a/tvision/doc/troubleshooting/Linux/1/utf8.cc b/tvision/doc/troubleshooting/Linux/1/utf8.cc new file mode 100755 index 0000000..fd1319c --- /dev/null +++ b/tvision/doc/troubleshooting/Linux/1/utf8.cc @@ -0,0 +1,11 @@ +#include + +#define ENTER_UTF8 "\e%G" +#define EXIT_UTF8 "\e%@" + +int main(int argc, char *argv[]) +{ + fputs(ENTER_UTF8,stdout); + + return 0; +} diff --git a/tvision/doc/troubleshooting/Linux/2/readme.txt b/tvision/doc/troubleshooting/Linux/2/readme.txt new file mode 100755 index 0000000..9b21ebc --- /dev/null +++ b/tvision/doc/troubleshooting/Linux/2/readme.txt @@ -0,0 +1,38 @@ +Introduction: +------------- + +TV can inform a lot of things when compiled in debug mode. + +This test will determine: +------------------------- + +Which mode of drawing is in use. + +Steps: +------ + +1) Uncomment the following line: + +//#define DEBUG + +located at the include/tv/linux/log.h header. + +2) Uncomment the following line: + +//#define DEBUG_CODEPAGE + +is line 298 aprox. located at classes/linux/linuxscr.cc + +3) Recompile TV and make sure the editor is using this version of the library. + +4) Start the editor using: + +e -r 2> log.txt + +5) Just exit. + +The log.txt will contain very important information about what was detected, +send it to me. +If the user doesn't have access to the /dev/vcs* devices generate another log +file for the root. + diff --git a/tvision/doc/troubleshooting/Linux/3/readme.txt b/tvision/doc/troubleshooting/Linux/3/readme.txt new file mode 100755 index 0000000..aa8d6a2 --- /dev/null +++ b/tvision/doc/troubleshooting/Linux/3/readme.txt @@ -0,0 +1,21 @@ +Introduction: +------------- + +Linux can be configured to use a custom font with an arbitrary encoding. This +font doesn't have to follow any standard and in fact most standars doesn't +define how to display control characters ([0-31] + [127-159]). + +This test will determine: +------------------------- + +The font and Unicode maps. + +Steps: +------ + +1) Run: + +consolechars -F font.psf -M map.acm -U map.sfm + +2) Send me the output files: font.psf, map.acm and map.sfm + diff --git a/tvision/doc/troubleshooting/Linux/4/readme.txt b/tvision/doc/troubleshooting/Linux/4/readme.txt new file mode 100755 index 0000000..434e53e --- /dev/null +++ b/tvision/doc/troubleshooting/Linux/4/readme.txt @@ -0,0 +1,39 @@ +Introduction: +------------- + +UNIX consoles are quite complex to handle in a way that's fast and reliable +at the same time. Buffered output can do a real mess. + +This test will determine: +------------------------- + +If Linux is executing all the escape sequences. + +Steps: +------ + +1) Compile two versions of the test program: + +g++ -o t1 test.cc +g++ -o t2 -DSEPARATED_HANDLE=1 test.cc + +2) Run "./t1 1 2> log_4_1.txt" +Describe the output, the exact name of the colors is not really important, +but the sequence is. The colors should go from the 0 to 15 for foreground +and 15 to 0 for background 13 times. +Also pay attention to the separation between " Hello! " messages. + +3) Run "./t1 20 2> /dev/null" +Check if the output is the same as (2), try with other numbers other than +20. + +4) Run "./t2 1 2> log_4_2.txt" +Is the same output? + +5) Run "./t2 20 2> /dev/null" +Is the same? + +6) Just in case: reset the console using "reset" ;-) + +7) Send me the log files and the descriptions. + diff --git a/tvision/doc/troubleshooting/Linux/4/test.cc b/tvision/doc/troubleshooting/Linux/4/test.cc new file mode 100755 index 0000000..89cf923 --- /dev/null +++ b/tvision/doc/troubleshooting/Linux/4/test.cc @@ -0,0 +1,297 @@ +/**[txh]******************************************************************** + + Copyright (c) 2003 by Salvador E. Tropea + This code is part of our Turbo Vision port and is covered by the GPL +license. + +***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef SEPARATED_HANDLE + #define SEPARATED_HANDLE 0 +#endif + +struct termios inTermiosOrig; +struct termios inTermiosNew; +struct termios outTermiosOrig; +struct termios outTermiosNew; +int oldInFlags; +int newInFlags; +FILE *fIn; +FILE *fOut; +int hIn; +int hOut; +const char *error; +int tioclinuxOK; + +int InitIn() +{ + fputs("TGKeyLinux::InitOnce\n",stderr); + hIn=fileno(stdin); + + if (!isatty(hIn)) + { + error="that's an interactive application, don't redirect stdin"; + return 1; + } + // We can't use stdin for all the operations, instead we must open it again + // using another file descriptor. + // Here is why: In order to get some keys, I saw it for ESC pressed alone, + // we must set the O_NONBLOCK attribute. + // We can do it, but the stdout file handle seems to be just a copy of the + // stdin file handle (dupped?). When you use duplicated file handles they + // share the "File Status Flags". It means that setting O_NONBLOCK will + // set O_NONBLOCK for output too. So what? well when we do that the one that + // doesn't block is Linux kernel, so if we send too much information to + // stdout, no matters if we use fflush, sometimes Linux could lose data. + // This effect seems to happend at exit, may be because owr process dies + // before Linux have a chance to process the remaining data and it closes + // the file handle. The fact is that using O_NONBLOCK sometimes we fail to + // restore the cursor position. + // Now a question remains: do I have to restore the mode? + char *ttyName=ttyname(hIn); + if (!ttyName) + { + error="failed to get the name of the current terminal used for input"; + return 3; + } + fIn=fopen(ttyName,"r+b"); + if (!fIn) + { + error="failed to open the input terminal"; + return 4; + } + hIn=fileno(fIn); + + if (tcgetattr(hIn,&inTermiosOrig)) + { + error="can't get input terminal attributes"; + return 2; + } + + memcpy(&inTermiosNew,&inTermiosOrig,sizeof(inTermiosNew)); + // Ignore breaks + inTermiosNew.c_iflag|= (IGNBRK | BRKINT); + // Disable Xon/off + inTermiosNew.c_iflag&= ~(IXOFF | IXON); + // Character oriented, no echo, no signals + inTermiosNew.c_lflag&= ~(ICANON | ECHO | ISIG); + if (tcsetattr(hIn,TCSAFLUSH,&inTermiosNew)) + { + error="can't set input terminal attributes"; + return 3; + } + // Don't block, needed to get some keys, even when the input is in character + // oriented mode. I saw it for ESC alone. + oldInFlags=fcntl(hIn,F_GETFL,0); + newInFlags=oldInFlags | O_NONBLOCK; + fcntl(hIn,F_SETFL,newInFlags); + + return 0; +} + +int InitOut() +{ + fputs("TScreenLinux::InitOnce\n",stderr); + hOut=fileno(stdout); + // SET: Original code tried to open a tty at any cost, eg: if stdout was + // redirected it tried to open stdin's tty for writing. I don't see the + // point of such an effort and in fact crashes the library, so here I just + // explain to the user how to run the application in the right way. + if (!isatty(hOut)) + { + error="that's an interactive application, don't redirect stdout. " + "If you want to collect information redirect stderr like this: " + "program 2> file"; + return 1; + } + if (SEPARATED_HANDLE) + { + fputs("Using separated handle\n",stderr); + /* Testing a reopen */ + char *ttyName=ttyname(hOut); + if (!ttyName) + { + error="failed to get the name of the current terminal used for output"; + return 3; + } + fOut=fopen(ttyName,"w+b"); + if (!fOut) + { + error="failed to open the output terminal"; + return 4; + } + int fgs=fcntl(hOut,F_GETFL,0); + fcntl(fileno(fOut),F_SETFL,fgs); + + if (tcgetattr(hOut,&outTermiosOrig)) + { + error="can't get output terminal information"; + return 2; + } + hOut=fileno(fOut); + setvbuf(fOut,NULL,_IONBF,0); + } + else + { + fOut=stdout; + + if (tcgetattr(hOut,&outTermiosOrig)) + { + error="can't get output terminal information"; + return 2; + } + } + + // Save cursor position, attributes and charset + fputs("\E7",fOut); + memcpy(&outTermiosNew,&outTermiosOrig,sizeof(outTermiosNew)); + outTermiosNew.c_oflag|=OPOST; + if (tcsetattr(hOut,TCSAFLUSH,&outTermiosNew)) + { + error="can't configure terminal mode"; + return 3; + } + + // Test the TIOCLINUX + int arg=6; + tioclinuxOK=(ioctl(hOut,TIOCLINUX,&arg)!=-1); + if (tioclinuxOK) + fputs("Linux Console IOCTL working\n",stderr); + + return 0; +} + + +int Init() +{ + // Identify the terminal, if that's linux or console go on. + char *terminal=getenv("TERM"); + if (!terminal || !(!strcmp(terminal,"console") || !strncmp(terminal,"linux",5))) + { + fputs("Not a Linux console\n",stderr); + return 1; + } + + // Initialize terminal + if (InitOut()) + { + fprintf(stderr,"Error! %s",error); + fprintf(stderr,"\r\n"); + return 2; + } + // Initialize keyboard + if (InitIn()) + { + tcsetattr(hOut,TCSAFLUSH,&outTermiosOrig); + fprintf(stderr,"Error! %s",error); + fprintf(stderr,"\r\n"); + return 3; + } + return 0; +} + +void DeInitIn() +{ + tcsetattr(hIn,TCSAFLUSH,&inTermiosOrig); +} + +void DeInitOut() +{ + // Is that a Linux bug? Sometime \E8 works, others not. + fputs("\E8",fOut); + // Ensure the last command is executed + fflush(fOut); + // Restore console mode + tcsetattr(hOut,TCSAFLUSH,&outTermiosOrig); +} + +void DeInit() +{ + DeInitOut(); + DeInitIn(); +} + +int oldCol=-1, oldFore=-1, oldBack=-1; + +void mapColor(int col) +{ + static char map[] = {0, 4, 2, 6, 1, 5, 3, 7}; + int back,fore; + + if (col==oldCol) + return; + oldCol=col; + back=(col >> 4) & 7; + fore=col & 15; + + #define SB set_a_background ? set_a_background : set_background + #define SF set_a_foreground ? set_a_foreground : set_foreground + + if (fore!=oldFore && back!=oldBack) + fprintf(fOut,"\E[%d;%d;%dm",fore>7 ? 1 : 22,30+map[fore & 7],40+map[back]); + else + { + if (fore!=oldFore) + fprintf(fOut,"\E[%d;%dm",fore>7 ? 1 : 22,30+map[fore & 7]); + else + fprintf(fOut,"\E[%dm",40+map[back]); + } + + oldFore = fore; + oldBack = back; + + #undef SB + #undef SF +} + +void SetCursorPos(unsigned x, unsigned y) +{ + fprintf(fOut,"\E[%d;%dH",y+1,x+1); +} + +int main(int argc, char *argv[]) +{ + if (argc!=2) + { + printf("Usage: %s number\n",argv[0]); + return 2; + } + int repeat=atoi(argv[1]); + if (!repeat || repeat>100) + { + printf("The number must be between 1 and 100\n"); + return 3; + } + if (Init()) + return 1; + // Exit UTF-8 mode + fputs("\e%@",fOut); + // G1 in kernel mode and selected + fputs("\e)K\xE",fOut); + unsigned i,j,k; + for (k=0; k + +/*------------------------------------------------------------------------*/ +/* */ +/* ctrlToArrow */ +/* */ +/* argument: */ +/* */ +/* keyCode - scan code to be mapped to keypad arrow code */ +/* */ +/* returns: */ +/* */ +/* scan code for arrow key corresponding to Wordstar key, */ +/* or original key code if no correspondence exists */ +/* */ +/*------------------------------------------------------------------------*/ +ushort ctrlToArrow(ushort keyCode) +{ + +static const ushort ctrlCodes[] = + { + kbCtrlS, kbCtrlD, kbCtrlE, kbCtrlX, kbCtrlA, + kbCtrlF, kbCtrlG, kbCtrlV, kbCtrlR, kbCtrlC, kbCtrlH + }; + +static const ushort arrowCodes[] = + { + kbLeft, kbRight, kbUp, kbDown, kbHome, + kbEnd, kbDel, kbIns,kbPgUp, kbPgDn, kbBack + }; + + /* The keycode contains now also the shift flags, which the + caller don't want to see */ + ushort _keyCode = keyCode & 0x7F; + + for( unsigned i = 0; i<(sizeof(ctrlCodes)/sizeof(ushort)) ; i++ ) + if( _keyCode==ctrlCodes[i] ) + return arrowCodes[i]; + /* If it was not found, return the original code */ + return keyCode; +} + +/*------------------------------------------------------------------------*/ +/* */ +/* cstrlen */ +/* */ +/* argument: */ +/* */ +/* s - pointer to 0-terminated string */ +/* */ +/* returns */ +/* */ +/* length of string, ignoring '~' characters. */ +/* */ +/* Comments: */ +/* */ +/* Used in determining the displayed length of command strings, */ +/* which use '~' to toggle between display attributes */ +/* */ +/*------------------------------------------------------------------------*/ + +int cstrlen( const char *s ) +{ + int len = 0; + while( *s != EOS ) + { + if( *s++ != '~' ) + len++; + } + return len; +} + diff --git a/tvision/dual.cc b/tvision/dual.cc new file mode 100644 index 0000000..5180a81 --- /dev/null +++ b/tvision/dual.cc @@ -0,0 +1,52 @@ +/* Copyright (C) 1996-1998 Robert H”hne, see COPYING.RH for details */ +/* This file is part of RHIDE. */ +#define Uses_TScreen +#define Uses_TEventQueue + +#include + +#ifdef TVCompf_djgpp +#include +#include +#endif + +int dual_display_supported() +{ +#ifdef TVCompf_djgpp + __dpmi_regs r; + r.x.ax = 0x1a00; + __dpmi_int(0x10,&r); + if (r.h.al != 0x1a) return 0; + if (r.h.bh == 0x01) return 1; +#endif +/* +#ifdef TVOSf_Linux + extern unsigned short *mono_mem; + return (mono_mem != NULL); +#endif +*/ + return 0; +} + +void SetDualDisplay() +{ + if (TDisplay::dual_display) return; + if (!dual_display_supported()) return; + TEventQueue::suspend(); + TScreen::suspend(); + TDisplay::dual_display = 1; + TScreen::resume(); + TEventQueue::resume(); +} + + +void SetNormalDisplay() +{ + if (!TDisplay::dual_display) return; + TEventQueue::suspend(); + TScreen::suspend(); + TDisplay::dual_display = 0; + TScreen::resume(); + TEventQueue::resume(); +} + diff --git a/tvision/examples/Makefile b/tvision/examples/Makefile new file mode 100644 index 0000000..dfe095a --- /dev/null +++ b/tvision/examples/Makefile @@ -0,0 +1,118 @@ +# Copyright (C) 2001-2007 by Salvador E. Tropea (SET), +# see copyrigh file for details +# +# This file is mostly used to clean the examples directories, but can be +# used to compile all of them or just one from this directory. +# +.PHONY: clean + +examples=demo/demo desklogo/desklogo desklogo/set-logo \ + desklogo/tv_logo dlgdsn/libtest dyntxt/dyntext \ + inplis/implis listvi/lst_view msgcls/msgcls \ + progba/test sdlg/test sdlg2/test tcombo/test \ + terminal/test tprogb/test tutorial/tvguid01 \ + tutorial/tvguid02 tutorial/tvguid03 tutorial/tvguid04 \ + tutorial/tvguid05 tutorial/tvguid06 tutorial/tvguid07 \ + tutorial/tvguid08 tutorial/tvguid09 tutorial/tvguid10 \ + tutorial/tvguid11 tutorial/tvguid12 tutorial/tvguid13 \ + tutorial/tvguid14 tutorial/tvguid15 tutorial/tvguid16 \ + tvedit/tvedit tvhc/tvhc clipboard/test fonts/test \ + helpdemo/helpdemo fonts/genraw videomode/test \ + cyrillic/linuxkoi8/test cyrillic/x11koi8/test \ + bhelp/thelp i18n/test viewers/test + +all: $(addsuffix .exe,$(examples)) + +bhelp/thelp.exe: bhelp/thelp.gpr + +clipboard/test.exe: clipboard/test.gpr + +cyrillic/linuxkoi8/test.exe: cyrillic/linuxkoi8/test.gpr + +cyrillic/x11koi8/test.exe: cyrillic/x11koi8/test.gpr + +demo/demo.exe: demo/demo.gpr + +desklogo/desklogo.exe: desklogo/desklogo.gpr + +desklogo/set-logo.exe: desklogo/set-logo.gpr + +desklogo/tv_logo.exe: desklogo/tv_logo.gpr + +dlgdsn/libtest.exe: dlgdsn/libtest.gpr + +dyntxt/dyntext.exe: dyntxt/dyntext.gpr + +fonts/test.exe: fonts/test.gpr + +fonts/genraw.exe: fonts/genraw.gpr + +helpdemo/helpdemo.exe: helpdemo/helpdemo.gpr + +i18n/test.exe: i18n/test.gpr + +inplis/implis.exe: inplis/implis.gpr + +listvi/lst_view.exe: listvi/lst_view.gpr + +msgcls/msgcls.exe: msgcls/msgcls.gpr + +progba/test.exe: progba/test.gpr + +sdlg/test.exe: sdlg/test.gpr + +sdlg2/test.exe: sdlg2/test.gpr + +tcombo/test.exe: tcombo/test.gpr + +terminal/test.exe: terminal/test.gpr + +tprogb/test.exe: tprogb/test.gpr + +tutorial/tvguid01.exe: tutorial/tvguid01.gpr + +tutorial/tvguid02.exe: tutorial/tvguid02.gpr + +tutorial/tvguid03.exe: tutorial/tvguid03.gpr + +tutorial/tvguid04.exe: tutorial/tvguid04.gpr + +tutorial/tvguid05.exe: tutorial/tvguid05.gpr + +tutorial/tvguid06.exe: tutorial/tvguid06.gpr + +tutorial/tvguid07.exe: tutorial/tvguid07.gpr + +tutorial/tvguid08.exe: tutorial/tvguid08.gpr + +tutorial/tvguid09.exe: tutorial/tvguid09.gpr + +tutorial/tvguid10.exe: tutorial/tvguid10.gpr + +tutorial/tvguid11.exe: tutorial/tvguid11.gpr + +tutorial/tvguid12.exe: tutorial/tvguid12.gpr + +tutorial/tvguid13.exe: tutorial/tvguid13.gpr + +tutorial/tvguid14.exe: tutorial/tvguid14.gpr + +tutorial/tvguid15.exe: tutorial/tvguid15.gpr + +tutorial/tvguid16.exe: tutorial/tvguid16.gpr + +tvedit/tvedit.exe: tvedit/tvedit.gpr + +tvhc/tvhc.exe: tvhc/tvhc.gpr + +videomode/test.exe: videomode/test.gpr + +viewers/test.exe: viewers/test.gpr + +%.exe: %.gpr + $(MAKE) -C $(dir $<) -f $(addsuffix .mkf,$(basename $(notdir $<))) + +clean: + @echo 'Cleaning examples.' + -@rm -f */*.o */*/*.o */*.exe */*/*.exe */*.gdt */*/*.gdt */*.bkp \ + */*/*.bkp *.bkp */*.dst */*/*.dst diff --git a/tvision/examples/bhelp/.tvrc b/tvision/examples/bhelp/.tvrc new file mode 100644 index 0000000..65c7b04 --- /dev/null +++ b/tvision/examples/bhelp/.tvrc @@ -0,0 +1,6 @@ +[TV] +{ + # This is needed because Borland files are encoded in ANSI CP 437 + AppCP=437 + Font10x20=1 +} diff --git a/tvision/examples/bhelp/bhelp.cc b/tvision/examples/bhelp/bhelp.cc new file mode 100644 index 0000000..7a5b231 --- /dev/null +++ b/tvision/examples/bhelp/bhelp.cc @@ -0,0 +1,325 @@ +/**[txh]******************************************************************** + + Copyright (c) 2002 by Jan Van Buggenhout + + Based on code: + Copyright (c) 1994 by Borland International + Modified by Sergio Sigala + Modified by Salvador E. Tropea , + Copyright (c) 1999 by Andreas F. Gorup von Besanez + + Covered by the GPL license. + + Description: + This is a class derived from THelpFile to read Borland help files. + +***************************************************************************/ + +#define Uses_ctype +#define Uses_limits +#define Uses_string +#define Uses_stdlib +#define Uses_sys_stat +#define Uses_filelength +#define Uses_TCollection +#define Uses_TStreamableClass +#define Uses_THelpFile +#define Uses_fpstream +#include +#include "bhelp.h" + +char *read0String(fpstream & s) +{ + int l; + long p = s.tellg(); + + for (l = 1; s.readByte(); l++) ; + char *buffer = new char[l]; + + s.seekg(p); + s.readBytes(buffer, l); + return buffer; +} + +// TBorlandHelpTopic + +const char *const TBorlandHelpTopic::name = "TBorlandHelpTopic"; + +TBorlandHelpTopic::TBorlandHelpTopic(fpstream & s, char *comp) +{ + char type; + unsigned short datalength, refslength; + + s >> type; + s >> datalength; + unsigned char *data = new unsigned char[datalength]; + char *text = new char[datalength * 9]; + char *curtext = text; + + s.readBytes(data, datalength); + + ushort noRefs; + + s >> type; + s >> refslength; + s >> previous; + s >> next; + s >> noRefs; + setNumCrossRefs(0); + refslength -= 6; + ushort *refs = (ushort *)(new uchar[refslength]); + ushort *curref = refs; + + s.readBytes(refs, refslength); + + for (long k = 0; k < datalength * 2; k++) + { + unsigned char Nibble; + + Nibble = (data[k / 2] >> ((k & 1) * 4)) & 0xf; + switch (Nibble) + { + + case 0: + *curtext++ = 0; + break; + + case 0xe: /* Rep */ + { + ushort RepCount; + + k++; + RepCount = ((data[k / 2] >> ((k & 1) * 4)) & 0xf) + 2; + k++; + Nibble = (data[k / 2] >> ((k & 1) * 4)) & 0xf; + if (Nibble < 0xe) + { + memset(curtext, comp[Nibble], RepCount); + curtext += RepCount; + } + else if (Nibble == 0xf) + { + k++; + Nibble = data[k / 2] >> ((k & 1) * 4); + k++; + memset(curtext, + Nibble | ((data[k / 2] >> ((k & 1) * 4)) << 4), RepCount); + curtext += RepCount; + } + break; + } + + case 0xf: /* Raw */ + k++; + Nibble = data[k / 2] >> ((k & 1) * 4); + k++; + *curtext++ = Nibble | ((data[k / 2] >> ((k & 1) * 4)) << 4); + break; + + default: + *curtext++ = comp[Nibble]; + break; + } + } + + for (char *para = text; (para < curtext) && (*para != 1); + para += strlen(para) + 1) + { + for (char *ref = strchr(para, 2); ref; ref = strchr(ref, 2)) + { + char *endref = strchr(ref + 1, 2) - 1; + int length = endref - ref; + + TCrossRef cref; + + cref.offset = ref - text + 1; + cref.length = length; + cref.ref = *curref++; + addCrossRef(cref); + + memmove(ref, ref + 1, length); + memmove(endref, endref + 2, curtext - endref); + + curtext -= 2; + } + TParagraph *paragraph = new TParagraph; + + paragraph->text = strdup(para); + paragraph->size = strlen(para) + 1; + paragraph->wrap = False; + addParagraph(paragraph); + } + free(data); + free(text); + free(refs); +} + +TStreamableClass RBorlandHelpTopic(TBorlandHelpTopic::name, + TBorlandHelpTopic::build, + __DELTA(TBorlandHelpTopic)); + +// TBorlandHelpIndex + +const char *const TBorlandHelpIndex::name = "TBorlandHelpIndex"; + +TBorlandHelpIndex::TBorlandHelpIndex(fpstream & s):THelpIndex() +{ + unsigned short length; + unsigned char *buffer; + + s >> length; + buffer = new unsigned char[length]; + + s.readBytes(buffer, length); + size = *((unsigned short *) buffer); + index = new long[size]; + + buffer += 2; + for (int k = 0; k < size * 3; k += 3) + index[k/3] = ((buffer[k + 2] & 0x80) << 24) + + (buffer[k] + (buffer[k + 1] << 8) + ((buffer[k + 2] & 0x7f) << 16)); +} + +void *TBorlandHelpIndex::read(ipstream & is) +{ + // FIXME + return 0; +} + +TStreamable *TBorlandHelpIndex::build() +{ + return new TBorlandHelpIndex(streamableInit); +} + +TStreamableClass RBorlandHelpIndex(TBorlandHelpIndex::name, + TBorlandHelpIndex::build, + __DELTA(TBorlandHelpIndex)); + +// TBorlandHelpFile + +TBorlandHelpFile::TBorlandHelpFile(fpstream & s):THelpFile(s) +{ + char *Stamp; + char FormatVersion; + + modified=False; + stream->seekg(0); + Stamp = read0String(*stream); + stream->seekg(14, CLY_IOSCur); + *stream >> FormatVersion; + stream->seekg(1, CLY_IOSCur); + + while (!stream->eof()) + { + char type; + unsigned short length; + unsigned char *buffer=NULL; + + *stream >> type; + if (type != 1) + { + *stream >> length; + buffer = (unsigned char *) malloc(length); + stream->readBytes(buffer, length); + } + switch (type) + { + case 0: /* FileHeader */ + { + ushort *o = (ushort *) buffer; + options = o[0]; + indexscreen = o[1]; + height = buffer[6]; + width = buffer[7]; + margin = buffer[8]; + break; + } + + case 1: /* ConText */ + index = new TBorlandHelpIndex(*stream); + break; + + case 2: /* Text */ + stream->seekg(-(length + 3), CLY_IOSCur); + return; + + case 3: /* KeyWord */ + stream->seekg(-(length + 3), CLY_IOSCur); + return; + + case 4: /* Index */ + { + char temp[41]; + *temp = 0; + glossaryItems = *((ushort *) buffer); + glossary = new char *[glossaryItems]; + char *g = (char *) buffer + 2; + for (int i = 0; i < glossaryItems; i++) + { + uchar lengthcode = *g++; + ushort carry = (lengthcode & 0xe0) >> 5; + ushort unique = lengthcode & 0x1f; + glossary[i] = new char[carry + unique + 3]; + strncpy(temp + carry, g, unique); + temp[carry + unique] = 0; + g += unique; + strncpy(temp + carry + unique + 1, g, 2); + g += 2; + memcpy(glossary[i], temp, carry + unique + 3); + } + break; + } + + case 5: /* Compression */ + *compressiontable = 0; + memcpy(compressiontable + 1, buffer + 2, 13); + break; + + case 6: /* IndexTags */ + break; + } + if (type != 1) + free(buffer); + } +} + +class TSearchResults : public TCollection +{ + public: + TSearchResults() : TCollection(0, 1) {}; + virtual void *readItem( ipstream& ) { return 0; }; + virtual void writeItem( void *, opstream& ) {}; +}; + +TCollection *TBorlandHelpFile::search(char *s) +{ + char *ss = strdup(s); + if (!(options & 4)) strupr(ss); + int found = 0; + int length = strlen(s); + TCollection *coll = new TSearchResults(); + for (int i = 0; i < glossaryItems; i++) + { + if (!strncmp(ss, glossary[i], length)) + { + found = 1; + coll->insert(glossary[i]); + } + else if (found) break; + } + free(ss); + return coll; +} + +THelpTopic *TBorlandHelpFile::getTopic(int i) +{ + long pos = index->position(i); + + if (pos > 0) + { + stream->seekg(pos); + return new TBorlandHelpTopic(*stream, compressiontable); + } + else + return (invalidTopic()); +} diff --git a/tvision/examples/bhelp/bhelp.h b/tvision/examples/bhelp/bhelp.h new file mode 100644 index 0000000..179eb57 --- /dev/null +++ b/tvision/examples/bhelp/bhelp.h @@ -0,0 +1,80 @@ +/**[txh]******************************************************************** + + Copyright (c) 2002 by Jan Van Buggenhout + + Based on code: + Copyright (c) 1994 by Borland International + Modified by Sergio Sigala + Modified by Salvador E. Tropea , + Copyright (c) 1999 by Andreas F. Gorup von Besanez + + Covered by the GPL license. + + Description: + This is a class derived from THelpFile to read Borland help files. + +***************************************************************************/ + +#if !defined(TBorlandHelpFile_Included) +#define TBorlandHelpFile_Included + +class TBorlandHelpTopic: public THelpTopic +{ + +public: + + TBorlandHelpTopic( fpstream & s, char * comp ); + short int previous, next; + +protected: + + virtual void *read( ipstream& ) { return 0; }; + +public: + + static const char * const name; + static TStreamable *build() { return 0; }; + +}; + +// TBorlandHelpIndex + +class TBorlandHelpIndex : public THelpIndex +{ +public: + + TBorlandHelpIndex( fpstream & ); + TBorlandHelpIndex( StreamableInit ) {}; + +protected: + + virtual void *read( ipstream& ); + +public: + + static const char * const name; + static TStreamable *build(); + +}; + +// TBorlandHelpFile + +class TBorlandHelpFile : public THelpFile +{ + +public: + + TBorlandHelpFile( fpstream & ); + TCollection *search(char *sstr); + + virtual THelpTopic *getTopic( int ); + ushort options, indexscreen; + uchar height, width, margin; + ushort glossaryItems; + char ** glossary; + char compressiontable[13]; + +}; + +#endif // Uses_TBorlandHelpFile && !TBorlandHelpFile_Included + diff --git a/tvision/examples/bhelp/rhide.env b/tvision/examples/bhelp/rhide.env new file mode 100644 index 0000000..56091d7 --- /dev/null +++ b/tvision/examples/bhelp/rhide.env @@ -0,0 +1,5 @@ +# +# This include file have rhide options for all the subprojects. +# +include ../rhide.env + diff --git a/tvision/examples/bhelp/thelp.bmk b/tvision/examples/bhelp/thelp.bmk new file mode 100644 index 0000000..23348c3 --- /dev/null +++ b/tvision/examples/bhelp/thelp.bmk @@ -0,0 +1,10 @@ +#!/usr/bin/make +# +# Copyright (c) 2003 by Salvador E. Tropea. +# Covered by the GPL license. +# +!include ../common.bmk +all: thelp.exe +!include ../../makes/common.bmk +!include thelp.umk + diff --git a/tvision/examples/bhelp/thelp.cc b/tvision/examples/bhelp/thelp.cc new file mode 100644 index 0000000..87ae036 --- /dev/null +++ b/tvision/examples/bhelp/thelp.cc @@ -0,0 +1,221 @@ +/**[txh]******************************************************************** + + Copyright (c) 1999 by Andreas F. Gorup von Besanez + Copyright (c) 2002 by Jan Van Buggenhout + Copyright (c) 2002-2003 by Salvador E. Tropea + + Covered by the GPL license. + + Description: + This program reads the help files used by Turbo C++ and Borland C++ +compilers. + +***************************************************************************/ + +#define Uses_stdlib +#define Uses_stdio +#define Uses_access +#define Uses_string +#define Uses_TKeys +#define Uses_ifpstream +#define Uses_IOS_BIN +#define Uses_TCollection +#define Uses_THelpWindow +#define Uses_TApplication +#define Uses_TDialog +#define Uses_TButton +#define Uses_TListBox +#define Uses_TPalette +#define Uses_TDeskTop +#define Uses_getopt +#define Uses_MsgBox +#include +#include "bhelp.h" + +class THelp:public TApplication +{ +public: + THelp(); + virtual TPalette& getPalette() const; + static TDeskTop *initDeskTop( TRect r ); + virtual void getEvent(TEvent& event); + virtual void run(); + static void ParseCommandLine(int argc, char *argv[]); + + static const char *fileName; +}; + +const char *THelp::fileName="tchelp.tch"; + +THelp::THelp():TProgInit(0, 0, &THelp::initDeskTop) +{ +} + +#define cpAppColor \ + "\x71\x70\x78\x74\x20\x28\x24\x17\x1F\x1A\x31\x31\x1E\x71\x1F" \ + "\x37\x3F\x3A\x13\x13\x3E\x21\x3F\x70\x7F\x7A\x13\x13\x70\x7F\x7E" \ + "\x70\x7F\x7A\x13\x13\x70\x70\x7F\x7E\x20\x2B\x2F\x78\x2E\x70\x30" \ + "\x3F\x3E\x1F\x2F\x1A\x20\x72\x31\x31\x30\x2F\x3E\x31\x13\x38\x00" \ + "\x17\x1F\x1A\x71\x71\x1E\x17\x1F\x1E\x20\x2B\x2F\x78\x2E\x10\x30" \ + "\x3F\x3E\x70\x2F\x7A\x20\x12\x31\x31\x30\x2F\x3E\x31\x13\x38\x00" \ + "\x37\x3F\x3A\x13\x13\x3E\x30\x3F\x3E\x20\x2B\x2F\x78\x2E\x30\x70" \ + "\x7F\x7E\x1F\x2F\x1A\x20\x32\x31\x71\x70\x2F\x7E\x71\x13\x78\x00" \ + "\x37\x3F\x3A\x13\x13\x30\x3E\x1E" // help colors + +TPalette& THelp::getPalette() const +{ + static TPalette helpcolor ( cpAppColor , sizeof( cpAppColor )-1 ); + return helpcolor; +} + +TDeskTop *THelp::initDeskTop( TRect r ) +{ + return new TDeskTop( r ); +} + +void THelp::getEvent(TEvent &event) +{ + if (event.what == evKeyDown) + { + switch (event.keyDown.keyCode) + { + case kbF5: + event.what = evCommand; + event.message.infoPtr = 0; + event.message.command = cmZoom; + return; + case kbCtrlF5: + event.what = evCommand; + event.message.infoPtr = 0; + event.message.command = cmResize; + return; + } + } + TApplication::getEvent(event); +} + +char *searchstring = NULL; +int maxlength = 0; +int which = 0; + +class TSearchDialog : public TDialog +{ + public: + TSearchDialog(TCollection *results) : + TWindowInit( &TSearchDialog::initFrame ), + TDialog (TRect (0, 0, maxlength + 4, results->getCount() + 6), "Select Result") + { + TRect r = getExtent(); + r.grow(-2,-2); + r.b.y -= 2; + options |= ofCentered; + TListBox *resultList = new TListBox( r, 1, 0); + resultList->newList(results); + insert(resultList); + r.a.x--; + r.a.y = r.b.y + 1; + r.b.y += 3; + insert(new TButton(r, __("~V~iew"), cmOK, bfDefault)); + setCurrent(resultList, normalSelect); + }; +}; + +void setmaxlength(void *str, void *u) +{ + int l = strlen((char *) str); + if ( l > maxlength) maxlength = l; +} + +ushort getContext(TCollection *results) +{ + char *result = (char *) results->at(which); + char *res = result + strlen(result) + 1; + return *((ushort *) res); +} + +void THelp::run() +{ + if (access(fileName,R_OK)!=0) + { + messageBox(__("File not found"), mfOKButton | mfError); + endModal(cmQuit); + return; + } + fpstream *helpStrm = new fpstream(fileName, CLY_IOSIn); + TBorlandHelpFile *helpFile = new TBorlandHelpFile(*helpStrm); + ushort start = helpFile->indexscreen; + if (searchstring && *searchstring) + { + TCollection *results = helpFile->search(searchstring); + switch (results->getCount()) + { + case 0: + break; + case 1: + start = getContext(results); + break; + default: + { + results->forEach(setmaxlength, 0); + TDialog *SD = new TSearchDialog(results); + if (execView(SD) == cmOK) + { + char* rec = (char *) malloc(SD->dataSize()); + SD->getData(rec); + which = *((int *) (rec + 4)); + start = getContext(results); + } + break; + } + } + } + THelpWindow *helpWindow = new THelpWindow(helpFile, start); + execView(validView(helpWindow)); +} + +static +struct CLY_option longopts[] = +{ + { "file", 0, 0, 'f' }, + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +void THelp::ParseCommandLine(int argc, char *argv[]) +{ + int optc; + + while ((optc=CLY_getopt_long(argc,argv,"f:h",longopts,0))!=EOF) + { + switch (optc) + { + case 'f': + fileName=CLY_optarg; + break; + case 'h': + default: + printf("Borland's Help file viewer\n"); + printf("Copyright (c) 1999 by Andreas F. Gorup von Besanez \n"); + printf("Copyright (c) 2002 by Jan Van Buggenhout \n"); + printf("Copyright (c) 2002-2003 by Salvador E. Tropea \n"); + printf("This program is covered by the GPL license.\n"); + printf("\n\n"); + printf("%s [--file Name] Text_to_search\n",argv[0]); + printf("--file Name : Name of the help file\n"); + printf("--help : This text\n"); + exit(1); + } + } +} + +int main(int argc, char ** argv) +{ + THelp::ParseCommandLine(argc,argv); + THelp app; + if (argc == 2) + searchstring = argv[1]; + + app.run(); + app.shutDown(); + return 0; +} diff --git a/tvision/examples/bhelp/thelp.gpr b/tvision/examples/bhelp/thelp.gpr new file mode 100644 index 0000000..9f26f22 Binary files /dev/null and b/tvision/examples/bhelp/thelp.gpr differ diff --git a/tvision/examples/bhelp/thelp.mkf b/tvision/examples/bhelp/thelp.mkf new file mode 100644 index 0000000..6febc10 --- /dev/null +++ b/tvision/examples/bhelp/thelp.mkf @@ -0,0 +1,11 @@ +#!/usr/bin/make +# +# Copyright (c) 2003-2004 by Salvador E. Tropea. +# Covered by the GPL license. +# +vpath_src= +vpath_obj=. +INCLUDE_DIRS=../../include +COMMON_IMK=../../makes/common.imk +include $(COMMON_IMK) +include thelp$(ExIMK) diff --git a/tvision/examples/bhelp/thelp.umk b/tvision/examples/bhelp/thelp.umk new file mode 100644 index 0000000..5d5ac40 --- /dev/null +++ b/tvision/examples/bhelp/thelp.umk @@ -0,0 +1,22 @@ +#!/usr/bin/make +# Automatically generated from RHIDE projects, don't edit +# + +OBJFILES=\ + ./bhelp$(ExOBJ) \ + ./thelp$(ExOBJ) + +LIBRARIES= + +thelp$(ExEXE):: \ + ./bhelp$(ExOBJ) \ + ./thelp$(ExOBJ) \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_LINK) + +./bhelp$(ExOBJ):: bhelp.cc + $(RHIDE_COMPILE_CC) + +./thelp$(ExOBJ):: thelp.cc + $(RHIDE_COMPILE_CC) + diff --git a/tvision/examples/clipboard/rhide.env b/tvision/examples/clipboard/rhide.env new file mode 100644 index 0000000..56091d7 --- /dev/null +++ b/tvision/examples/clipboard/rhide.env @@ -0,0 +1,5 @@ +# +# This include file have rhide options for all the subprojects. +# +include ../rhide.env + diff --git a/tvision/examples/clipboard/test.bmk b/tvision/examples/clipboard/test.bmk new file mode 100644 index 0000000..7d27d57 --- /dev/null +++ b/tvision/examples/clipboard/test.bmk @@ -0,0 +1,10 @@ +#!/usr/bin/make +# +# Copyright (c) 2003 by Salvador E. Tropea. +# Covered by the GPL license. +# +!include ../common.bmk +all: test.exe +!include ../../makes/common.bmk +!include test.umk + diff --git a/tvision/examples/clipboard/test.cc b/tvision/examples/clipboard/test.cc new file mode 100644 index 0000000..39b9afd --- /dev/null +++ b/tvision/examples/clipboard/test.cc @@ -0,0 +1,174 @@ +/**[txh]******************************************************************** + + Copyright (c) 2002 by Salvador E. Tropea + This code is Public Domain and you can use it for any purpose. Note that +when you link to another libraries, obviously needed, the code can (and +currently will) be affected by the libraries license. + Currently my TV port is GPL so this code becomes GPL, but if you link +with another Turbo Vision port or the library changes license things are +different. + + Description: + This examples shows how to use the OS independent clipboard class. + +***************************************************************************/ + +#define Uses_stdio +#define Uses_string +#define Uses_TProgram +#define Uses_TApplication +#define Uses_TRect +#define Uses_TMenuBar +#define Uses_TSubMenu +#define Uses_TMenuItem +#define Uses_TStatusLine +#define Uses_TStatusItem +#define Uses_TStatusDef +#define Uses_TVOSClipboard +#define Uses_MsgBox +#define Uses_TKeys +#define Uses_TScreen + +#include + +const int cmTestCopy=100; +const int cmTestPaste=101; +const int cmTestCopy2=102; +const int cmTestPaste2=103; + +class TMyApp : public TApplication +{ +public: + TMyApp(); + static TStatusLine *initStatusLine(TRect r); + static TMenuBar *initMenuBar(TRect r); + virtual void handleEvent(TEvent& event); + void testCopy(int clip); + void testPaste(int clip); +}; + + +TMyApp::TMyApp() : + TProgInit(&TMyApp::initStatusLine,&TMyApp::initMenuBar,&TMyApp::initDeskTop) +{ +} + +void TMyApp::handleEvent(TEvent& event) +{ + TApplication::handleEvent(event); + if (event.what==evCommand) + { + switch (event.message.command) + { + case cmTestCopy: + testCopy(0); + break; + + case cmTestPaste: + testPaste(0); + break; + + case cmTestCopy2: + testCopy(1); + break; + + case cmTestPaste2: + testPaste(1); + break; + } + clearEvent(event); + } +} + +TMenuBar *TMyApp::initMenuBar(TRect r) +{ + r.b.y=r.a.y+1; + return new TMenuBar(r, + *new TSubMenu("~D~emo",kbAltD) + + *new TMenuItem("Test ~c~opy",cmTestCopy,kbNoKey,hcNoContext,"" )+ + *new TMenuItem("Test ~p~aste",cmTestPaste,kbNoKey,hcNoContext,"" )+ + *new TMenuItem("Test ~c~opy secondary",cmTestCopy2,kbNoKey,hcNoContext,"" )+ + *new TMenuItem("Test ~p~aste secondary",cmTestPaste2,kbNoKey,hcNoContext,"" )+ + *new TMenuItem("E~x~it",cmQuit,kbNoKey,hcNoContext,"Alt-X") + ); +} + +TStatusLine *TMyApp::initStatusLine(TRect r) +{ + r.a.y=r.b.y-1; + return new TStatusLine(r, + *new TStatusDef(0,0xFFFF)+ + *new TStatusItem(0,kbF10,cmMenu) + + *new TStatusItem("~Alt-X~ Exit",kbAltX,cmQuit) + ); +} + +const char *aMessage="Turbo Vision Clipboard demo message: Hi!"; + +void TMyApp::testCopy(int clip) +{ + if (!TVOSClipboard::isAvailable()) + { + messageBox("Sorry but none OS specific clipboard is available",mfError | mfOKButton); + return; + } + if (clip>=TVOSClipboard::isAvailable()) + { + messageBox("Sorry but this OS doesn't have such a clipboard",mfError | mfOKButton); + return; + } + int res=TVOSClipboard::copy(clip,aMessage,strlen(aMessage)); + if (!res) + { + messageBox(mfError | mfOKButton,"Error copying to clipboard: %s", + TVOSClipboard::getError()); + return; + } + messageBox(mfInformation | mfOKButton, + "Clipboard name: %s, a message was copied successfuly", + TVOSClipboard::getName()); +} + +void TMyApp::testPaste(int clip) +{ + if (!TVOSClipboard::isAvailable()) + { + messageBox("Sorry but none OS specific clipboard is available",mfError | mfOKButton); + return; + } + if (clip>=TVOSClipboard::isAvailable()) + { + messageBox("Sorry but this OS doesn't have such a clipboard",mfError | mfOKButton); + return; + } + unsigned length; + char *result=TVOSClipboard::paste(clip,length); + if (!result) + { + messageBox(mfError | mfOKButton,"Error pasting from clipboard: %s", + TVOSClipboard::getError()); + return; + } + if (length>80) + { + result[80]=0; + messageBox(mfInformation | mfOKButton,"First 80 characters from clipboard: %s",result); + } + else + messageBox(mfInformation | mfOKButton,"Content of the clipboard: %s",result); +} + +int main(int argc, char *argv[], char **envir) +{ + TDisplay::setArgv(argc,argv,envir); + TMyApp myApp; + const char *title=TScreen::getWindowTitle(); + TScreen::setWindowTitle("Turbo Vision Demo Program"); + myApp.run(); + if (title) + { + TScreen::setWindowTitle(title); + delete[] title; + } + return 0; +} diff --git a/tvision/examples/clipboard/test.gpr b/tvision/examples/clipboard/test.gpr new file mode 100644 index 0000000..e0f3cd8 Binary files /dev/null and b/tvision/examples/clipboard/test.gpr differ diff --git a/tvision/examples/clipboard/test.mkf b/tvision/examples/clipboard/test.mkf new file mode 100644 index 0000000..de53dab --- /dev/null +++ b/tvision/examples/clipboard/test.mkf @@ -0,0 +1,11 @@ +#!/usr/bin/make +# +# Copyright (c) 2003-2004 by Salvador E. Tropea. +# Covered by the GPL license. +# +vpath_src= +vpath_obj=. +INCLUDE_DIRS=../../include +COMMON_IMK=../../makes/common.imk +include $(COMMON_IMK) +include test$(ExIMK) diff --git a/tvision/examples/clipboard/test.umk b/tvision/examples/clipboard/test.umk new file mode 100644 index 0000000..ce3bdf8 --- /dev/null +++ b/tvision/examples/clipboard/test.umk @@ -0,0 +1,17 @@ +#!/usr/bin/make +# Automatically generated from RHIDE projects, don't edit +# + +OBJFILES=\ + ./test$(ExOBJ) + +LIBRARIES= + +test$(ExEXE):: \ + ./test$(ExOBJ) \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_LINK) + +./test$(ExOBJ):: test.cc + $(RHIDE_COMPILE_CC) + diff --git a/tvision/examples/common.bmk b/tvision/examples/common.bmk new file mode 100644 index 0000000..e93dfc3 --- /dev/null +++ b/tvision/examples/common.bmk @@ -0,0 +1,12 @@ +#!/usr/bin/make +# +# Copyright (c) 2003 by Salvador E. Tropea. +# Covered by the GPL license. +# +SRCDIRS=. +INCLUDE_DIRS=-I../../winnt/include -I../../include +RHIDE_LIBS=../../makes/librhtv.lib +CONFIG_PATH=../../makes +.cpp.obj: + +.cpp.exe: diff --git a/tvision/examples/cyrillic/linuxkoi8/README b/tvision/examples/cyrillic/linuxkoi8/README new file mode 100644 index 0000000..7d55d24 --- /dev/null +++ b/tvision/examples/cyrillic/linuxkoi8/README @@ -0,0 +1,43 @@ +This is a small test program for the KOI8-R support on Linux consoles. +This test needs full access to the console to work properly. It means: run +the program from the shell, don't use midnight commander nor screen, nor +other application in the middle. Also ensure the user you use can write to +/dev/vcsa* devices. I didn't test it using frame buffer. It won't work from +an X console, nor in native X mode. Just pure console access, if in doubt try +it as root. + + +How to run the test? + +1) Compile it using "make -f test.mak" as with other examples. +2) Load a KOI8-R font and a russian keyboard map. The setkoi8.sh script is +what I use for it. If you use KOI8-R in your machine you probably won't need +it at all. +3) Run the test "./test.exe". +4) Do the testings (screen and keyboard tests). +5) Go back to your original encodings. I use setlat1.sh for this. + +What can be tested? + + The first thing to test is the detection of the encoding. The background +should look as a regular TV background and the file menu entry should show +the russian equivalent for file. Note I know nothing about russian, a user +provided the traslation so I trust this is the correct one ;-). According to +the traslitaration table of my dictionary this is "fail", the pronunciation +of the english word file. + The second thing to test is the keyboard. If you know how ru1 map works you +can skeep the following explanation. + The ru1 key map uses the right alt key to switch between two modes: +cyrillic and latin. The key is a toggle key. To test it just press the right +alt, release it and then press the A key, you should get the cyrillic letter +whose translitaration is F (looks like a greek phi). Pressing the right alt +again you'll go back to the latin mode, needed to enter command line commands +;-) + Now you should test the "File" menu. Press Alt+a and you'll get the menu. +Then test the same but in the cyrillic mode. + +Note: The lat1-16.psf.gz font included here is a real latin 1 font, not the +damaged one included in a lot of console-tools packages. Debian Potato and +Woody have broken lat1-* fonts, they are in fact copies of lat1u-* fonts. + +SET diff --git a/tvision/examples/cyrillic/linuxkoi8/koi8-r.acm.gz b/tvision/examples/cyrillic/linuxkoi8/koi8-r.acm.gz new file mode 100644 index 0000000..96884df Binary files /dev/null and b/tvision/examples/cyrillic/linuxkoi8/koi8-r.acm.gz differ diff --git a/tvision/examples/cyrillic/linuxkoi8/koi8-r.psf.gz b/tvision/examples/cyrillic/linuxkoi8/koi8-r.psf.gz new file mode 100644 index 0000000..be511d7 Binary files /dev/null and b/tvision/examples/cyrillic/linuxkoi8/koi8-r.psf.gz differ diff --git a/tvision/examples/cyrillic/linuxkoi8/lat1-16.psf.gz b/tvision/examples/cyrillic/linuxkoi8/lat1-16.psf.gz new file mode 100644 index 0000000..0308fcc Binary files /dev/null and b/tvision/examples/cyrillic/linuxkoi8/lat1-16.psf.gz differ diff --git a/tvision/examples/cyrillic/linuxkoi8/rhide.env b/tvision/examples/cyrillic/linuxkoi8/rhide.env new file mode 100644 index 0000000..5c9ddae --- /dev/null +++ b/tvision/examples/cyrillic/linuxkoi8/rhide.env @@ -0,0 +1,5 @@ +# +# This include file have rhide options for all the subprojects. +# +include ../../rhide.env + diff --git a/tvision/examples/cyrillic/linuxkoi8/ru1.kmap.gz b/tvision/examples/cyrillic/linuxkoi8/ru1.kmap.gz new file mode 100644 index 0000000..bd0040a Binary files /dev/null and b/tvision/examples/cyrillic/linuxkoi8/ru1.kmap.gz differ diff --git a/tvision/examples/cyrillic/linuxkoi8/setkoi8.sh b/tvision/examples/cyrillic/linuxkoi8/setkoi8.sh new file mode 100755 index 0000000..9b8683c --- /dev/null +++ b/tvision/examples/cyrillic/linuxkoi8/setkoi8.sh @@ -0,0 +1,16 @@ +#!/bin/sh +# +# This script sets a russian configuration. +# Is customized for my personal needs and is only an example. +# +# Load a KOI8-R font. It contains a fake SFM. +# +consolechars -f koi8-r.psf.gz +# +# Load a KOI8-R map. That's a fake ACM. +# +consolechars -m koi8-r.acm.gz +# +# Load a russian keyboard map. +# +loadkeys ru1.kmap.gz diff --git a/tvision/examples/cyrillic/linuxkoi8/setlat1.sh b/tvision/examples/cyrillic/linuxkoi8/setlat1.sh new file mode 100755 index 0000000..51f588a --- /dev/null +++ b/tvision/examples/cyrillic/linuxkoi8/setlat1.sh @@ -0,0 +1,17 @@ +#!/bin/sh +# +# This script restores the configuration you use. +# Is customized for my personal needs and is only an example. +# +# +# I use ISO-8859-1 fonts: +# +consolechars -f lat1-16.psf.gz +# +# And I encode my documents in ISO-8859-1, so the map is trivial: +# +consolechars -m trivial.acm +# +# In Debian 3.0 Woody the boot time keymap is here: +# +loadkeys /etc/console/boottime.kmap.gz diff --git a/tvision/examples/cyrillic/linuxkoi8/test.cc b/tvision/examples/cyrillic/linuxkoi8/test.cc new file mode 100644 index 0000000..8f0e488 --- /dev/null +++ b/tvision/examples/cyrillic/linuxkoi8/test.cc @@ -0,0 +1,54 @@ +#define Uses_TApplication +#define Uses_TKeys +#define Uses_TRect +#define Uses_TMenuBar +#define Uses_TSubMenu +#define Uses_TMenuItem +#define Uses_TStatusLine +#define Uses_TStatusItem +#define Uses_TStatusDef +#define Uses_TDeskTop +#define Uses_TVCodePage +#include + +class TMyApp : public TApplication +{ +public: + TMyApp(); + static TMenuBar *initMenuBar(TRect r); +}; + +TMyApp::TMyApp() : + TProgInit(&TMyApp::initStatusLine, + &TMyApp::initMenuBar, + &TMyApp::initDeskTop + ) +{ +} + +TMenuBar *TMyApp::initMenuBar( TRect r ) +{ + r.b.y=r.a.y+1; + return new TMenuBar( r, + //*new TSubMenu("~F~ile",kbAltF)+ + *new TSubMenu("~æ~ÁÊÌ",0)+ // KOI8 test + *new TMenuItem("~O~pen",200,kbF3,hcNoContext,"F3")+ + *new TMenuItem("~N~ew", 200,kbF4,hcNoContext,"F4")+ + newLine()+ + *new TMenuItem("E~x~it",cmQuit,kbAltX,hcNoContext,"Alt-X")+ + *new TSubMenu("~W~indow", kbAltW )+ + *new TMenuItem("~N~ext",cmNext,kbF6,hcNoContext,"F6")+ + *new TMenuItem("~Z~oom",cmZoom,kbF5,hcNoContext,"F5") + ); +} + +int main() +{ + TMyApp myApp; + // Currently autodetection is broken, so I'm forcing it until I find a solution + //TVCodePage::SetCodePage(TVCodePage::KOI8r); + myApp.redraw(); + + myApp.run(); + return 0; +} diff --git a/tvision/examples/cyrillic/linuxkoi8/test.gpr b/tvision/examples/cyrillic/linuxkoi8/test.gpr new file mode 100644 index 0000000..e0f3cd8 Binary files /dev/null and b/tvision/examples/cyrillic/linuxkoi8/test.gpr differ diff --git a/tvision/examples/cyrillic/linuxkoi8/test.mkf b/tvision/examples/cyrillic/linuxkoi8/test.mkf new file mode 100644 index 0000000..1a66a2f --- /dev/null +++ b/tvision/examples/cyrillic/linuxkoi8/test.mkf @@ -0,0 +1,11 @@ +#!/usr/bin/make +# +# Copyright (c) 2003-2004 by Salvador E. Tropea. +# Covered by the GPL license. +# +vpath_src= +vpath_obj=. +INCLUDE_DIRS=../../../include +COMMON_IMK=../../../makes/common.imk +include $(COMMON_IMK) +include test$(ExIMK) diff --git a/tvision/examples/cyrillic/linuxkoi8/test.umk b/tvision/examples/cyrillic/linuxkoi8/test.umk new file mode 100644 index 0000000..ce3bdf8 --- /dev/null +++ b/tvision/examples/cyrillic/linuxkoi8/test.umk @@ -0,0 +1,17 @@ +#!/usr/bin/make +# Automatically generated from RHIDE projects, don't edit +# + +OBJFILES=\ + ./test$(ExOBJ) + +LIBRARIES= + +test$(ExEXE):: \ + ./test$(ExOBJ) \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_LINK) + +./test$(ExOBJ):: test.cc + $(RHIDE_COMPILE_CC) + diff --git a/tvision/examples/cyrillic/linuxkoi8/trivial.acm b/tvision/examples/cyrillic/linuxkoi8/trivial.acm new file mode 100644 index 0000000..95d8e63 --- /dev/null +++ b/tvision/examples/cyrillic/linuxkoi8/trivial.acm @@ -0,0 +1,129 @@ +# Internal value Output character +0x80 0x80 +0x81 0x81 +0x82 0x82 +0x83 0x83 +0x84 0x84 +0x85 0x85 +0x86 0x86 +0x87 0x87 +0x88 0x88 +0x89 0x89 +0x8A 0x8A +0x8B 0x8B +0x8C 0x8C +0x8D 0x8D +0x8E 0x8E +0x8F 0x8F +0x90 0x90 +0x91 0x91 +0x92 0x92 +0x93 0x93 +0x94 0x94 +0x95 0x95 +0x96 0x96 +0x97 0x97 +0x98 0x98 +0x99 0x99 +0x9A 0x9A +0x9B 0x9B +0x9C 0x9C +0x9D 0x9D +0x9E 0x9E +0x9F 0x9F +0xA0 0xA0 +0xA1 0xA1 +0xA2 0xA2 +0xA3 0xA3 +0xA4 0xA4 +0xA5 0xA5 +0xA6 0xA6 +0xA7 0xA7 +0xA8 0xA8 +0xA9 0xA9 +0xAA 0xAA +0xAB 0xAB +0xAC 0xAC +0xAD 0xAD +0xAE 0xAE +0xAF 0xAF +0xB0 0xB0 +0xB1 0xB1 +0xB2 0xB2 +0xB3 0xB3 +0xB4 0xB4 +0xB5 0xB5 +0xB6 0xB6 +0xB7 0xB7 +0xB8 0xB8 +0xB9 0xB9 +0xBA 0xBA +0xBB 0xBB +0xBC 0xBC +0xBD 0xBD +0xBE 0xBE +0xBF 0xBF +0xC0 0xC0 +0xC1 0xC1 +0xC2 0xC2 +0xC3 0xC3 +0xC4 0xC4 +0xC5 0xC5 +0xC6 0xC6 +0xC7 0xC7 +0xC8 0xC8 +0xC9 0xC9 +0xCA 0xCA +0xCB 0xCB +0xCC 0xCC +0xCD 0xCD +0xCE 0xCE +0xCF 0xCF +0xD0 0xD0 +0xD1 0xD1 +0xD2 0xD2 +0xD3 0xD3 +0xD4 0xD4 +0xD5 0xD5 +0xD6 0xD6 +0xD7 0xD7 +0xD8 0xD8 +0xD9 0xD9 +0xDA 0xDA +0xDB 0xDB +0xDC 0xDC +0xDD 0xDD +0xDE 0xDE +0xDF 0xDF +0xE0 0xE0 +0xE1 0xE1 +0xE2 0xE2 +0xE3 0xE3 +0xE4 0xE4 +0xE5 0xE5 +0xE6 0xE6 +0xE7 0xE7 +0xE8 0xE8 +0xE9 0xE9 +0xEA 0xEA +0xEB 0xEB +0xEC 0xEC +0xED 0xED +0xEE 0xEE +0xEF 0xEF +0xF0 0xF0 +0xF1 0xF1 +0xF2 0xF2 +0xF3 0xF3 +0xF4 0xF4 +0xF5 0xF5 +0xF6 0xF6 +0xF7 0xF7 +0xF8 0xF8 +0xF9 0xF9 +0xFA 0xFA +0xFB 0xFB +0xFC 0xFC +0xFD 0xFD +0xFE 0xFE +0xFF 0xFF diff --git a/tvision/examples/cyrillic/x11koi8/rhide.env b/tvision/examples/cyrillic/x11koi8/rhide.env new file mode 100644 index 0000000..5c9ddae --- /dev/null +++ b/tvision/examples/cyrillic/x11koi8/rhide.env @@ -0,0 +1,5 @@ +# +# This include file have rhide options for all the subprojects. +# +include ../../rhide.env + diff --git a/tvision/examples/cyrillic/x11koi8/test.cc b/tvision/examples/cyrillic/x11koi8/test.cc new file mode 100644 index 0000000..0a17119 --- /dev/null +++ b/tvision/examples/cyrillic/x11koi8/test.cc @@ -0,0 +1,110 @@ +/**[txh]******************************************************************** + + Copyright (c) 2002 by Salvador E. Tropea + This code is Public Domain and you can use it for any purpose. Note that +when you link to another libraries, obviously needed, the code can (and +currently will) be affected by the libraries license. + Currently my TV port is GPL so this code becomes GPL, but if you link +with another Turbo Vision port or the library changes license things are +different. + + Description: + This examples shows how to load and use a KOI-8r font when running on the +X11 server. + Note this example also works for the Linux console and doesn't need KOI8r +fonts loaded in your system. + +***************************************************************************/ + +#define Uses_TApplication +#define Uses_TKeys +#define Uses_TRect +#define Uses_TMenuBar +#define Uses_TSubMenu +#define Uses_TMenuItem +#define Uses_TStatusLine +#define Uses_TStatusItem +#define Uses_TStatusDef +#define Uses_TDeskTop +#define Uses_TVCodePage +#define Uses_TVFontCollection +#define Uses_TScreen +#define Uses_TVConfigFile +#include + +class TMyApp : public TApplication +{ +public: + TMyApp(); + static TMenuBar *initMenuBar(TRect r); + static TVFontCollection *fonts; + static TScreenFont256 *fontsCallBack(int which, unsigned w, unsigned height); +}; + +TVFontCollection *TMyApp::fonts=NULL; + +TMyApp::TMyApp() : + TProgInit(&TMyApp::initStatusLine, + &TMyApp::initMenuBar, + &TMyApp::initDeskTop + ) +{ +} + +/**[txh]******************************************************************** + + Description: + This is the magic routine, is called each time a font is needed. We have +to return the requested font or NULL if not available. + +***************************************************************************/ + +TScreenFont256 *TMyApp::fontsCallBack(int which, unsigned width, unsigned height) +{ + if (!fonts) return NULL; // Check we successfully loaded the font + if (which) return NULL; // Just the primary + if (width!=8 || height!=16) return NULL; // Only 8x16 + uchar *data=fonts->GetFont(width,height); + if (!data) return NULL; + TScreenFont256 *f=new TScreenFont256; + f->w=width; + f->h=height; + f->data=data; + + return f; +} + +TMenuBar *TMyApp::initMenuBar(TRect r) +{ + r.b.y=r.a.y+1; + return new TMenuBar( r, + //*new TSubMenu("~F~ile",kbAltF)+ + *new TSubMenu("~æ~ÁÊÌ",0)+ // KOI8 test + *new TMenuItem("~O~pen",200,kbF3,hcNoContext,"F3")+ + *new TMenuItem("~N~ew", 200,kbF4,hcNoContext,"F4")+ + newLine()+ + *new TMenuItem("E~x~it",cmQuit,kbAltX,hcNoContext,"Alt-X")+ + *new TSubMenu("~W~indow", kbAltW )+ + *new TMenuItem("~N~ext",cmNext,kbF6,hcNoContext,"F6")+ + *new TMenuItem("~Z~oom",cmZoom,kbF5,hcNoContext,"F5") + ); +} + +int main() +{ + // Load a font we know supports cyrillics + TMyApp::fonts=new TVFontCollection("../../fonts/ocr.sft",TVCodePage::KOI8r); + // Setup our call back to provide the needed fonts + TScreen::setFontRequestCallBack(TMyApp::fontsCallBack); + // Now indicate to TV we want to use KOI8r for any driver. + // This can be achieved indicating settings in a configuration file or like + // this: + TProgInit::config=new TVMainConfigFile(); + TVMainConfigFile::Add(NULL,"AppCP",TVCodePage::KOI8r); + TVMainConfigFile::Add(NULL,"ScrCP",TVCodePage::KOI8r); + TVMainConfigFile::Add(NULL,"InpCP",TVCodePage::KOI8r); + + TMyApp myApp; + myApp.run(); + return 0; +} diff --git a/tvision/examples/cyrillic/x11koi8/test.gpr b/tvision/examples/cyrillic/x11koi8/test.gpr new file mode 100644 index 0000000..e0f3cd8 Binary files /dev/null and b/tvision/examples/cyrillic/x11koi8/test.gpr differ diff --git a/tvision/examples/cyrillic/x11koi8/test.mkf b/tvision/examples/cyrillic/x11koi8/test.mkf new file mode 100644 index 0000000..1a66a2f --- /dev/null +++ b/tvision/examples/cyrillic/x11koi8/test.mkf @@ -0,0 +1,11 @@ +#!/usr/bin/make +# +# Copyright (c) 2003-2004 by Salvador E. Tropea. +# Covered by the GPL license. +# +vpath_src= +vpath_obj=. +INCLUDE_DIRS=../../../include +COMMON_IMK=../../../makes/common.imk +include $(COMMON_IMK) +include test$(ExIMK) diff --git a/tvision/examples/cyrillic/x11koi8/test.umk b/tvision/examples/cyrillic/x11koi8/test.umk new file mode 100644 index 0000000..ce3bdf8 --- /dev/null +++ b/tvision/examples/cyrillic/x11koi8/test.umk @@ -0,0 +1,17 @@ +#!/usr/bin/make +# Automatically generated from RHIDE projects, don't edit +# + +OBJFILES=\ + ./test$(ExOBJ) + +LIBRARIES= + +test$(ExEXE):: \ + ./test$(ExOBJ) \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_LINK) + +./test$(ExOBJ):: test.cc + $(RHIDE_COMPILE_CC) + diff --git a/tvision/examples/demo/ascii.cc b/tvision/examples/demo/ascii.cc new file mode 100644 index 0000000..49e1c1f --- /dev/null +++ b/tvision/examples/demo/ascii.cc @@ -0,0 +1,306 @@ +/*----------------------------------------------------------*/ +/* */ +/* Ascii.cpp: Member functions of following classes: */ +/* TTable */ +/* TReport */ +/* TAsciiChart */ +/* */ +/*----------------------------------------------------------*/ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + */ +/* + * Modified by Sergio Sigala + * Modified by Salvador E. Tropea to compile for 64 bits architectures. + */ + +// SET: moved the standard headers before tv.h +#define Uses_string +#include +#include +//#include SET: These two are only to bloat the code. +#include // SET: printf does the job much simplier + +#define Uses_TRect +#define Uses_TEvent +#define Uses_TKeys +#define Uses_TDrawBuffer +#define Uses_TStreamableClass +#define Uses_TStreamable +#define Uses_TView +#define Uses_TWindow +#include +__link( RView ) +__link( RWindow ) + +#include "ascii.h" + + +// +// TTable functions +// + +const char * const TTable::name = "TTable"; + + +void TTable::write( opstream& os ) +{ + TView::write( os ); +} + + +void *TTable::read( ipstream& is ) +{ + TView::read( is ); + return this; +} + + +TStreamable *TTable::build() +{ + return new TTable( streamableInit ); +} + + +TStreamableClass RTable( TTable::name, + TTable::build, + __DELTA(TTable) + ); + + +TTable::TTable(TRect& r) : + TView( r ) +{ + eventMask |= evKeyboard; +} + + +void TTable::draw() +{ + TDrawBuffer buf; + char color = getColor(6); + + for(ushort y = 0; y <= size.y-1; y++) + { + buf.moveChar(0, ' ', color, (short)size.x ); + for(ushort x = 0; x <= size.x-1; x++) + buf.moveChar(x, (ushort)(32*y+x), color, (ushort)1 ); + writeLine(0, y, (short)size.x, (ushort)1, buf); + } + showCursor(); +} + +// +// cmCharFocused is a offset value (basically the ascii code of the +// current selected character) thus should be added, not or'ed, to +// cmAsciiTableCmdBase. +// + +void TTable::charFocused() +{ + message(owner, evBroadcast, cmAsciiTableCmdBase + cmCharFocused, + (void *)(long)(cursor.x + 32 * cursor.y)); +} + + +void TTable::handleEvent(TEvent& event) +{ + TView::handleEvent(event); + + if (event.what == evMouseDown) + { + do + { + if(mouseInView(event.mouse.where)) + { + TPoint spot = makeLocal(event.mouse.where); + setCursor(spot.x, spot.y); + charFocused(); + } + } while (mouseEvent(event, evMouseMove)); + clearEvent(event); + } + else + { + if (event.what == evKeyboard) + { + switch (event.keyDown.keyCode) + { + case kbHome: + setCursor(0,0); + break; + case kbEnd: + setCursor(size.x-1, size.y-1); + break; + case kbUp: + if (cursor.y > 0) + setCursor(cursor.x, cursor.y-1); + break; + case kbDown: + if (cursor.y < size.y-1) + setCursor(cursor.x, cursor.y+1); + break; + case kbLeft: + if (cursor.x > 0) + setCursor(cursor.x-1, cursor.y); + break; + case kbRight: + if (cursor.x < size.x-1) + setCursor(cursor.x+1, cursor.y); + break; + default: + setCursor(event.keyDown.charScan.charCode % 32, + event.keyDown.charScan.charCode / 32); + break; + } + charFocused(); + clearEvent(event); + } + } +} + + +// +// TReport functions +// + +const char * const TReport::name = "TReport"; + + +void TReport::write( opstream& os ) +{ + TView::write( os ); + os << asciiChar; +} + + +void *TReport::read( ipstream& is ) +{ + TView::read( is ); + is >> asciiChar; + return this; +} + + +TStreamable *TReport::build() +{ + return new TReport( streamableInit ); +} + + +TStreamableClass RReport( TReport::name, + TReport::build, + __DELTA(TReport) + ); + + +TReport::TReport(TRect& r) : + TView(r) +{ + asciiChar = 0; +} + + +void TReport::draw() +{ + TDrawBuffer buf; + char color = getColor(6); + char str[80]; + + sprintf(str, "%s%c%s%3d%s%2X ", //wsz: to print 32 characters + " Char: ", (asciiChar==0)?(char)0x20:(char)asciiChar, + " Decimal: ", (int)asciiChar, + " Hex: ", (int)asciiChar); //wsz: :-) + /* SET: from Robert's port + statusStr + << " Char: " << (char ) ((asciiChar == 0) ? 0x20 : asciiChar) + << " Decimal: " << setw(3) << (int) asciiChar + << " Hex " << hex << setiosflags(ios::uppercase) + << setw(2) << (int) asciiChar << " " << ends;*/ + + buf.moveStr(0, str, color); + writeLine(0, 0, 32, 1, buf); +} + + +void TReport::handleEvent(TEvent& event) +{ + TView::handleEvent(event); + if (event.what == evBroadcast) + { + if (event.message.command == cmAsciiTableCmdBase + cmCharFocused) + { + asciiChar = event.message.infoLong; + drawView(); + } + } +} + + +// +// TAsciiChart functions +// + +const char * const TAsciiChart::name = "TAsciiChart"; + + +void TAsciiChart::write( opstream& os ) +{ + TWindow::write( os ); +} + + +void *TAsciiChart::read( ipstream& is ) +{ + TWindow::read( is ); + return this; +} + + +TStreamable *TAsciiChart::build() +{ + return new TAsciiChart( streamableInit ); +} + + +TStreamableClass RAsciiChart( TAsciiChart::name, + TAsciiChart::build, + __DELTA(TAsciiChart) + ); + + +TAsciiChart::TAsciiChart() : + TWindowInit( &TAsciiChart::initFrame ) + , TWindow(TRect(0, 0, 34, 12), "ASCII Chart", wnNoNumber) +{ + TView *control; + + flags &= ~(wfGrow | wfZoom); + palette = wpGrayWindow; + + TRect r = getExtent(); + r.grow(-1, -1); + r.a.y = r.b.y - 1; + control = new TReport( r ); + control->options |= ofFramed; + control->eventMask |= evBroadcast; + insert(control); + + r = getExtent(); + r.grow(-1, -1); + r.b.y = r.b.y - 2; + control = new TTable( r ); + control->options |= ofFramed; + control->options |= ofSelectable; + control->blockCursor(); + insert(control); + control->select(); +} + +void TAsciiChart::handleEvent( TEvent &event ) { + TWindow::handleEvent( event ); +} diff --git a/tvision/examples/demo/ascii.h b/tvision/examples/demo/ascii.h new file mode 100644 index 0000000..eefb9b8 --- /dev/null +++ b/tvision/examples/demo/ascii.h @@ -0,0 +1,140 @@ +/*-------------------------------------------------------*/ +/* */ +/* Ascii.h: Header file for Ascii.cpp */ +/* */ +/*-------------------------------------------------------*/ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + */ + +#if !defined( __ASCII_H ) +#define __ASCII_H + +const int cmAsciiTableCmdBase = 910; +const int cmCharFocused = 0; + + +class TTable : public TView +{ + +public: + + TTable( TRect& r ); + TTable( StreamableInit ) : TView(streamableInit) { }; + virtual void draw(); + virtual void handleEvent( TEvent& event ); + void charFocused(); + +private: + + virtual const char *streamableName() const + { return name; } + +protected: + + virtual void write( opstream& ); + virtual void *read( ipstream& ); + +public: + + static const char * const name; + static TStreamable *build(); + +}; + + +inline ipstream& operator >> ( ipstream& is, TTable& cl ) + { return is >> (TStreamable&) cl; } +inline ipstream& operator >> ( ipstream& is, TTable*& cl ) + { return is >> (void *&) cl; } + +inline opstream& operator << ( opstream& os, TTable& cl ) + { return os << (TStreamable&) cl; } +inline opstream& operator << ( opstream& os, TTable* cl ) + { return os << (TStreamable *) cl; } + + +class TReport : public TView +{ + +public: + + TReport( TRect& r ); + TReport( StreamableInit ) : TView(streamableInit) { }; + virtual void draw(); + virtual void handleEvent( TEvent& event ); + +private: + + long asciiChar; + + virtual const char *streamableName() const + { return name; } + +protected: + + virtual void write( opstream& ); + virtual void *read( ipstream& ); + +public: + + static const char * const name; + static TStreamable *build(); + +}; + +inline ipstream& operator >> ( ipstream& is, TReport& cl ) + { return is >> (TStreamable&) cl; } +inline ipstream& operator >> ( ipstream& is, TReport*& cl ) + { return is >> (void *&) cl; } + +inline opstream& operator << ( opstream& os, TReport& cl ) + { return os << (TStreamable&) cl; } +inline opstream& operator << ( opstream& os, TReport* cl ) + { return os << (TStreamable *) cl; } + + +class TAsciiChart : public TWindow +{ + +public: + + TAsciiChart(); + TAsciiChart( StreamableInit ) : TWindowInit(&initFrame), + TWindow(streamableInit) + { }; + virtual void handleEvent( TEvent &event ); + +private: + + virtual const char *streamableName() const + { return name; } + +protected: + + virtual void write( opstream& ); + virtual void *read( ipstream& ); + +public: + + static const char * const name; + static TStreamable *build(); + +}; + +inline ipstream& operator >> ( ipstream& is, TAsciiChart& cl ) + { return is >> (TStreamable&) cl; } +inline ipstream& operator >> ( ipstream& is, TAsciiChart*& cl ) + { return is >> (void *&) cl; } + +inline opstream& operator << ( opstream& os, TAsciiChart& cl ) + { return os << (TStreamable&) cl; } +inline opstream& operator << ( opstream& os, TAsciiChart* cl ) + { return os << (TStreamable *) cl; } + + +#endif // __ASCII_H diff --git a/tvision/examples/demo/calendar.cc b/tvision/examples/demo/calendar.cc new file mode 100644 index 0000000..c10d1cb --- /dev/null +++ b/tvision/examples/demo/calendar.cc @@ -0,0 +1,297 @@ +/*---------------------------------------------------------*/ +/* */ +/* Calendar.cpp: TCalenderWindow member functions. */ +/* */ +/*---------------------------------------------------------*/ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + */ +/* + * Modified by Sergio Sigala + * Modified by Salvador E. Tropea to show how to deal with code page + * dependent values. + */ + +// SET: moved the standard headers before tv.h +#define Uses_string +#define Uses_stdlib +#include +#include +#include +#define Uses_AllocLocal + +#define Uses_TRect +#define Uses_TEvent +#define Uses_TKeys +#define Uses_TDrawBuffer +#define Uses_TStreamableClass +#define Uses_TStreamable +#define Uses_TView +#define Uses_TWindow +#include +__link( RView ) +__link( RWindow ) + +#include "calendar.h" + +char TCalendarView::upArrowChar ='\036'; +char TCalendarView::oupArrowChar ='\036'; +char TCalendarView::downArrowChar ='\037'; +char TCalendarView::odownArrowChar='\037'; + +static char *monthNames[] = { + "", + "January", "February", "March", "April", "May", "June", + "July", "August", "September","October", "November", "December" +}; + + +static unsigned char daysInMonth[] = { + 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + + +// +// TCalendarView functions +// + +const char * const TCalendarView::name = "TCalendarView"; + + +void TCalendarView::write( opstream& os ) +{ + TView::write( os ); + os << days << month << year << curDay << curMonth << curYear; +} + + +void *TCalendarView::read( ipstream& is ) +{ + TView::read( is ); + is >> days >> month >> year >> curDay >> curMonth >> curYear; + return this; +} + + +TStreamable *TCalendarView::build() +{ + return new TCalendarView( streamableInit ); +} + + +TStreamableClass RCalendarView( TCalendarView::name, + TCalendarView::build, + __DELTA(TCalendarView) + ); + + +TCalendarView::TCalendarView(TRect& r) : TView( r ) +{ + /* SS: little change */ + +// struct date d; + + options |= ofSelectable; + eventMask |= evMouseAuto; + + time_t now = time(NULL); + tm *broken = localtime(&now); + + year = curYear = broken->tm_year + 1900; + month = curMonth = broken->tm_mon + 1; + curDay = broken->tm_mday; + +// getdate( &d ); +// year = curYear = d.da_year; +// month = curMonth = d.da_mon; +// curDay = d.da_day; + + drawView(); +} + + +int dayOfWeek(int day, int month, int year) +{ + int century, yr, dw; + + if(month < 3) + { + month += 10; + --year; + } + else + month -= 2; + + century = year / 100; + yr = year % 100; + dw = (((26 * (int)month - 2) / 10) + (int)day + yr + (yr / 4) + (century / 4) - + (2 * century)) % 7; + + if(dw < 0) + dw += 7; + + return((int)dw); +} + + +void TCalendarView::draw() +{ + AllocLocalStr(str,size.x+1); + + unsigned current = 1 - dayOfWeek(1, month, year); + unsigned days = daysInMonth[month] + ((year % 4 == 0 && month == 2) ? 1 : 0); + char color, boldColor; + int i, j; + TDrawBuffer buf; + + color = getColor(6); + boldColor = getColor(7); + + buf.moveChar(0, ' ', color, size.x); + + sprintf(str, "%c%12s %4d %c", upArrowChar, monthNames[month], year, + downArrowChar); //wsz: to see full year and down arrow + /*ostrstream( str, sizeof str) + << setw(9) << monthNames[month] << " " << setw(4) << year + << " " << (char) 30 << " " << (char) 31 << " " << ends;*/ + + buf.moveStr(0, str, color); + writeLine(0, 0, size.x, 1, buf); + + buf.moveChar(0, ' ', color, size.x); + buf.moveStr(0, "Su Mo Tu We Th Fr Sa", color); + writeLine(0, 1, size.x, 1, buf); + + for(i = 1; i <= 6; i++) + { + buf.moveChar(0, ' ', color, size.x); + for(j = 0; j <= 6; j++) + { + if(current < 1 || current > days) + buf.moveStr(j*3, " ", color); + else + { + sprintf(str, "%2d", (int)current); + /*ostrstream( str, sizeof str ) Ugh! then people say C++ is slow ... + << setw(2) << (int) current << ends;*/ + if(year == curYear && month == curMonth && current == curDay) + buf.moveStr(j*3, str, boldColor); + else + buf.moveStr(j*3, str, color); + } + current++; + } + writeLine(0, (short)(i+1), size.x, 1, buf); + } +} + + +void TCalendarView::handleEvent(TEvent& event) +{ + TPoint point; + + TView::handleEvent(event); + if (state && sfSelected) + { + if ( (event.what & evMouse) && (evMouseDown || evMouseAuto) ) + { + point = makeLocal(event.mouse.where); + if (point.x == 0 && point.y == 0) + { + ++month; + if (month > 12) + { + ++year; + month = 1; + } + drawView(); + } + else if (point.x == 19 && point.y == 0) + { + --month; + if (month < 1) + { + --year; + month = 12; + } + drawView(); + } + } + else if (event.what == evKeyboard) + { + if ( (loByte(event.keyDown.keyCode) == '+') || + event.keyDown.keyCode == kbDown) + { + ++month; + if (month > 12) + { + ++year; + month = 1; + } + } + else if ( (loByte(event.keyDown.keyCode) == '-') || + event.keyDown.keyCode == kbUp) + { + --month; + if (month < 1) + { + --year; + month = 12; + } + } + drawView(); + } + } +} + + +// +// TCalendarWindow functions +// + +const char * const TCalendarWindow::name = "TCalendarWindow"; + + +void TCalendarWindow::write( opstream& os ) +{ + TWindow::write( os ); +} + + +void *TCalendarWindow::read( ipstream& is ) +{ + TWindow::read( is ); + return this; +} + + +TStreamable *TCalendarWindow::build() +{ + return new TCalendarWindow( streamableInit ); +} + + +TStreamableClass RCalendarWindow( TCalendarWindow::name, + TCalendarWindow::build, + __DELTA(TCalendarWindow) + ); + + +TCalendarWindow::TCalendarWindow() : + TWindowInit( &TCalendarWindow::initFrame ) + , TWindow( TRect(1, 1, 23, 11), "Calendar", wnNoNumber ) +{ + TRect r(getExtent()); + + flags &= ~(wfZoom | wfGrow); + growMode = 0; + + palette = wpCyanWindow; + + r.grow(-1, -1); + insert( new TCalendarView( r )); +} diff --git a/tvision/examples/demo/calendar.h b/tvision/examples/demo/calendar.h new file mode 100644 index 0000000..e1b1a18 --- /dev/null +++ b/tvision/examples/demo/calendar.h @@ -0,0 +1,102 @@ +/*-------------------------------------------------------*/ +/* */ +/* Calendar.h: Header file for Calendar.cpp */ +/* */ +/*-------------------------------------------------------*/ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + */ + +#if !defined( __CALENDAR_H ) +#define __CALENDAR_H + +class TCalendarView : public TView +{ + +public: + + TCalendarView(TRect & r); + TCalendarView( StreamableInit ) : TView(streamableInit) { }; + virtual void handleEvent(TEvent& event); + virtual void draw(); + + // The following are code page dependent, take a look at tvdemo3.cc to + // see how we handle it + static char upArrowChar; + static char oupArrowChar; + static char downArrowChar; + static char odownArrowChar; + +private: + + unsigned days, month, year; + unsigned curDay, curMonth, curYear; + + virtual const char *streamableName() const + { return name; } + +protected: + + virtual void write( opstream& ); + virtual void *read( ipstream& ); + +public: + + static const char * const name; + static TStreamable *build(); +}; + +inline ipstream& operator >> ( ipstream& is, TCalendarView& cl ) + { return is >> (TStreamable&) cl; } +inline ipstream& operator >> ( ipstream& is, TCalendarView*& cl ) + { return is >> (void *&) cl; } + +inline opstream& operator << ( opstream& os, TCalendarView& cl ) + { return os << (TStreamable&) cl; } +inline opstream& operator << ( opstream& os, TCalendarView* cl ) + { return os << (TStreamable *) cl; } + + +class TCalendarWindow : public TWindow +{ + +public: + + TCalendarWindow(); + TCalendarWindow( StreamableInit ) : + TWindowInit(&TCalendarWindow::initFrame) + , TWindow(streamableInit) { }; + +private: + + virtual const char *streamableName() const + { return name; } + +protected: + + virtual void write( opstream& ); + virtual void *read( ipstream& ); + +public: + + static const char * const name; + static TStreamable *build(); + +}; + +inline ipstream& operator >> ( ipstream& is, TCalendarWindow& cl ) + { return is >> (TStreamable&) cl; } +inline ipstream& operator >> ( ipstream& is, TCalendarWindow*& cl ) + { return is >> (void *&) cl; } + +inline opstream& operator << ( opstream& os, TCalendarWindow& cl ) + { return os << (TStreamable&) cl; } +inline opstream& operator << ( opstream& os, TCalendarWindow* cl ) + { return os << (TStreamable *) cl; } + + +#endif // __CALENDAR_H diff --git a/tvision/examples/demo/demo.bmk b/tvision/examples/demo/demo.bmk new file mode 100644 index 0000000..3f47f26 --- /dev/null +++ b/tvision/examples/demo/demo.bmk @@ -0,0 +1,10 @@ +#!/usr/bin/make +# +# Copyright (c) 2003 by Salvador E. Tropea. +# Covered by the GPL license. +# +!include ../common.bmk +all: demo.exe +!include ../../makes/common.bmk +!include demo.umk + diff --git a/tvision/examples/demo/demo.gpr b/tvision/examples/demo/demo.gpr new file mode 100644 index 0000000..2d796dd Binary files /dev/null and b/tvision/examples/demo/demo.gpr differ diff --git a/tvision/examples/demo/demo.mkf b/tvision/examples/demo/demo.mkf new file mode 100644 index 0000000..618de72 --- /dev/null +++ b/tvision/examples/demo/demo.mkf @@ -0,0 +1,11 @@ +#!/usr/bin/make +# +# Copyright (c) 2003-2004 by Salvador E. Tropea. +# Covered by the GPL license. +# +vpath_src= +vpath_obj=. +INCLUDE_DIRS=../../include +COMMON_IMK=../../makes/common.imk +include $(COMMON_IMK) +include demo$(ExIMK) diff --git a/tvision/examples/demo/demo.umk b/tvision/examples/demo/demo.umk new file mode 100644 index 0000000..7b91fa2 --- /dev/null +++ b/tvision/examples/demo/demo.umk @@ -0,0 +1,57 @@ +#!/usr/bin/make +# Automatically generated from RHIDE projects, don't edit +# + +OBJFILES=\ + ./ascii$(ExOBJ) \ + ./calendar$(ExOBJ) \ + ./fileview$(ExOBJ) \ + ./gadgets$(ExOBJ) \ + ./mousedlg$(ExOBJ) \ + ./puzzle$(ExOBJ) \ + ./tvdemo1$(ExOBJ) \ + ./tvdemo2$(ExOBJ) \ + ./tvdemo3$(ExOBJ) + +LIBRARIES= + +demo$(ExEXE):: \ + ./ascii$(ExOBJ) \ + ./calendar$(ExOBJ) \ + ./fileview$(ExOBJ) \ + ./gadgets$(ExOBJ) \ + ./mousedlg$(ExOBJ) \ + ./puzzle$(ExOBJ) \ + ./tvdemo1$(ExOBJ) \ + ./tvdemo2$(ExOBJ) \ + ./tvdemo3$(ExOBJ) \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_LINK) + +./ascii$(ExOBJ):: ascii.cc + $(RHIDE_COMPILE_CC) + +./calendar$(ExOBJ):: calendar.cc + $(RHIDE_COMPILE_CC) + +./fileview$(ExOBJ):: fileview.cc + $(RHIDE_COMPILE_CC) + +./gadgets$(ExOBJ):: gadgets.cc + $(RHIDE_COMPILE_CC) + +./mousedlg$(ExOBJ):: mousedlg.cc + $(RHIDE_COMPILE_CC) + +./puzzle$(ExOBJ):: puzzle.cc + $(RHIDE_COMPILE_CC) + +./tvdemo1$(ExOBJ):: tvdemo1.cc + $(RHIDE_COMPILE_CC) + +./tvdemo2$(ExOBJ):: tvdemo2.cc + $(RHIDE_COMPILE_CC) + +./tvdemo3$(ExOBJ):: tvdemo3.cc + $(RHIDE_COMPILE_CC) + diff --git a/tvision/examples/demo/demohelp.h b/tvision/examples/demo/demohelp.h new file mode 100644 index 0000000..22fe18b --- /dev/null +++ b/tvision/examples/demo/demohelp.h @@ -0,0 +1,40 @@ +const int + hcAsciiTable = 6, + hcCalculator = 4, + hcCalendar = 5, + hcCancelBtn = 35, + hcFCChDirDBox = 37, + hcFChangeDir = 15, + hcFDosShell = 16, + hcFExit = 17, + hcFOFileOpenDBox = 31, + hcFOFiles = 33, + hcFOName = 32, + hcFOOpenBtn = 34, + hcFOpen = 14, + hcFile = 13, + hcNocontext = 0, + hcOCColorsDBox = 39, + hcOColors = 28, + hcOMMouseDBox = 38, + hcOMouse = 27, + hcORestoreDesktop = 30, + hcOSaveDesktop = 29, + hcOpenBtn = 36, + hcOptions = 26, + hcPuzzle = 3, + hcSAbout = 8, + hcSAsciiTable = 11, + hcSCalculator = 12, + hcSCalendar = 10, + hcSPuzzle = 9, + hcSystem = 7, + hcViewer = 2, + hcWCascade = 22, + hcWClose = 25, + hcWNext = 23, + hcWPrevious = 24, + hcWSizeMove = 19, + hcWTile = 21, + hcWZoom = 20, + hcWindows = 18; diff --git a/tvision/examples/demo/demohelp.h32 b/tvision/examples/demo/demohelp.h32 new file mode 100644 index 0000000..1fabc91 Binary files /dev/null and b/tvision/examples/demo/demohelp.h32 differ diff --git a/tvision/examples/demo/diffs.cc b/tvision/examples/demo/diffs.cc new file mode 100644 index 0000000..e1db97d --- /dev/null +++ b/tvision/examples/demo/diffs.cc @@ -0,0 +1,416 @@ +These are the differences between the original directory and this one. You +can see what things I changed to make it work. Some of them aren't really +needed. + +Only in .: Makefile.am +Only in .: Makefile.in +diff -u ./ascii.cc E:\DJ\CONTRIB\tvision\examples\demo\ascii.cc +--- ./ascii.cc Mon Jan 19 15:16:34 1998 ++++ E:\DJ\CONTRIB\tvision\examples\demo\ascii.cc Sat Jan 9 20:25:36 1999 +@@ -25,15 +25,16 @@ + #define Uses_TStreamable + #define Uses_TView + #define Uses_TWindow +-#include ++#include + __link( RView ) + __link( RWindow ) + + #include + #include + #include +-#include +-#include ++//#include SET: These two are only to bloat the code. ++//#include ++#include // SET: printf does the job much simplier + + #include "ascii.h" + +@@ -208,13 +209,17 @@ + TDrawBuffer buf; + char color = getColor(6); + char str[80]; +- ostrstream statusStr( str, sizeof str ); + ++ sprintf(str, "%s%c%s%3d%s%2X", ++ " Char: ", (asciiChar==0)?(char)0x20:(char)asciiChar, ++ " Decimal: ", (int)asciiChar, ++ " Hex ", (int)asciiChar); ++ /* SET: from Robert's port + statusStr + << " Char: " << (char ) ((asciiChar == 0) ? 0x20 : asciiChar) + << " Decimal: " << setw(3) << (int) asciiChar + << " Hex " << hex << setiosflags(ios::uppercase) +- << setw(2) << (int) asciiChar << " " << ends; ++ << setw(2) << (int) asciiChar << " " << ends;*/ + + buf.moveStr(0, str, color); + writeLine(0, 0, 32, 1, buf); +diff -u ./calc.cc E:\DJ\CONTRIB\tvision\examples\demo\calc.cc +--- ./calc.cc Mon Jan 19 15:16:34 1998 ++++ E:\DJ\CONTRIB\tvision\examples\demo\calc.cc Sat Jan 9 20:12:38 1999 +@@ -24,7 +24,8 @@ + #define Uses_TStreamable + #define Uses_TView + #define Uses_TDialog +-#include ++#define Uses_TPalette // SET: added ++#include + __link( RView ) + __link( RDialog ) + __link( RButton ) +diff -u ./calendar.cc E:\DJ\CONTRIB\tvision\examples\demo\calendar.cc +--- ./calendar.cc Mon Jan 19 15:16:34 1998 ++++ E:\DJ\CONTRIB\tvision\examples\demo\calendar.cc Sat Jan 9 20:30:12 1999 +@@ -22,15 +22,16 @@ + #define Uses_TStreamable + #define Uses_TView + #define Uses_TWindow +-#include ++#include + __link( RView ) + __link( RWindow ) + + #include + #include + #include +-#include +-#include ++//#include ++//#include ++#include + #include + + #include "calendar.h" +@@ -133,49 +134,50 @@ + + void TCalendarView::draw() + { +- char str[23]; +- char current = (char)(1 - dayOfWeek(1, month, year)); +- char days = (char)( daysInMonth[month] + +- ((year % 4 == 0 && month == 2) ? 1 : 0) ); ++ char str[size.x+1]; ++ unsigned current = 1 - dayOfWeek(1, month, year); ++ unsigned days = daysInMonth[month] + ((year % 4 == 0 && month == 2) ? 1 : 0); + char color, boldColor; +- short i, j; ++ int i, j; + TDrawBuffer buf; + + color = getColor(6); + boldColor = getColor(7); + +- buf.moveChar(0, ' ', color, 22); ++ buf.moveChar(0, ' ', color, size.x); + +- ostrstream( str, sizeof str) ++ sprintf(str, "\036%15s %4d\037", monthNames[month], year); ++ /*ostrstream( str, sizeof str) + << setw(9) << monthNames[month] << " " << setw(4) << year +- << " " << (char) 30 << " " << (char) 31 << " " << ends; ++ << " " << (char) 30 << " " << (char) 31 << " " << ends;*/ + + buf.moveStr(0, str, color); +- writeLine(0, 0, 22, 1, buf); ++ writeLine(0, 0, size.x, 1, buf); + +- buf.moveChar(0, ' ', color, 22); ++ buf.moveChar(0, ' ', color, size.x); + buf.moveStr(0, "Su Mo Tu We Th Fr Sa", color); +- writeLine(0, 1, 22, 1, buf); ++ writeLine(0, 1, size.x, 1, buf); + + for(i = 1; i <= 6; i++) + { +- buf.moveChar(0, ' ', color, 22); ++ buf.moveChar(0, ' ', color, size.x); + for(j = 0; j <= 6; j++) + { + if(current < 1 || current > days) +- buf.moveStr((short)(j*3), " ", color); ++ buf.moveStr(j*3, " ", color); + else + { +- ostrstream( str, sizeof str ) +- << setw(2) << (int) current << ends; ++ sprintf(str, "%2d", (int)current); ++ /*ostrstream( str, sizeof str ) Ugh! then people say C++ is slow ... ++ << setw(2) << (int) current << ends;*/ + if(year == curYear && month == curMonth && current == curDay) +- buf.moveStr((short)(j*3), str, boldColor); ++ buf.moveStr(j*3, str, boldColor); + else +- buf.moveStr((short)(j*3), str, color); ++ buf.moveStr(j*3, str, color); + } + current++; + } +- writeLine(0, (short)(i+1), 22, 1, buf); ++ writeLine(0, (short)(i+1), size.x, 1, buf); + } + } + +Only in E:\DJ\CONTRIB\tvision\examples\demo\: demo.gpr +diff -u ./fileview.cc E:\DJ\CONTRIB\tvision\examples\demo\fileview.cc +--- ./fileview.cc Mon Jan 19 15:16:34 1998 ++++ E:\DJ\CONTRIB\tvision\examples\demo\fileview.cc Sat Jan 9 20:30:18 1999 +@@ -22,7 +22,7 @@ + #define Uses_TProgram + #define Uses_TDeskTop + #define Uses_TStreamableClass +-#include ++#include + __link(RScroller) + __link(RScrollBar) + +diff -u ./fileview.h E:\DJ\CONTRIB\tvision\examples\demo\fileview.h +--- ./fileview.h Mon Jan 19 15:16:32 1998 ++++ E:\DJ\CONTRIB\tvision\examples\demo\fileview.h Sat Jan 9 20:30:22 1999 +@@ -17,7 +17,7 @@ + #define Uses_TCollection + #define Uses_TScroller + #define Uses_TWindow +-#include ++#include + + const hlChangeDir = cmChangeDir; + +diff -u ./gadgets.cc E:\DJ\CONTRIB\tvision\examples\demo\gadgets.cc +--- ./gadgets.cc Mon Jan 19 15:16:34 1998 ++++ E:\DJ\CONTRIB\tvision\examples\demo\gadgets.cc Sat Jan 9 20:30:28 1999 +@@ -22,7 +22,7 @@ + #define Uses_TRect + #define Uses_TView + #define Uses_TDrawBuffer +-#include ++#include + + #include + #include +diff -u ./gadgets.h E:\DJ\CONTRIB\tvision\examples\demo\gadgets.h +--- ./gadgets.h Mon Jan 19 15:16:34 1998 ++++ E:\DJ\CONTRIB\tvision\examples\demo\gadgets.h Sat Jan 9 20:30:30 1999 +@@ -17,7 +17,7 @@ + #define Uses_TEvent + #define Uses_TRect + #define Uses_TView +-#include ++#include + + + class THeapView : public TView +Only in E:\DJ\CONTRIB\tvision\examples\demo\: help.cc +Only in E:\DJ\CONTRIB\tvision\examples\demo\: help.h +Only in E:\DJ\CONTRIB\tvision\examples\demo\: helpbase.cc +Only in E:\DJ\CONTRIB\tvision\examples\demo\: helpbase.h +diff -u ./mousedlg.cc E:\DJ\CONTRIB\tvision\examples\demo\mousedlg.cc +--- ./mousedlg.cc Mon Jan 19 15:16:34 1998 ++++ E:\DJ\CONTRIB\tvision\examples\demo\mousedlg.cc Sat Jan 9 20:38:50 1999 +@@ -27,7 +27,8 @@ + #define Uses_TButton + #define Uses_TSItem + #define Uses_TEventQueue +-#include ++#define Uses_TPalette ++#include + + #include + #include +@@ -65,7 +66,8 @@ + + if (event.what == evMouseDown) + { +- if (event.mouse.eventFlags & meDoubleClick) ++ //if (event.mouse.eventFlags & meDoubleClick) SET: ++ if (event.mouse.doubleClick) + { + clicked = (short)((clicked) ? 0 : 1); + drawView(); +Only in .: pp +diff -u ./puzzle.cc E:\DJ\CONTRIB\tvision\examples\demo\puzzle.cc +--- ./puzzle.cc Mon Jan 19 15:16:34 1998 ++++ E:\DJ\CONTRIB\tvision\examples\demo\puzzle.cc Sat Jan 9 20:39:12 1999 +@@ -22,7 +22,8 @@ + #define Uses_TStreamable + #define Uses_TView + #define Uses_TWindow +-#include ++#define Uses_TPalette ++#include + __link( RView ) + __link( RWindow ) + +Only in E:\DJ\CONTRIB\tvision\examples\demo\: rhide.env +diff -u ./tvdemo.h E:\DJ\CONTRIB\tvision\examples\demo\tvdemo.h +--- ./tvdemo.h Mon Jan 19 15:16:34 1998 ++++ E:\DJ\CONTRIB\tvision\examples\demo\tvdemo.h Sat Jan 9 21:09:16 1999 +@@ -29,7 +29,7 @@ + static TMenuBar *initMenuBar( TRect r ); + virtual void handleEvent(TEvent& Event); + virtual void getEvent(TEvent& event); +-// virtual TPalette& getPalette() const; ++ virtual TPalette& getPalette() const; + virtual void idle(); // Updates heap and clock views + + private: +diff -u ./tvdemo1.cc E:\DJ\CONTRIB\tvision\examples\demo\tvdemo1.cc +--- ./tvdemo1.cc Tue Jul 21 10:48:00 1998 ++++ E:\DJ\CONTRIB\tvision\examples\demo\tvdemo1.cc Sat Jan 9 20:40:28 1999 +@@ -28,14 +28,14 @@ + #define Uses_TWindow + #define Uses_TDeskTop + +-#include ++#include + + #include "tvdemo.h" + #include "gadgets.h" + #include "fileview.h" + #include "puzzle.h" + #include "demohelp.h" +-#include ++#include + + #include + #include +diff -u ./tvdemo2.cc E:\DJ\CONTRIB\tvision\examples\demo\tvdemo2.cc +--- ./tvdemo2.cc Mon Jan 19 15:16:34 1998 ++++ E:\DJ\CONTRIB\tvision\examples\demo\tvdemo2.cc Sat Jan 9 21:18:56 1999 +@@ -29,7 +29,7 @@ + #define Uses_TChDirDialog + #define Uses_TScreen + +-#include ++#include + + #include "tvdemo.h" + #include "tvcmds.h" +@@ -48,7 +48,7 @@ + void TVDemo::shell() + { + /* SS: this simulates a Ctrl-Z */ +- raise(SIGTSTP); /* stop the process */ ++ /*raise(SIGTSTP);*/ /* stop the process */ + } + + +@@ -130,6 +130,22 @@ + } + + ++ushort executeDialog( TDialog* pD, void* data=0 ) ++{ ++ ushort c=cmCancel; ++ ++ if (TProgram::application->validView(pD)) ++ { ++ if (data) ++ pD->setData(data); ++ c = TProgram::deskTop->execView(pD); ++ if ((c != cmCancel) && (data)) ++ pD->getData(data); ++ destroy(pD); ++ } ++ ++ return c; ++} + + // + // About Box function() +@@ -338,7 +354,8 @@ + + TColorGroup &group5 = group1 + group2 + group3 + group4; + +- TColorDialog *c = new TColorDialog((TPalette*)0, &group5 ); ++ TPalette *temp_pal=new TPalette(getPalette()); ++ TColorDialog *c = new TColorDialog(temp_pal, &group5 ); + + if( validView( c ) != 0 ) + { +@@ -351,4 +368,5 @@ + } + destroy( c ); + } ++ delete temp_pal; + } +diff -u ./tvdemo3.cc E:\DJ\CONTRIB\tvision\examples\demo\tvdemo3.cc +--- ./tvdemo3.cc Tue Jul 21 10:48:16 1998 ++++ E:\DJ\CONTRIB\tvision\examples\demo\tvdemo3.cc Sat Jan 9 21:10:08 1999 +@@ -30,7 +30,7 @@ + #define Uses_TDialog + #define Uses_TEventQueue + +-#include ++#include + + #include "tvdemo.h" + #include "tvcmds.h" +@@ -39,7 +39,7 @@ + #include "demohelp.h" + #include "fileview.h" + +-#include ++#include + + // + // Mouse Control Dialog Box function +@@ -96,12 +96,44 @@ + // + // getPalette() function ( returns application's palette ) + // +-/* ++#define cpAppColor \ ++ "\x71\x70\x78\x74\x20\x28\x24\x17\x1F\x1A\x31\x31\x1E\x71\x1F" \ ++ "\x37\x3F\x3A\x13\x13\x3E\x21\x3F\x70\x7F\x7A\x13\x13\x70\x7F\x7E" \ ++ "\x70\x7F\x7A\x13\x13\x70\x70\x7F\x7E\x20\x2B\x2F\x78\x2E\x70\x30" \ ++ "\x3F\x3E\x1F\x2F\x1A\x20\x72\x31\x31\x30\x2F\x3E\x31\x13\x38\x00" \ ++ "\x17\x1F\x1A\x71\x71\x1E\x17\x1F\x1E\x20\x2B\x2F\x78\x2E\x10\x30" \ ++ "\x3F\x3E\x70\x2F\x7A\x20\x12\x31\x31\x30\x2F\x3E\x31\x13\x38\x00" \ ++ "\x37\x3F\x3A\x13\x13\x3E\x30\x3F\x3E\x20\x2B\x2F\x78\x2E\x30\x70" \ ++ "\x7F\x7E\x1F\x2F\x1A\x20\x32\x31\x71\x70\x2F\x7E\x71\x13\x78\x00" \ ++ "\x37\x3F\x3A\x13\x13\x30\x3E\x1E" // help colors ++ ++#define cpAppBlackWhite \ ++ "\x70\x70\x78\x7F\x07\x07\x0F\x07\x0F\x07\x70\x70\x07\x70\x0F" \ ++ "\x07\x0F\x07\x70\x70\x07\x70\x0F\x70\x7F\x7F\x70\x07\x70\x07\x0F" \ ++ "\x70\x7F\x7F\x70\x07\x70\x70\x7F\x7F\x07\x0F\x0F\x78\x0F\x78\x07" \ ++ "\x0F\x0F\x0F\x70\x0F\x07\x70\x70\x70\x07\x70\x0F\x07\x07\x08\x00" \ ++ "\x07\x0F\x0F\x07\x70\x07\x07\x0F\x0F\x70\x78\x7F\x08\x7F\x08\x70" \ ++ "\x7F\x7F\x7F\x0F\x70\x70\x07\x70\x70\x70\x07\x7F\x70\x07\x78\x00" \ ++ "\x70\x7F\x7F\x70\x07\x70\x70\x7F\x7F\x07\x0F\x0F\x78\x0F\x78\x07" \ ++ "\x0F\x0F\x0F\x70\x0F\x07\x70\x70\x70\x07\x70\x0F\x07\x07\x08\x00" \ ++ "\x07\x0F\x07\x70\x70\x07\x0F\x70" // help colors ++ ++#define cpAppMonochrome \ ++ "\x70\x07\x07\x0F\x70\x70\x70\x07\x0F\x07\x70\x70\x07\x70\x00" \ ++ "\x07\x0F\x07\x70\x70\x07\x70\x00\x70\x70\x70\x07\x07\x70\x07\x00" \ ++ "\x70\x70\x70\x07\x07\x70\x70\x70\x0F\x07\x07\x0F\x70\x0F\x70\x07" \ ++ "\x0F\x0F\x07\x70\x07\x07\x70\x07\x07\x07\x70\x0F\x07\x07\x70\x00" \ ++ "\x70\x70\x70\x07\x07\x70\x70\x70\x0F\x07\x07\x0F\x70\x0F\x70\x07" \ ++ "\x0F\x0F\x07\x70\x07\x07\x70\x07\x07\x07\x70\x0F\x07\x07\x01\x00" \ ++ "\x70\x70\x70\x07\x07\x70\x70\x70\x0F\x07\x07\x0F\x70\x0F\x70\x07" \ ++ "\x0F\x0F\x07\x70\x07\x07\x70\x07\x07\x07\x70\x0F\x07\x07\x01\x00" \ ++ "\x07\x0F\x07\x70\x70\x07\x0F\x70" // help colors ++ + TPalette& TVDemo::getPalette() const + { +- static TPalette newcolor ( cpAppColor cHelpColor, sizeof( cpAppColor cHelpColor )-1 ); +- static TPalette newblackwhite( cpAppBlackWhite cHelpBlackWhite, sizeof( cpAppBlackWhite cHelpBlackWhite)-1 ); +- static TPalette newmonochrome( cpAppMonochrome cHelpMonochrome, sizeof( cpAppMonochrome cHelpMonochrome)-1 ); ++ static TPalette newcolor ( cpAppColor , sizeof( cpAppColor )-1 ); ++ static TPalette newblackwhite( cpAppBlackWhite , sizeof( cpAppBlackWhite )-1 ); ++ static TPalette newmonochrome( cpAppMonochrome , sizeof( cpAppMonochrome )-1 ); + static TPalette *palettes[] = + { + &newcolor, +@@ -111,7 +143,7 @@ + return *(palettes[appPalette]); + + } +-*/ ++ + + // + // isTileable() function ( checks a view on desktop is tileable or not ) diff --git a/tvision/examples/demo/fileview.cc b/tvision/examples/demo/fileview.cc new file mode 100644 index 0000000..e14cc27 --- /dev/null +++ b/tvision/examples/demo/fileview.cc @@ -0,0 +1,186 @@ +/*---------------------------------------------------------*/ +/* */ +/* Turbo Vision FileViewer Demo Support File */ +/* */ +/*---------------------------------------------------------*/ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + */ +/* + * Modified by Sergio Sigala + * Modified by Salvador E. Tropea + */ + +// SET: moved the standard headers before tv.h +#define Uses_stdio +#define Uses_string +#define Uses_stdlib +#define Uses_ctype +#define Uses_IfStreamGetLine +#define Uses_fstream + +#define Uses_MsgBox +#define Uses_TKeys +#define Uses_TScroller +#define Uses_TDrawBuffer +#define Uses_TRect +#define Uses_TProgram +#define Uses_TDeskTop +#define Uses_TStreamableClass +#define Uses_TEditor // JASC, cmOpen +#include +__link(RScroller) +__link(RScrollBar) + +#include "tvcmds.h" +#include "fileview.h" + +UsingNamespaceStd + +const char * const TFileViewer::name = "TFileViewer"; + +TFileViewer::TFileViewer( const TRect& bounds, + TScrollBar *aHScrollBar, + TScrollBar *aVScrollBar, + const char *aFileName) : + TScroller( bounds, aHScrollBar, aVScrollBar ) +{ + growMode = gfGrowHiX | gfGrowHiY; + isValid = True; + fileName = 0; + readFile( aFileName ); + delta.x=delta.y=0; +} + +TFileViewer::~TFileViewer() +{ + delete [] fileName; + CLY_destroy(fileLines); +} + +void TFileViewer::draw() +{ + char *p; + + ushort c = getColor(0x0301); + for( short i = 0; i < size.y; i++ ) + { + TDrawBuffer b; + b.moveChar( 0, ' ', c, (short)size.x ); + + if( delta.y + i < fileLines->getCount() ) + { + char s[maxLineLength+1]; + p = (char *)( fileLines->at(delta.y+i) ); + if( p == 0 || (int)strlen(p) < delta.x ) + s[0] = EOS; + else + { + strncpy( s, p+delta.x, size.x ); + if( (int)strlen( p + delta.x ) > size.x ) + s[size.x] = EOS; + } + b.moveStr( 0, s, c ); + } + writeBuf( 0, i, (short)size.x, 1, b ); + } +} + +void TFileViewer::scrollDraw() +{ + TScroller::scrollDraw(); + draw(); +} + +void TFileViewer::readFile( const char *fName ) +{ + delete fileName; + + limit.x = 0; + fileName = newStr( fName ); + fileLines = new TLineCollection(5, 5); + ifstream fileToView( fName ); + if( !fileToView ) + { + messageBox( "Invalid drive or directory", mfError | mfOKButton ); + isValid = False; + } + else + { + char line[maxLineLength+1]; + // SET: Changed to use getline as suggested by Andris. + // New standards makes the use of get incorrect. + while( !lowMemory() && + !fileToView.eof() && + IfStreamGetLine(fileToView,line,sizeof line) + ) + { + limit.x = max( limit.x, (int)strlen( line ) ); + fileLines->insert( newStr( line ) ); + } + isValid = True; + } + limit.y = fileLines->getCount(); +} + +void TFileViewer::setState( ushort aState, Boolean enable ) +{ + TScroller::setState( aState, enable ); + if( enable && (aState & sfExposed) ) + setLimit( limit.x, limit.y ); +} + +Boolean TFileViewer::valid( ushort ) +{ + return isValid; +} + +void *TFileViewer::read(ipstream& is) +{ + char *fName; + + TScroller::read(is); + fName = is.readString(); + fileName = 0; + readFile(fName); + delete fName; + return this; +} + +void TFileViewer::write(opstream& os) +{ + TScroller::write(os); + os.writeString(fileName); +} + +TStreamable *TFileViewer::build() +{ + return new TFileViewer( streamableInit ); +} + + +TStreamableClass RFileView( TFileViewer::name, + TFileViewer::build, + __DELTA(TFileViewer) + ); + + + +static short winNumber = 0; + +TFileWindow::TFileWindow( const char *fileName ) : + TWindowInit( &TFileWindow::initFrame ), + TWindow( TProgram::deskTop->getExtent(), fileName, winNumber++ ) +{ + options |= ofTileable; + TRect r( getExtent() ); + r.grow(-1, -1); + insert(new TFileViewer( r, + standardScrollBar(sbHorizontal | sbHandleKeyboard), + standardScrollBar(sbVertical | sbHandleKeyboard), + fileName) ); +} diff --git a/tvision/examples/demo/fileview.h b/tvision/examples/demo/fileview.h new file mode 100644 index 0000000..9f3b80e --- /dev/null +++ b/tvision/examples/demo/fileview.h @@ -0,0 +1,88 @@ +/*---------------------------------------------------------*/ +/* */ +/* Fileview.h: Header file for fileview.cpp. */ +/* */ +/*---------------------------------------------------------*/ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + */ + +#if !defined( __FILEVIEW_H ) +#define __FILEVIEW_H + +#define Uses_TCollection +#define Uses_TScroller +#define Uses_TWindow +#include + +const int hlChangeDir = cmChangeDir; + +class TLineCollection : public TCollection +{ + +public: + + TLineCollection(short lim, short delta) : TCollection(lim, delta) {} + virtual void freeItem(void *p) { delete[] (char *)p; } + +private: + + virtual void *readItem( ipstream& ) { return 0; } + virtual void writeItem( void *, opstream& ) {} + +}; + +class TFileViewer : public TScroller +{ + +public: + + char *fileName; + TCollection *fileLines; + Boolean isValid; + TFileViewer( const TRect& bounds, + TScrollBar *aHScrollBar, + TScrollBar *aVScrollBar, + const char *aFileName + ); + ~TFileViewer(); + TFileViewer( StreamableInit ) : TScroller(streamableInit) { }; + void draw(); + void readFile( const char *fName ); + void setState( ushort aState, Boolean enable ); + void scrollDraw(); + Boolean valid( ushort command ); + +private: + + virtual const char *streamableName() const + { return name; } + +protected: + + virtual void write( opstream& ); + virtual void *read( ipstream& ); + +public: + + static const char * const name; + static TStreamable *build(); + +}; + +class TFileWindow : public TWindow +{ + +public: + + TFileWindow( const char *fileName ); + +}; + +// const int maxLineLength = 256; JASC, defined in editors.h + +#endif diff --git a/tvision/examples/demo/gadgets.cc b/tvision/examples/demo/gadgets.cc new file mode 100644 index 0000000..1af7f6f --- /dev/null +++ b/tvision/examples/demo/gadgets.cc @@ -0,0 +1,185 @@ +/*-------------------------------------------------------------------*/ +/* */ +/* Turbo Vision Demo */ +/* */ +/* Gadgets.cpp: Gadgets for the Turbo Vision Demo. Includes a */ +/* heap view and a clock view which display the clock at the */ +/* right end of the menu bar and the current heap space at */ +/* the right end of the status line. */ +/* */ +/*-------------------------------------------------------------------*/ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + */ +/* + * Modified by Sergio Sigala + * Modified to compile with gcc v3.x by Salvador E. Tropea, with the help of + * Andris Pavenis. + * Modified by Mike Gorchak to report free memory on QNX. + */ +#include + +// SET: moved the standard headers before tv.h +#define Uses_string +#define Uses_stdlib +#define Uses_ctype +#define Uses_time +#define Uses_iomanip +#if defined(TVOSf_QNXRtP) || defined(TVOSf_QNX4) + #define Uses_stdio + #define Uses_sys_stat +#endif // TVOSf_QNXRtP + +#define Uses_TRect +#define Uses_TView +#define Uses_TDrawBuffer +#include + +#ifdef TVOSf_QNX4 + #include +#endif // TVOSf_QNX4 + +#include "gadgets.h" + +//extern "C" unsigned long farcoreleft( void ); + +// +// ------------- Heap Viewer functions +// + +THeapView::THeapView(TRect& r) : TView( r ) +{ + oldMem = 0; + newMem = heapSize(); + + /* SS: now resizing under X works well */ + growMode = gfGrowLoX | gfGrowLoY | gfGrowHiX | gfGrowHiY; +} + + +void THeapView::draw() +{ + TDrawBuffer buf; + char c = getColor(2); + + buf.moveChar(0, ' ', c, (short)size.x); + buf.moveStr(0, heapStr, c); + writeLine(0, 0, (short)size.x, 1, buf); +} + + +void THeapView::update() +{ + if( (newMem = heapSize()) != oldMem ) + { + oldMem = newMem; + drawView(); + } +} + + +long THeapView::heapSize() +{ + #if defined(TVOSf_QNXRtP) + struct stat st; + long rval=0; + + if (stat("/proc", &st)==0) + { + rval=st.st_size; + } + + if (rval>1024UL*512UL) // one half megabyte ! + { + if (rval>1024UL*1024UL*32UL) // if above 32Mb free + { + sprintf(heapStr, "%10dMb", rval/1024UL/1024UL); + } + else + { + sprintf(heapStr, "%10dKb", rval/1024UL); + } + } + else + { + sprintf(heapStr, "%12d", rval); + } + + return rval; + #elif defined(TVOSf_QNX4) + + _osinfo CurrInfo; + unsigned long rval; + + qnx_osinfo(0, &CurrInfo); + rval=CurrInfo.freepmem; + + if (rval>1024UL*512UL) // one half megabyte ! + { + if (rval>1024UL*1024UL*32UL) // if above 32Mb free + { + sprintf(heapStr, "%10dMb", rval/1024UL/1024UL); + } + else + { + sprintf(heapStr, "%10dKb", rval/1024UL); + } + } + else + { + sprintf(heapStr, "%12d", rval); + } + + return rval; + + #else + /* SS: changed */ + strcpy(heapStr, "Hello world!"); + return -1; + #endif // TVOSf_QNXRtP +} + + +// +// -------------- Clock Viewer functions +// + +TClockView::TClockView( TRect& r ) : TView( r ) +{ + strcpy(lastTime, " "); + strcpy(curTime, " "); + + /* SS: now resizing under X works well */ + growMode = gfGrowLoX | gfGrowHiX; +} + + +void TClockView::draw() +{ + TDrawBuffer buf; + char c = getColor(2); + + buf.moveChar(0, ' ', c, (short)size.x); + buf.moveStr(0, curTime, c); + writeLine(0, 0, (short)size.x, 1, buf); +} + + +void TClockView::update() +{ + time_t t = time(0); + char *date = ctime(&t); + + date[19] = '\0'; + strcpy(curTime, &date[11]); /* Extract time. */ + + if( strcmp(lastTime, curTime) ) + { + drawView(); + strcpy(lastTime, curTime); + } +} diff --git a/tvision/examples/demo/gadgets.h b/tvision/examples/demo/gadgets.h new file mode 100644 index 0000000..22017fd --- /dev/null +++ b/tvision/examples/demo/gadgets.h @@ -0,0 +1,57 @@ +/*---------------------------------------------------------*/ +/* */ +/* Gadgets.h : Header file for gadgets.cpp */ +/* */ +/*---------------------------------------------------------*/ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + */ + +#if !defined( __GADGETS_H ) +#define __GADGETS_H + +#define Uses_TEvent +#define Uses_TRect +#define Uses_TView +#include + + +class THeapView : public TView +{ + +public: + + THeapView( TRect& r ); + virtual void update(); + virtual void draw(); + virtual long heapSize(); + +private: + + long oldMem, newMem; + char heapStr[16]; + +}; + + +class TClockView : public TView +{ + +public: + + TClockView( TRect& r ); + virtual void draw(); + virtual void update(); + +private: + + char lastTime[9]; + char curTime[9]; + +}; + +#endif // __GADGETS_H diff --git a/tvision/examples/demo/mousedlg.cc b/tvision/examples/demo/mousedlg.cc new file mode 100644 index 0000000..93e1a83 --- /dev/null +++ b/tvision/examples/demo/mousedlg.cc @@ -0,0 +1,155 @@ +/*---------------------------------------------------------*/ +/* */ +/* Mousedlg.cpp : Member functions of following classes: */ +/* TClickTester */ +/* TMouseDialog */ +/* */ +/*---------------------------------------------------------*/ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + */ +/* + * Modified by Sergio Sigala + * Modified to compile with gcc v3.x by Salvador E. Tropea, with the help of + * Andris Pavenis. + */ + +// SET: moved the standard headers before tv.h +#define Uses_string +#define Uses_stdlib +#define Uses_ctype + +#define Uses_TRect +#define Uses_TStaticText +#define Uses_TEvent +#define Uses_TDrawBuffer +#define Uses_TDialog +#define Uses_TLabel +#define Uses_TScrollBar +#define Uses_TCheckBoxes +#define Uses_TButton +#define Uses_TSItem +#define Uses_TEventQueue +#define Uses_TPalette +#define Uses_iomanip +#include + +#include "mousedlg.h" + + +#define cpMousePalette "\x07\x08" + + +// +// TClickTester functions +// + +TClickTester::TClickTester(TRect& r, char *aText) : + TStaticText(r, aText) +{ + clicked = 0; +} + + +TPalette& TClickTester::getPalette() const +{ + static TPalette palette( cpMousePalette, sizeof(cpMousePalette)-1 ); + return palette; +} + + +void TClickTester::handleEvent(TEvent& event) +{ + TStaticText::handleEvent(event); + + if (event.what == evMouseDown) + { + //if (event.mouse.eventFlags & meDoubleClick) SET: + if (event.mouse.doubleClick) + { + clicked = (short)((clicked) ? 0 : 1); + drawView(); + } + clearEvent(event); + } +} + + +void TClickTester::draw() +{ + TDrawBuffer buf; + char c; + + if (clicked) + c = getColor(2); + else + c = getColor(1); + + buf.moveChar(0, ' ', c, (short)size.x); + buf.moveStr(0, text, c); + writeLine(0, 0, (short)size.x, 1, buf); +} + + +// +// TMouseDialog functions +// + +TMouseDialog::TMouseDialog() : + TWindowInit( &TMouseDialog::initFrame ) + , TDialog( TRect(0, 0, 34, 12), "Mouse options" ) +{ + TRect r(3, 4, 30, 5); + + options |= ofCentered; + + mouseScrollBar = new TScrollBar(r); + mouseScrollBar->setParams(1, 1, 20, 20, 1); + mouseScrollBar->options |= ofSelectable; + mouseScrollBar->setValue(TEventQueue::doubleDelay); + insert(mouseScrollBar); + + r = TRect(2, 2, 21, 3); + insert(new TLabel(r, "~M~ouse double click", mouseScrollBar)); + + r = TRect(3, 3, 30, 4); + insert(new TClickTester(r, "Fast Medium Slow")); + + r = TRect(3, 6, 30, 7); + insert(new TCheckBoxes(r, new TSItem("~R~everse mouse buttons", NULL))); + oldDelay = TEventQueue::doubleDelay; + + r = TRect(9, 9, 19, 11); + insert(new TButton(r, "O~K~", cmOK, bfDefault)); + + r = TRect(21, 9, 31, 11); + insert(new TButton(r, "Cancel", cmCancel, bfNormal)); + + selectNext( (Boolean) 0); +} + + +void TMouseDialog::handleEvent(TEvent& event) +{ + TDialog::handleEvent(event); + switch(event.what) + { + case evCommand: + if(event.message.command == cmCancel) + TEventQueue::doubleDelay = oldDelay; + break; + + case evBroadcast: + if(event.message.command == cmScrollBarChanged) + { + TEventQueue::doubleDelay = (short)mouseScrollBar->value; + clearEvent(event); + } + break; + } +} + diff --git a/tvision/examples/demo/mousedlg.h b/tvision/examples/demo/mousedlg.h new file mode 100644 index 0000000..80139a4 --- /dev/null +++ b/tvision/examples/demo/mousedlg.h @@ -0,0 +1,44 @@ +/*---------------------------------------------------------*/ +/* */ +/* Mousedlg.h : Header file for mousedlg.cpp */ +/* */ +/*---------------------------------------------------------*/ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + */ + +class TClickTester : public TStaticText +{ + +public: + + TClickTester(TRect& r, char *aText); + virtual TPalette& getPalette() const; + virtual void handleEvent(TEvent& event); + virtual void draw(); + +private: + + char clicked; + +}; + + +class TMouseDialog : public TDialog +{ + +public: + + TMouseDialog(); + virtual void handleEvent(TEvent& event); + +private: + + TScrollBar *mouseScrollBar; + short oldDelay; + +}; diff --git a/tvision/examples/demo/puzzle.cc b/tvision/examples/demo/puzzle.cc new file mode 100644 index 0000000..3471c31 --- /dev/null +++ b/tvision/examples/demo/puzzle.cc @@ -0,0 +1,371 @@ +/*---------------------------------------------------------*/ +/* */ +/* Turbo Vision Puzzle Demo */ +/* */ +/*---------------------------------------------------------*/ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + */ +/* + * Modified by Sergio Sigala + * Modified to compile with gcc v3.x by Salvador E. Tropea, with the help of + * Andris Pavenis. + */ + +// SET: moved the standard headers before tv.h +#define Uses_string +#define Uses_stdio /* SS: for sprintf(...) */ +#define Uses_stdlib +#define Uses_ctype +#define Uses_iomanip + +#define Uses_TRect +#define Uses_TEvent +#define Uses_TKeys +#define Uses_TDrawBuffer +#define Uses_TStreamableClass +#define Uses_TStreamable +#define Uses_TView +#define Uses_TWindow +#define Uses_TPalette +#include + +#if defined(TVComp_MSC) || defined(TVComp_BCPP) + #include + #include +#else + #include + #include + #include +#endif + +__link( RView ) +__link( RWindow ) + +#include "puzzle.h" + + +#define cpPuzzlePalette "\x06\x07" + + +// +// TPuzzleView functions & static variables +// + +const char * const TPuzzleView::name = "TPuzzleView"; + + +void TPuzzleView::write( opstream& os ) +{ + TView::write( os ); + os.writeBytes(board, sizeof(board)); + os << moves << solved; +} + + +void *TPuzzleView::read( ipstream& is ) +{ + TView::read( is ); + is.readBytes(board, sizeof(board)); + is >> moves >> solved; + return this; +} + + +TStreamable *TPuzzleView::build() +{ + return new TPuzzleView( streamableInit ); +} + + +TStreamableClass RPuzzleView( TPuzzleView::name, + TPuzzleView::build, + __DELTA(TPuzzleView) + ); + + +static char boardStart[16] = + { 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', + 'M', 'N', 'O', ' ' + }; + +static char map[15] = + { 0, 1, 0, 1, + 1, 0, 1, 0, + 0, 1, 0, 1, + 1, 0, 1 + }; + + +TPuzzleView::TPuzzleView(TRect& r) : TView(r) +{ + srand(time(NULL)); + options |= ofSelectable; + memset( board, ' ', sizeof(board) ); + + for(int i = 0; i <= 3; i++) + for(int j = 0; j <= 3; j++) + board[i][j] = boardStart[i*4+j]; + + scramble(); +} + + +void TPuzzleView::draw() +{ + char tmp[8]; + char color[2], colorBack; + TDrawBuffer buf; + + color[0] = color[1] = colorBack = getColor(1); + if (!solved) + color[1] = getColor(2); + + /* SS: little change */ + short i; + for(i = 0; i <= 3; i++) + //for(short i = 0; i <= 3; i++) + { + buf.moveChar(0, ' ', colorBack, 18); + if(i == 1) + buf.moveStr(13, "Move", colorBack); + if(i == 2) + { + sprintf(tmp, "%d", moves); + buf.moveStr(14, tmp, colorBack); + } + for(short j = 0; j <= 3; j++) + { + strcpy(tmp, " "); + tmp[1] = board[i][j]; + if(board[i][j] == ' ') + buf.moveStr( (short)(j*3), tmp, color[0]); + else + buf.moveStr( (short)(j*3), tmp, + color[(int) map[board[i][j]-'A']]); + } + writeLine(0, i, 18, 1, buf); + } +} + + +TPalette& TPuzzleView::getPalette() const +{ + static TPalette palette( cpPuzzlePalette, sizeof(cpPuzzlePalette)-1 ); + return palette; +} + + +void TPuzzleView::handleEvent(TEvent& event) +{ + TView::handleEvent(event); + + if (solved && (event.what & (evKeyboard | evMouse) ) ) + { + scramble(); + clearEvent(event); + } + + if(event.what == evMouseDown) + { + moveTile(event.mouse.where); + clearEvent(event); + winCheck(); + } + else if(event.what == evKeyDown) + { + moveKey(event.keyDown.keyCode); + clearEvent(event); + winCheck(); + } +} + +void TPuzzleView::moveKey(int key) +{ + /* SS: little change */ + int i; + for(i = 0; i <= 15; i++) +// for(int i = 0; i <= 15; i++) + if(board[i/4][i%4] == ' ') + break; + + int x = i % 4; + int y = i / 4; + + switch(key) + { + case kbDown: + if (y > 0) + { + board[y][x] = board[y-1][x]; + board[y-1][x] = ' '; + if(moves < 1000) + moves++; + } + break; + + case kbUp: + if (y < 3) + { + board[y][x] = board[y+1][x]; + board[y+1][x] = ' '; + if(moves < 1000) + moves++; + } + break; + + case kbRight: + if (x > 0) + { + board[y][x] = board[y][x-1]; + board[y][x-1] = ' '; + if(moves < 1000) + moves++; + } + break; + + case kbLeft: + if (x < 3) + { + board[y][x] = board[y][x+1]; + board[y][x+1] = ' '; + if(moves < 1000) + moves++; + } + break; + } + drawView(); +} + +void TPuzzleView::moveTile(TPoint p) +{ + p = makeLocal(p); + + /* SS: little change */ + int i; + for(i = 0; i <= 15; i++) +// for(int i = 0; i <= 15; i++) + if(board[i/4][i%4] == ' ') + break; + int x = p.x / 3; + int y = p.y; + + switch( (y*4 + x - i) ) + { + case -4: // Piece moves down + moveKey(kbDown); + break; + + case -1: // Piece moves right + moveKey(kbRight); + break; + + case 1: // Piece moves left + moveKey(kbLeft); + break; + + case 4: // Piece moves up + moveKey(kbUp); + break; + + } + drawView(); +} + +void TPuzzleView::scramble() +{ + moves = 0; + solved = 0; + do + { + switch( (rand() >> 4) % 4) + { + case 0: + moveKey(kbUp); + break; + + case 1: + moveKey(kbDown); + break; + + case 2: + moveKey(kbRight); + break; + + case 3: + moveKey(kbLeft); + break; + } + } while (moves++ <= 500); + + moves = 0; + drawView(); +} + + +static char *solution = "ABCDEFGHIJKLMNO "; + +void TPuzzleView::winCheck() +{ + /* SS: little change */ + int i; + for(i = 0; i <= 15; i++) +// for(int i = 0; i <= 15; i++) + if(board[i/4][i%4] != solution[i]) + break; + + if(i == 16) + solved = 1; + drawView(); +} + + +// +// TPuzzleWindow functions +// + +const char * const TPuzzleWindow::name = "TPuzzleWindow"; + + +void TPuzzleWindow::write( opstream& os ) +{ + TWindow::write( os ); +} + + +void *TPuzzleWindow::read( ipstream& is ) +{ + TWindow::read( is ); + return this; +} + + +TStreamable *TPuzzleWindow::build() +{ + return new TPuzzleWindow( streamableInit ); +} + + +TStreamableClass RPuzzleWindow( TPuzzleWindow::name, + TPuzzleWindow::build, + __DELTA(TPuzzleWindow) + ); + + +TPuzzleWindow::TPuzzleWindow() : + TWindowInit( &TPuzzleWindow::initFrame ) + , TWindow( TRect(1, 1, 21, 7), "Puzzle", wnNoNumber) +{ + flags &= ~(wfZoom | wfGrow); + growMode = 0; + + TRect r = getExtent(); + r.grow(-1, -1); + insert( new TPuzzleView(r) ); +} diff --git a/tvision/examples/demo/puzzle.h b/tvision/examples/demo/puzzle.h new file mode 100644 index 0000000..f3db61c --- /dev/null +++ b/tvision/examples/demo/puzzle.h @@ -0,0 +1,102 @@ +/*---------------------------------------------------------*/ +/* */ +/* Puzzle.h : Header file for puzzle.cpp */ +/* */ +/*---------------------------------------------------------*/ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + */ + +#if !defined( __PUZZLE_H ) +#define __PUZZLE_H + +class TPuzzleView : public TView +{ + +public: + + TPuzzleView(TRect& r); + TPuzzleView( StreamableInit ) : TView(streamableInit) { }; + virtual TPalette& getPalette() const; + virtual void handleEvent(TEvent& event); + virtual void draw(); + void moveKey(int key); + void moveTile(TPoint point); + void scramble(); + void winCheck(); + +private: + + char board[6][6]; + int moves; + char solved; + + virtual const char *streamableName() const + { return name; } + +protected: + + virtual void write( opstream& ); + virtual void *read( ipstream& ); + +public: + + static const char * const name; + static TStreamable *build(); + +}; + +inline ipstream& operator >> ( ipstream& is, TPuzzleView& cl ) + { return is >> (TStreamable&) cl; } +inline ipstream& operator >> ( ipstream& is, TPuzzleView*& cl ) + { return is >> (void *&) cl; } + +inline opstream& operator << ( opstream& os, TPuzzleView& cl ) + { return os << (TStreamable&) cl; } +inline opstream& operator << ( opstream& os, TPuzzleView* cl ) + { return os << (TStreamable *) cl; } + + +class TPuzzleWindow : public TWindow +{ + +public: + + TPuzzleWindow(); + TPuzzleWindow( StreamableInit ) : + TWindowInit(&TPuzzleWindow::initFrame) + , TWindow(streamableInit) { }; + +private: + + virtual const char *streamableName() const + { return name; } + +protected: + + virtual void write( opstream& ); + virtual void *read( ipstream& ); + +public: + + static const char * const name; + static TStreamable *build(); + +}; + +inline ipstream& operator >> ( ipstream& is, TPuzzleWindow& cl ) + { return is >> (TStreamable&) cl; } +inline ipstream& operator >> ( ipstream& is, TPuzzleWindow*& cl ) + { return is >> (void *&) cl; } + +inline opstream& operator << ( opstream& os, TPuzzleWindow& cl ) + { return os << (TStreamable&) cl; } +inline opstream& operator << ( opstream& os, TPuzzleWindow* cl ) + { return os << (TStreamable *) cl; } + + +#endif // __PUZZLE_H diff --git a/tvision/examples/demo/rhide.env b/tvision/examples/demo/rhide.env new file mode 100644 index 0000000..56091d7 --- /dev/null +++ b/tvision/examples/demo/rhide.env @@ -0,0 +1,5 @@ +# +# This include file have rhide options for all the subprojects. +# +include ../rhide.env + diff --git a/tvision/examples/demo/tvcmds.h b/tvision/examples/demo/tvcmds.h new file mode 100644 index 0000000..f2d5252 --- /dev/null +++ b/tvision/examples/demo/tvcmds.h @@ -0,0 +1,28 @@ +/*-----------------------------------------------------*/ +/* */ +/* Tvcmds.h : Constants for TVDemo events */ +/* */ +/*-----------------------------------------------------*/ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + */ + +const int cmAboutCmd = 105; // JASC, conflict with standard cmOpen +const int cmPuzzleCmd = 101; +const int cmCalendarCmd = 102; +const int cmAsciiCmd = 103; +const int cmCalcCmd = 104; +#define cmOpenCmd cmOpen +const int cmChDirCmd = 106; +// SET: Use cmCallShell instead +//const int cmDOS_Cmd = 107; +const int cmMouseCmd = 108; +const int cmColorCmd = 109; +const int cmSaveCmd = 110; +const int cmRestoreCmd = 111; +const int cmTestInputBox= 112; +const int cmTestPicture = 113; diff --git a/tvision/examples/demo/tvdemo.h b/tvision/examples/demo/tvdemo.h new file mode 100644 index 0000000..00d1608 --- /dev/null +++ b/tvision/examples/demo/tvdemo.h @@ -0,0 +1,71 @@ +/*---------------------------------------------------------*/ +/* */ +/* TVDemo.h : Header file for TVDemo.cpp */ +/* */ +/*---------------------------------------------------------*/ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + */ + +class TStatusLine; +class TMenuBar; +struct TEvent; +class TPalette; +class THeapView; +class TClockView; +class fpstream; + +class TVDemo : public TApplication +{ + +public: + + TVDemo( int argc, char **argv ); + static TStatusLine *initStatusLine( TRect r ); + static TMenuBar *initMenuBar( TRect r ); + virtual void handleEvent(TEvent& Event); + virtual void getEvent(TEvent& event); + virtual TPalette& getPalette() const; + virtual void idle(); // Updates heap and clock views + +private: + + THeapView *heap; // Heap view + TClockView *clock; // Clock view + + void aboutDlgBox(); // "About" box + void puzzle(); // Puzzle + void calendar(); // Calendar + void asciiTable(); // Ascii table + void calculator(); // Calculator + void openFile( char *fileSpec ); // File Viewer + void changeDir(); // Change directory + void shell(); // DOS shell + void tile(); // Tile windows + void cascade(); // Cascade windows + void mouse(); // Mouse control dialog box + void colors(); // Color control dialog box + void outOfMemory(); // For validView() function + void loadDesktop(fpstream& s); // Load and restore the + void retrieveDesktop(); // previously saved desktop + void storeDesktop(fpstream& s); // Store the current desktop + void saveDesktop(); // in a resource file + void testInputBox(); // SET: Just a test to show inputBox use + void testPictureVal(); // SET: Just a test for the picture validator + + // In original demo that's a CP 437 specific code. I left it but I use + // it to show how to solve this using the new code page features of + // this port of TV. + static uchar systemMenuIcon[]; // Menu name for the "system menu" + // encoded in current code page + static uchar osystemMenuIcon[]; // Same encoded in CP 437, used as + // reference. +public: + // Previous callback in the code page chain + static TVCodePageCallBack oldCPCallBack; + static void cpCallBack(ushort *map); // That's our callback +}; diff --git a/tvision/examples/demo/tvdemo1.cc b/tvision/examples/demo/tvdemo1.cc new file mode 100644 index 0000000..1f6ae0e --- /dev/null +++ b/tvision/examples/demo/tvdemo1.cc @@ -0,0 +1,327 @@ +/*----------------------------------------------------------*/ +/* */ +/* Turbo Vision TVDEMO source file */ +/* */ +/*----------------------------------------------------------*/ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + */ +/* + * Modified by Sergio Sigala + * Modified to compile with gcc v3.x by Salvador E. Tropea, with the help of + * Andris Pavenis. + * Added code page example by Salvador E. Tropea (SET) + */ + +// SET: moved the standard headers before tv.h +#include +#define Uses_string + +#define Uses_TVCodePage +#define Uses_TView +#define Uses_TRect +#define Uses_TStatusLine +#define Uses_TStatusDef +#define Uses_TStatusItem +#define Uses_TKeys +#define Uses_MsgBox +#define Uses_fpstream +#define Uses_TEvent +#define Uses_TDeskTop +#define Uses_TApplication +#define Uses_TWindow +#define Uses_TDeskTop +#define Uses_TScreen +#define Uses_IOS_BIN +#define Uses_THelpWindow +// Needed to remap the "system" menu character +#define Uses_TVCodePage +#define Uses_TStreamableClass + +#include + +#include "tvdemo.h" +#include "gadgets.h" +#include "fileview.h" +#include "puzzle.h" +#include "demohelp.h" + +UsingNamespaceStd + +/* SS: changed */ + +//#ifdef __DPMI32__ +#define HELP_FILENAME "demohelp.h32" +//#else +//#define HELP_FILENAME "DEMOHELP.H16" +//#endif + +__link(RCalculator); +__link(RCalcDisplay); +// +// main: create an application object. Constructor takes care of all +// initialization. Calling run() from TProgram makes it tick and +// the destructor will destroy the world. +// +// File names can be specified on the command line for automatic +// opening. +// + +int main(int argc, char **argv, char **envir) +{ + // The following is optional, but helps some low level drivers. + // Don't do it if you experiment any side effect in the arguments or you + // use these variables in a not so common way. + // Note that the Linux console driver will alter argv to be able to change + // what ps reports, you'll get the setWindowTitle argument. + TDisplay::setArgv(argc,argv,envir); + + // Uncommenting the next line the cursor won't be hided. + // This is a test to get an application a little bit friendly for Braille + // Terminals. + //TDisplay::setShowCursorEver(True); + + // We have non-ASCII symbols that depends on the code page. We must + // recode them to the screen code page, here is how we hook the code page + // change chain. + TVDemo::oldCPCallBack=TVCodePage::SetCallBack(TVDemo::cpCallBack); + + TVDemo *demoProgram = new TVDemo(argc,argv); + + // This is new in our port of TV: + const char *title=TScreen::getWindowTitle(); + TScreen::setWindowTitle("Turbo Vision Demo Program"); + demoProgram->run(); + + TObject::CLY_destroy( demoProgram ); + if( title ) + { + TScreen::setWindowTitle(title); + delete[] title; + } + + return 0; +} + + +// +// Constructor for the application. Command line parameters are interpreted +// as file names and opened. Wildcards are accepted and put up a dialog +// box with the appropriate search path. +// + +TVDemo::TVDemo( int argc, char **argv ) : + TProgInit( &TVDemo::initStatusLine, + &TVDemo::initMenuBar, + &TVDemo::initDeskTop ) +{ + TView *w; + char fileSpec[128]; + int len; + + TRect r = getExtent(); // Create the clock view. + r.a.x = r.b.x - 9; r.b.y = r.a.y + 1; + clock = new TClockView( r ); + insert(clock); + + r = getExtent(); // Create the heap view. + r.a.x = r.b.x - 13; r.a.y = r.b.y - 1; + heap = new THeapView( r ); + insert(heap); + + while (--argc > 0) // Display files specified + { // on command line. + strcpy( fileSpec, *++argv ); + len = strlen( fileSpec ); + + /* SS: changed */ + + if( fileSpec[len-1] == '/' ) + strcat( fileSpec, "*" ); + if( strchr( fileSpec, '*' ) || strchr( fileSpec, '?' ) ) + openFile( fileSpec ); + else + { + w = validView( new TFileWindow( fileSpec ) ); + if( w != 0 ) + deskTop->insert(w); + } + } + +} + + +// +// DemoApp::getEvent() +// Event loop to check for context help request +// + +void TVDemo::getEvent(TEvent &event) +{ + TWindow *w; + THelpFile *hFile; + fpstream *helpStrm; + static Boolean helpInUse = False; + + TApplication::getEvent(event); + switch (event.what) + { + case evCommand: + if ((event.message.command == cmHelp) && ( helpInUse == False)) + { + helpInUse = True; + helpStrm = new fpstream(HELP_FILENAME, CLY_IOSIn|CLY_IOSBin); + hFile = new THelpFile(*helpStrm); + if (!helpStrm) + { + messageBox("Could not open help file", mfError | mfOKButton); + delete hFile; + } + else + { + w = new THelpWindow(hFile, getHelpCtx()); + if (validView(w) != 0) + { + execView(w); + CLY_destroy(w); + } + clearEvent(event); + } + helpInUse = False; + } + break; + case evMouseDown: + if (event.mouse.buttons != 1) + event.what = evNothing; + break; + } + +} + +// +// Create statusline. +// + +TStatusLine *TVDemo::initStatusLine( TRect r ) +{ + r.a.y = r.b.y - 1; + + return (new TStatusLine( r, + *new TStatusDef( 0, 50 ) + + *new TStatusItem( "~F1~ Help", kbF1, cmHelp ) + + *new TStatusItem( "~Alt-X~ Exit", kbAltX, cmQuit ) + + *new TStatusItem( 0, kbAltF3, cmClose ) + + *new TStatusItem( 0, kbF10, cmMenu ) + + *new TStatusItem( 0, kbF5, cmZoom ) + + *new TStatusItem( 0, kbCtrlF5, cmResize ) + + *new TStatusDef( 50, 0xffff ) + + *new TStatusItem( "Howdy", kbF1, cmHelp ) + ) + ); +} + + +// +// Puzzle function +// + +void TVDemo::puzzle() +{ + TPuzzleWindow *puzz = (TPuzzleWindow *) validView(new TPuzzleWindow); + + if(puzz != 0) + { + puzz->helpCtx = hcPuzzle; + deskTop->insert(puzz); + } +} + + +// +// retrieveDesktop() function ( restores the previously stored Desktop ) +// + +// SET: Mike modified it to lowercase, is less annoying on POSIX systems +static const char *TVDemoFile="tvdemo.dst"; + +void TVDemo::retrieveDesktop() +{ + /* SS: changed */ + +// struct ffblk ffblk; + +// if (findfirst("TVDEMO.DST", &ffblk, 0)) + FILE *fp; + if ((fp = fopen(TVDemoFile, "r")) == NULL) + messageBox("Could not find desktop file", mfOKButton | mfError); + else + { + fclose(fp); + fpstream *f = new fpstream(TVDemoFile, CLY_IOSIn|CLY_IOSBin); + if( !f ) + messageBox("Could not open desktop file", mfOKButton | mfError); + else + { + TVDemo::loadDesktop(*f); + if( !f ) + messageBox("Error reading desktop file", mfOKButton | mfError); + } + delete f; + } +} + +// +// saveDesktop() function ( saves the DeskTop by calling storeDesktop function ) +// + +void TVDemo::saveDesktop() +{ + fpstream *f = new fpstream(TVDemoFile, CLY_IOSOut | CLY_IOSBin); + + if( f ) + { + TVDemo::storeDesktop(*f); + if( !f ) + { + messageBox("Could not create tvdemo.dst.", mfOKButton | mfError); + delete f; + ::remove(TVDemoFile); + return; + } + } + delete f; +} + +// +// writeView() function ( writes a view object to a resource file ) +// + +static void writeView(TView *p, void *strm) +{ + fpstream *s = (fpstream *) strm; + if (p != TProgram::deskTop->last) + *s << p; +} + +// +// storeDesktop() function ( stores the Desktop in a resource file ) +// + +void TVDemo::storeDesktop(fpstream& s) +{ + deskTop->forEach(::writeView, &s); + s << 0; +} + +// +// Tile function +// + +void TVDemo::tile() +{ + deskTop->tile( deskTop->getExtent() ); +} diff --git a/tvision/examples/demo/tvdemo2.cc b/tvision/examples/demo/tvdemo2.cc new file mode 100644 index 0000000..f1358e1 --- /dev/null +++ b/tvision/examples/demo/tvdemo2.cc @@ -0,0 +1,430 @@ +/*----------------------------------------------------------*/ +/* */ +/* Turbo Vision TVDEMO source file */ +/* */ +/*----------------------------------------------------------*/ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + */ +/* + * Modified by Sergio Sigala + */ + +// SET: moved the standard headers before tv.h + +#define Uses_stdlib +#define Uses_signal +#define Uses_TDialog +#define Uses_TRect +#define Uses_TStaticText +#define Uses_TButton +#define Uses_TEvent +#define Uses_TWindow +#define Uses_TColorGroup +#define Uses_TColorItem +#define Uses_TColorDialog +#define Uses_TPalette +#define Uses_TDeskTop +#define Uses_TApplication +#define Uses_TChDirDialog +#define Uses_TScreen +#define Uses_TCalculator +// Needed to remap the "system" menu character +#define Uses_TVCodePage +// Needed for the inputBoxTest +#define Uses_MsgBox +#define Uses_TPXPictureValidator + +#define Uses_TEditor // JASC 2006, cmOpen +#include + +#include "tvdemo.h" +#include "fileview.h" +#include "tvcmds.h" +#include "demohelp.h" +#include "ascii.h" +#include "calendar.h" + +// +// DOS/UNIX Shell Command. +// + +void TVDemo::shell() +{ + /* SS: this simulates a Ctrl-Z */ + /*raise(SIGTSTP);*/ /* stop the process */ + suspend(); + TScreen::System(CLY_GetShellName()); + resume(); + redraw(); +} + +void TVDemo::testInputBox() +{ + char buffer[20]; + strcpy(buffer,"Initial value"); + if (inputBox("Test for the inputBox","Enter a number",buffer,20)!=cmCancel) + { + messageBox(mfInformation | mfOKButton,"Value entered: %s",buffer); + } + else + { + messageBox("\x3""Input canceled", mfInformation | mfOKButton); + } +} + +void TVDemo::testPictureVal() +{ + char buffer[20]; + strcpy(buffer,"11-6789"); + if (inputBox("Test for the inputBox","Enter ##-####",buffer,20, + // You can add a picture validator like this + new TPXPictureValidator("##-####",True))!=cmCancel) + { + messageBox(mfInformation | mfOKButton,"Value entered: %s",buffer); + } + else + { + messageBox("\x3""Input canceled", mfInformation | mfOKButton); + } +} + +// +// DemoApp::handleEvent() +// Event loop to distribute the work. +// + +void TVDemo::handleEvent(TEvent &event) +{ + TApplication::handleEvent(event); + + if (event.what == evCommand) + { + switch (event.message.command) + { + case cmAboutCmd: // About Dialog Box + aboutDlgBox(); + break; + + case cmCalendarCmd: // Calendar Window + calendar(); + break; + + case cmAsciiCmd: // Ascii Table + asciiTable(); + break; + + case cmCalcCmd: // Calculator + calculator(); + break; + + case cmPuzzleCmd: // Puzzle + puzzle(); + break; + + case cmOpenCmd: // View a file + // SET: Even DOS port needs it. + if ( event.message.infoPtr ) // JASC, drag 'n' drop + { TView *w= validView( new TFileWindow( (char *)event.message.infoPtr ) ); + if( w != 0 ) + { deskTop->insert(w); + } + } + else + { openFile("*"); + } + break; + + case cmChDirCmd: // Change directory + changeDir(); + break; + + case cmCallShell: // DOS shell + shell(); + break; + + case cmTile: // Tile current file windows + tile(); + break; + + case cmCascade: // Cascade current file windows + cascade(); + break; + + case cmMouseCmd: // Mouse control dialog box + mouse(); + break; + + case cmColorCmd: // Color control dialog box + colors(); + break; + + case cmSaveCmd: // Save current desktop + saveDesktop(); + break; + + case cmRestoreCmd: // Restore saved desktop + retrieveDesktop(); + break; + + case cmTestInputBox: + testInputBox(); + break; + + case cmTestPicture: + testPictureVal(); + break; + + default: // Unknown command + return; + + } + clearEvent (event); + } +} + + +ushort executeDialog( TDialog* pD, void* data=0 ) +{ + ushort c=cmCancel; + + if (TProgram::application->validView(pD)) + { + if (data) + pD->setData(data); + c = TProgram::deskTop->execView(pD); + if ((c != cmCancel) && (data)) + pD->getData(data); + CLY_destroy(pD); + } + + return c; +} + +// +// About Box function() +// + +void TVDemo::aboutDlgBox() +{ + TDialog *aboutBox = new TDialog(TRect(0, 0, 39, 13), "About"); + + aboutBox->insert( + new TStaticText(TRect(9, 2, 30, 9), + "\003Turbo Vision Demo\n\n" // These strings will be + "\003C++ Version\n\n" // concatenated by the compiler. + "\003Copyright (c) 1994\n\n" // The \003 centers the line. + "\003Borland International" + ) + ); + + aboutBox->insert( + new TButton(TRect(14, 10, 26, 12), " OK", cmOK, bfDefault) + ); + + aboutBox->options |= ofCentered; + + executeDialog(aboutBox); + +} + + +// +// Ascii Chart function +// + +void TVDemo::asciiTable() +{ + TAsciiChart *chart = (TAsciiChart *) validView(new TAsciiChart); + + if(chart != 0) + { + chart->helpCtx = hcAsciiTable; + deskTop->insert(chart); + } +} + + +// +// Calendar function() +// + +void TVDemo::calendar() +{ + TCalendarWindow *cal = (TCalendarWindow *) validView(new TCalendarWindow); + + if(cal != 0) + { + cal->helpCtx = hcCalendar; + deskTop->insert( cal ); + } +} + + +// +// Calculator function +// + +void TVDemo::calculator() +{ + TCalculator *calc = (TCalculator *) validView(new TCalculator); + + if(calc != 0) + { + calc->helpCtx = hcCalculator; + deskTop->insert(calc); + } +} + +// +// Cascade function +// + +void TVDemo::cascade() +{ + deskTop->cascade( deskTop->getExtent() ); +} + + +// +// Change Directory function +// + +void TVDemo::changeDir() +{ + TView *d = validView( new TChDirDialog( 0, cmChangeDir ) ); + + if( d != 0 ) + { + d->helpCtx = hcFCChDirDBox; + deskTop->execView( d ); + CLY_destroy(d); + } +} + + +// +// Color Control Dialog Box function +// + +void TVDemo::colors() +{ + TColorGroup &group1 = + *new TColorGroup("Desktop") + + *new TColorItem("Color", 1)+ + + *new TColorGroup("Menus") + + *new TColorItem("Normal", 2)+ + *new TColorItem("Disabled", 3)+ + *new TColorItem("Shortcut", 4)+ + *new TColorItem("Selected", 5)+ + *new TColorItem("Selected disabled", 6)+ + *new TColorItem("Shortcut selected", 7 + ); + + TColorGroup &group2 = + *new TColorGroup("Dialogs/Calc") + + *new TColorItem("Frame/background", 33)+ + *new TColorItem("Frame icons", 34)+ + *new TColorItem("Scroll bar page", 35)+ + *new TColorItem("Scroll bar icons", 36)+ + *new TColorItem("Static text", 37)+ + + *new TColorItem("Label normal", 38)+ + *new TColorItem("Label selected", 39)+ + *new TColorItem("Label shortcut", 40 + ); + + TColorItem &item_coll1 = + *new TColorItem("Button normal", 41)+ + *new TColorItem("Button default", 42)+ + *new TColorItem("Button selected", 43)+ + *new TColorItem("Button disabled", 44)+ + *new TColorItem("Button shortcut", 45)+ + *new TColorItem("Button shadow", 46)+ + *new TColorItem("Cluster normal", 47)+ + *new TColorItem("Cluster selected", 48)+ + *new TColorItem("Cluster shortcut", 49 + ); + + TColorItem &item_coll2 = + *new TColorItem("Input normal", 50)+ + *new TColorItem("Input selected", 51)+ + *new TColorItem("Input arrow", 52)+ + + *new TColorItem("History button", 53)+ + *new TColorItem("History sides", 54)+ + *new TColorItem("History bar page", 55)+ + *new TColorItem("History bar icons", 56)+ + + *new TColorItem("List normal", 57)+ + *new TColorItem("List focused", 58)+ + *new TColorItem("List selected", 59)+ + *new TColorItem("List divider", 60)+ + + *new TColorItem("Information pane", 61 + ); + + group2 = group2 + item_coll1 + item_coll2; + + TColorGroup &group3 = + *new TColorGroup("Viewer") + + *new TColorItem("Frame passive", 8)+ + *new TColorItem("Frame active", 9)+ + *new TColorItem("Frame icons", 10)+ + *new TColorItem("Scroll bar page", 11)+ + *new TColorItem("Scroll bar icons", 12)+ + *new TColorItem("Text", 13)+ + *new TColorGroup("Puzzle")+ + *new TColorItem("Frame passive", 8)+ + *new TColorItem("Frame active", 9)+ + *new TColorItem("Frame icons", 10)+ + *new TColorItem("Scroll bar page", 11)+ + *new TColorItem("Scroll bar icons", 12)+ + *new TColorItem("Normal text", 13)+ + *new TColorItem("Highlighted text", 14 + ); + + + TColorGroup &group4 = + *new TColorGroup("Calendar") + + *new TColorItem("Frame passive", 16)+ + *new TColorItem("Frame active", 17)+ + *new TColorItem("Frame icons", 18)+ + *new TColorItem("Scroll bar page", 19)+ + *new TColorItem("Scroll bar icons", 20)+ + *new TColorItem("Normal text", 21)+ + *new TColorItem("Current day", 22)+ + + *new TColorGroup("Ascii table") + + *new TColorItem("Frame passive", 24)+ + *new TColorItem("Frame active", 25)+ + *new TColorItem("Frame icons", 26)+ + *new TColorItem("Scroll bar page", 27)+ + *new TColorItem("Scroll bar icons", 28)+ + *new TColorItem("Text", 29 + ); + + + TColorGroup &group5 = group1 + group2 + group3 + group4; + + TPalette *temp_pal=new TPalette(getPalette()); + TColorDialog *c = new TColorDialog(temp_pal, &group5 ); + + if( validView( c ) != 0 ) + { + c->helpCtx = hcOCColorsDBox; // set context help constant + c->setData(&getPalette()); + if( deskTop->execView( c ) != cmCancel ) + { + getPalette() = *(c->pal); + setScreenMode(TScreen::screenMode); + } + CLY_destroy(c); + } + delete temp_pal; +} diff --git a/tvision/examples/demo/tvdemo3.cc b/tvision/examples/demo/tvdemo3.cc new file mode 100644 index 0000000..e84b797 --- /dev/null +++ b/tvision/examples/demo/tvdemo3.cc @@ -0,0 +1,273 @@ +/*----------------------------------------------------------*/ +/* */ +/* Turbo Vision TVDEMO source file */ +/* */ +/*----------------------------------------------------------*/ +/* + * Turbo Vision - Version 2.0 + * + * Copyright (c) 1994 by Borland International + * All Rights Reserved. + * + */ +/* + * Modified by Sergio Sigala + * Added code page example by Salvador E. Tropea (SET) + */ + +#define Uses_TRect +#define Uses_TMenuBar +#define Uses_TSubMenu +#define Uses_TMenuItem +#define Uses_TKeys +#define Uses_fpstream +#define Uses_TView +#define Uses_TPalette +#define Uses_MsgBox +#define Uses_TFileDialog +#define Uses_TApplication +#define Uses_TDeskTop +#define Uses_TStaticText +#define Uses_TDialog +#define Uses_TEventQueue +#define Uses_TEditor // JASC 2006 cmOpen +// Needed to remap the "system" menu character +#define Uses_TVCodePage + +#include + +#include "tvdemo.h" +#include "tvcmds.h" +#include "gadgets.h" +#include "mousedlg.h" +#include "demohelp.h" +#include "fileview.h" +#include "calendar.h" + +uchar TVDemo::systemMenuIcon[]="~\360~"; +uchar TVDemo::osystemMenuIcon[]="~\360~"; +TVCodePageCallBack TVDemo::oldCPCallBack=NULL; + +// +// Mouse Control Dialog Box function +// + +void TVDemo::mouse() +{ + TMouseDialog *mouseCage = (TMouseDialog *) validView( new TMouseDialog() ); + + if (mouseCage != 0) + { + mouseCage->helpCtx = hcOMMouseDBox; + mouseCage->setData(&(TEventQueue::mouseReverse)); + if (deskTop->execView(mouseCage) != cmCancel) + mouseCage->getData(&(TEventQueue::mouseReverse)); + } + CLY_destroy(mouseCage); + +} + + +// +// File Viewer function +// + +void TVDemo::openFile( char *fileSpec ) +{ + TFileDialog *d= (TFileDialog *)validView( + new TFileDialog(fileSpec, "Open a File", "~N~ame", fdOpenButton, 100 )); + + if( d != 0 && deskTop->execView( d ) != cmCancel ) + { + char fileName[PATH_MAX]; + d->getFileName( fileName ); + d->helpCtx = hcFOFileOpenDBox; + TView *w= validView( new TFileWindow( fileName ) ); + if( w != 0 ) + deskTop->insert(w); + } + CLY_destroy(d); +} + + +// +// "Out of Memory" function ( called by validView() ) +// + +void TVDemo::outOfMemory() +{ + messageBox( "Not enough memory available to complete operation.", + mfError | mfOKButton ); +} + +// +// getPalette() function ( returns application's palette ) +// +#define cpAppColor \ + "\x71\x70\x78\x74\x20\x28\x24\x17\x1F\x1A\x31\x31\x1E\x71\x1F" \ + "\x37\x3F\x3A\x13\x13\x3E\x21\x3F\x70\x7F\x7A\x13\x13\x70\x7F\x7E" \ + "\x70\x7F\x7A\x13\x13\x70\x70\x7F\x7E\x20\x2B\x2F\x78\x2E\x70\x30" \ + "\x3F\x3E\x1F\x2F\x1A\x20\x72\x31\x31\x30\x2F\x3E\x31\x13\x38\x00" \ + "\x17\x1F\x1A\x71\x71\x1E\x17\x1F\x1E\x20\x2B\x2F\x78\x2E\x10\x30" \ + "\x3F\x3E\x70\x2F\x7A\x20\x12\x31\x31\x30\x2F\x3E\x31\x13\x38\x00" \ + "\x37\x3F\x3A\x13\x13\x3E\x30\x3F\x3E\x20\x2B\x2F\x78\x2E\x30\x70" \ + "\x7F\x7E\x1F\x2F\x1A\x20\x32\x31\x71\x70\x2F\x7E\x71\x13\x78\x00" \ + "\x37\x3F\x3A\x13\x13\x30\x3E\x1E" // help colors + +#define cpAppBlackWhite \ + "\x70\x70\x78\x7F\x07\x07\x0F\x07\x0F\x07\x70\x70\x07\x70\x0F" \ + "\x07\x0F\x07\x70\x70\x07\x70\x0F\x70\x7F\x7F\x70\x07\x70\x07\x0F" \ + "\x70\x7F\x7F\x70\x07\x70\x70\x7F\x7F\x07\x0F\x0F\x78\x0F\x78\x07" \ + "\x0F\x0F\x0F\x70\x0F\x07\x70\x70\x70\x07\x70\x0F\x07\x07\x08\x00" \ + "\x07\x0F\x0F\x07\x70\x07\x07\x0F\x0F\x70\x78\x7F\x08\x7F\x08\x70" \ + "\x7F\x7F\x7F\x0F\x70\x70\x07\x70\x70\x70\x07\x7F\x70\x07\x78\x00" \ + "\x70\x7F\x7F\x70\x07\x70\x70\x7F\x7F\x07\x0F\x0F\x78\x0F\x78\x07" \ + "\x0F\x0F\x0F\x70\x0F\x07\x70\x70\x70\x07\x70\x0F\x07\x07\x08\x00" \ + "\x07\x0F\x07\x70\x70\x07\x0F\x70" // help colors + +#define cpAppMonochrome \ + "\x70\x07\x07\x0F\x70\x70\x70\x07\x0F\x07\x70\x70\x07\x70\x00" \ + "\x07\x0F\x07\x70\x70\x07\x70\x00\x70\x70\x70\x07\x07\x70\x07\x00" \ + "\x70\x70\x70\x07\x07\x70\x70\x70\x0F\x07\x07\x0F\x70\x0F\x70\x07" \ + "\x0F\x0F\x07\x70\x07\x07\x70\x07\x07\x07\x70\x0F\x07\x07\x70\x00" \ + "\x70\x70\x70\x07\x07\x70\x70\x70\x0F\x07\x07\x0F\x70\x0F\x70\x07" \ + "\x0F\x0F\x07\x70\x07\x07\x70\x07\x07\x07\x70\x0F\x07\x07\x01\x00" \ + "\x70\x70\x70\x07\x07\x70\x70\x70\x0F\x07\x07\x0F\x70\x0F\x70\x07" \ + "\x0F\x0F\x07\x70\x07\x07\x70\x07\x07\x07\x70\x0F\x07\x07\x01\x00" \ + "\x07\x0F\x07\x70\x70\x07\x0F\x70" // help colors + +TPalette& TVDemo::getPalette() const +{ + static TPalette newcolor ( cpAppColor , sizeof( cpAppColor )-1 ); + static TPalette newblackwhite( cpAppBlackWhite , sizeof( cpAppBlackWhite )-1 ); + static TPalette newmonochrome( cpAppMonochrome , sizeof( cpAppMonochrome )-1 ); + static TPalette *palettes[] = + { + &newcolor, + &newblackwhite, + &newmonochrome + }; + return *(palettes[appPalette]); + +} + + +// +// isTileable() function ( checks a view on desktop is tileable or not ) +// + +static Boolean isTileable(TView *p, void * ) +{ + if( (p->options & ofTileable) != 0) + return True; + else + return False; +} + +// +// idle() function ( updates heap and clock views for this program. ) +// + +void TVDemo::idle() +{ + TProgram::idle(); + clock->update(); + heap->update(); + if (deskTop->firstThat(isTileable, 0) != 0 ) + { + enableCommand(cmTile); + enableCommand(cmCascade); + } + else + { + disableCommand(cmTile); + disableCommand(cmCascade); + } +} + +// +// closeView() function +// + +static void closeView(TView *p, void *p1) +{ + message(p, evCommand, cmClose, p1); +} + +// +// loadDesktop() function +// + +void TVDemo::loadDesktop(fpstream &s) +{ + TView *p; + + if (deskTop->valid(cmClose)) + { + deskTop->forEach(::closeView, 0); // Clear the desktop + do { + s >> p; + deskTop->insertBefore(validView(p), deskTop->last); + } + while (p != 0); + } +} + +// +// Menubar initialization. +// + +TMenuBar *TVDemo::initMenuBar(TRect r) +{ + TSubMenu& sub1 = + *new TSubMenu( (char *)systemMenuIcon, 0, hcSystem ) + + *new TMenuItem( "~A~bout...", cmAboutCmd, kbNoKey, hcSAbout ) + + newLine() + + *new TMenuItem( "~P~uzzle", cmPuzzleCmd, kbNoKey, hcSPuzzle ) + + *new TMenuItem( "Ca~l~endar", cmCalendarCmd, kbNoKey, hcSCalendar ) + + *new TMenuItem( "Ascii ~T~able", cmAsciiCmd, kbNoKey, hcSAsciiTable ) + + *new TMenuItem( "~C~alculator", cmCalcCmd, kbNoKey, hcCalculator ); + + TSubMenu& sub2 = + *new TSubMenu( "~F~ile", 0, hcFile ) + + //*new TSubMenu( "~æ~ÁÊÌ", 0, hcFile ) + // KOI8 test + *new TMenuItem( "~O~pen...", cmOpenCmd, kbF3, hcFOpen, "F3" ) + + *new TMenuItem( "~C~hange Dir...", cmChDirCmd, kbNoKey, hcFChangeDir ) + + newLine() + + *new TMenuItem( "S~h~ell", cmCallShell, kbNoKey, hcFDosShell ) + + *new TMenuItem( "E~x~it", cmQuit, kbAltX, hcFExit, "Alt-X" ); + + TSubMenu& sub3 = + *new TSubMenu( "~W~indows", 0, hcWindows ) + + *new TMenuItem( "~R~esize/move", cmResize, kbCtrlF5, hcWSizeMove, "Ctrl-F5" ) + + *new TMenuItem( "~Z~oom", cmZoom, kbF5, hcWZoom, "F5" ) + + *new TMenuItem( "~N~ext", cmNext, kbF6, hcWNext, "F6" ) + + *new TMenuItem( "~C~lose", cmClose, kbAltF3, hcWClose, "Alt-F3" ) + + *new TMenuItem( "~T~ile", cmTile, kbNoKey, hcWTile ) + + *new TMenuItem( "C~a~scade", cmCascade, kbNoKey, hcWCascade ); + + TSubMenu& sub4 = + *new TSubMenu( "~O~ptions", 0, hcOptions ) + + *new TMenuItem( "~M~ouse...", cmMouseCmd, kbNoKey, hcOMouse ) + + *new TMenuItem( "~C~olors...", cmColorCmd, kbNoKey, hcOColors ) + + *new TMenuItem( "~S~ave desktop", cmSaveCmd, kbNoKey, hcOSaveDesktop ) + + *new TMenuItem( "~R~etrieve desktop", cmRestoreCmd, kbNoKey, hcORestoreDesktop ) + + *new TMenuItem( "~T~est inputbox", cmTestInputBox, kbNoKey, hcNoContext ) + + *new TMenuItem( "~T~est picture validator", cmTestPicture, kbNoKey, hcNoContext ); + + r.b.y = r.a.y + 1; + return (new TMenuBar( r, sub1 + sub2 + sub3 + sub4 ) ); +} + +// Called each time the code page changes. In this example we only have +// potential code page changes at start-up. +void TVDemo::cpCallBack(ushort *map) +{ + TVCodePage::RemapString(systemMenuIcon,osystemMenuIcon,map); + TCalendarView::upArrowChar=TVCodePage::RemapChar(TCalendarView::oupArrowChar,map); + TCalendarView::downArrowChar=TVCodePage::RemapChar(TCalendarView::odownArrowChar,map); + // If the chain was already used call it + if (oldCPCallBack) + oldCPCallBack(map); +} + diff --git a/tvision/examples/desklogo/desklogo.bmk b/tvision/examples/desklogo/desklogo.bmk new file mode 100644 index 0000000..b8f8e3d --- /dev/null +++ b/tvision/examples/desklogo/desklogo.bmk @@ -0,0 +1,10 @@ +#!/usr/bin/make +# +# Copyright (c) 2003 by Salvador E. Tropea. +# Covered by the GPL license. +# +!include ../common.bmk +all: desklogo.exe +!include ../../makes/common.bmk +!include desklogo.umk + diff --git a/tvision/examples/desklogo/desklogo.cc b/tvision/examples/desklogo/desklogo.cc new file mode 100644 index 0000000..214fa84 --- /dev/null +++ b/tvision/examples/desklogo/desklogo.cc @@ -0,0 +1,224 @@ +//======================================================================== +// The following example routines have been provided by the Technical +// Support staff at Borland International. They are provided as a +// courtesy and not as part of a Borland product, and as such, are +// provided without the assurance of technical support or any specific +// guarantees. +//======================================================================== +// +// Ported and contributed by Joel +// +//======================================================================== + + +#define Uses_string + +#define Uses_TApplication +#define Uses_TBackground +#define Uses_TButton +#define Uses_TKeys +#define Uses_TDeskTop +#define Uses_TDialog +#define Uses_TMenu +#define Uses_TMenuBar +#define Uses_TMenuItem +#define Uses_TRect +#define Uses_TStaticText +#define Uses_TStatusDef +#define Uses_TStatusItem +#define Uses_TStatusLine + +#include + +#define PATTERN 177 + +const int cmAbout = 100; // User selected menu item 'About' + +char *lines[] ={"±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±²²²²²²²²²²²²²²²²²²±±±±²²±±±±±±±±±±±±±±²²±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±²²±±±±±±±±±±±±±²²±±±±±±±±±±±±²²±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±²²±±±±±±±±±±±±±±²²±±±±±±±±±±²²±±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±²²±±±±±±±±±±±±±±±²²±±±±±±±±²²±±±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±²²±±±±±±±±±±±±±±±±²²±±±±±±²²±±±±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±²²±±±±±±±±±±±±±±±±±²²±±±±²²±±±±±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±²²±±±±±±±±±±±±±±±±±±²²±±²²±±±±±±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±²²±±±±±±±±±±±±±±±±±±±±²²±±±±±±±±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±", + "±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±" }; + + +//======================================================================== +// class definitions +//------------------------------------------------------------------------ +class TApp : public TApplication { + // main application class + +public: + TApp(); + + static TMenuBar *initMenuBar( TRect r ); + static TDeskTop *initDeskTop( TRect r ); + void handleEvent( TEvent &event ); + void AboutDialog(); + +}; + +//------------------------------------------------------------------------ +class TNewDeskTop : public TDeskTop +{ // we derive a new desk top which will instantiate the background + // object with the character we select for the pattern + // also, the initBackground function is overridden to return + // our specialized TNewBackground +public: + TNewDeskTop( const TRect& r ); + static TBackground* initBackground( TRect r ); +}; + +//------------------------------------------------------------------------ +class TNewBackground : public TBackground +{ +public: + TNewBackground( const TRect& r, char pattern ); + void draw(); +}; + +//=========================================================================== +// Draw the background +//=========================================================================== +void TNewBackground::draw() +{ + + TDrawBuffer b; + + for(int i= 0; i < size.y; i++) + { + for( int j= 0; j < size.x; j++) + { + if (i<23 && j<80) + b.moveChar( j, lines[i][j], getColor(0x01), 1 ); + else + b.moveChar( j, '±', getColor(0x01), 1 ); + } + writeLine( 0, i, size.x, 1, b ); + } + +} + + +TApp::TApp() : TProgInit( &TApplication::initStatusLine, + &TApp::initMenuBar, &TApp::initDeskTop ) +{ +} + + + +TMenuBar *TApp::initMenuBar( TRect r ) +{ + r.b.y = r.a.y + 1; + return( new TMenuBar( r, new TMenu( + *new TMenuItem( "~A~bout", cmAbout, kbAltA, hcNoContext, 0 ) + ) ) ); +} + +//------------------------------------------------------------------------ +// redefine desktop initialization to cause usage of newly +// defined desktop +//------------------------------------------------------------------------ +TDeskTop *TApp::initDeskTop( TRect r ) +{ + // initDeskTop is passed a TRect which is the size of the + // application's window - in our case the whole screen + r.a.y++; + r.b.y--; + return ( new TNewDeskTop( r ) ); + +} + + + +void TApp::handleEvent (TEvent &event) +{ + // override the handleEvent so we can call the about box + TApplication::handleEvent( event ); + if( event.what == evCommand ) + { + switch( event.message.command ) + { + case cmAbout: + { + AboutDialog(); + clearEvent( event ); + break; + } + } + } +} + +//------------------------------------------------------------------------ +// create modal About dialog box +//------------------------------------------------------------------------ +void TApp::AboutDialog() +{ + + TDialog *pd = new TDialog( TRect( 0, 0, 35, 12 ), "About" ); + if (pd) + { + pd->options |= ofCentered; + pd->insert( new TStaticText( TRect( 1, 2, 34, 7 ), + "\003Turbo Vision Example\n\003\n" + "\003Modifying the desk top\n\003\n" + "\003Borland Technical Support")); + pd->insert( new TButton( TRect( 3,9,32,11 ), "~O~k", + cmOK, bfDefault ) ); + deskTop->execView( pd ); + } + CLY_destroy( pd ); +} + +//======================================================================== +// implementation of TNewDeskTop +//------------------------------------------------------------------------ +TNewDeskTop::TNewDeskTop( const TRect& r ) : + TDeskInit( &initBackground ), + TDeskTop( r ) +{ +} + +//------------------------------------------------------------------------ + +TBackground *TNewDeskTop::initBackground( TRect r ) +{ + // initializing the TBackground object allows us + // to pass it a character for the desktop pattern + return new TNewBackground( r, PATTERN ); +} + + +//======================================================================== +// implementation of TNewBackground +//------------------------------------------------------------------------ + +TNewBackground::TNewBackground( const TRect& r, char pattern ) : + TBackground( r, pattern ) +{ +} + +//======================================================================== +int main(void) +{ + TApp myApp; + myApp.run(); + return 0; +} diff --git a/tvision/examples/desklogo/desklogo.gpr b/tvision/examples/desklogo/desklogo.gpr new file mode 100644 index 0000000..f4866ef Binary files /dev/null and b/tvision/examples/desklogo/desklogo.gpr differ diff --git a/tvision/examples/desklogo/desklogo.mkf b/tvision/examples/desklogo/desklogo.mkf new file mode 100644 index 0000000..ff4d410 --- /dev/null +++ b/tvision/examples/desklogo/desklogo.mkf @@ -0,0 +1,11 @@ +#!/usr/bin/make +# +# Copyright (c) 2003-2004 by Salvador E. Tropea. +# Covered by the GPL license. +# +vpath_src= +vpath_obj=. +INCLUDE_DIRS=../../include +COMMON_IMK=../../makes/common.imk +include $(COMMON_IMK) +include desklogo$(ExIMK) diff --git a/tvision/examples/desklogo/desklogo.umk b/tvision/examples/desklogo/desklogo.umk new file mode 100644 index 0000000..df5b8c3 --- /dev/null +++ b/tvision/examples/desklogo/desklogo.umk @@ -0,0 +1,17 @@ +#!/usr/bin/make +# Automatically generated from RHIDE projects, don't edit +# + +OBJFILES=\ + ./desklogo$(ExOBJ) + +LIBRARIES= + +desklogo$(ExEXE):: \ + ./desklogo$(ExOBJ) \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_LINK) + +./desklogo$(ExOBJ):: desklogo.cc + $(RHIDE_COMPILE_CC) + diff --git a/tvision/examples/desklogo/rhide.env b/tvision/examples/desklogo/rhide.env new file mode 100644 index 0000000..56091d7 --- /dev/null +++ b/tvision/examples/desklogo/rhide.env @@ -0,0 +1,5 @@ +# +# This include file have rhide options for all the subprojects. +# +include ../rhide.env + diff --git a/tvision/examples/desklogo/set-logo.bmk b/tvision/examples/desklogo/set-logo.bmk new file mode 100644 index 0000000..e0cbdf7 --- /dev/null +++ b/tvision/examples/desklogo/set-logo.bmk @@ -0,0 +1,10 @@ +#!/usr/bin/make +# +# Copyright (c) 2003 by Salvador E. Tropea. +# Covered by the GPL license. +# +!include ../common.bmk +all: set-logo.exe +!include ../../makes/common.bmk +!include set-logo.umk + diff --git a/tvision/examples/desklogo/set-logo.cc b/tvision/examples/desklogo/set-logo.cc new file mode 100644 index 0000000..56bae17 --- /dev/null +++ b/tvision/examples/desklogo/set-logo.cc @@ -0,0 +1,259 @@ +//======================================================================== +// The following example routines have been provided by the Technical +// Support staff at Borland International. They are provided as a +// courtesy and not as part of a Borland product, and as such, are +// provided without the assurance of technical support or any specific +// guarantees. +//======================================================================== +// +// Ported and contributed by Joel +// +// SET: 1999/12/05, Added an example to show how to stop and resume the +// application under Linux. Based in a test from Matt Mueller +// +// +//======================================================================== + +// To avoid pulling TScreen and signal.h for anything but UNIX +#include + +#define Uses_string + +#define Uses_TApplication +#define Uses_TBackground +#define Uses_TButton +#define Uses_TKeys +#define Uses_TDeskTop +#define Uses_TDialog +#define Uses_TMenu +#define Uses_TMenuBar +#define Uses_TMenuItem +#define Uses_TRect +#define Uses_TStaticText +#define Uses_TStatusDef +#define Uses_TStatusItem +#define Uses_TStatusLine + +#ifdef TVOS_UNIX + #define Uses_TScreen + #define Uses_signal +#endif + +#include + +#define PATTERN 177 + +const int cmAbout = 100; // User selected menu item 'About' + +char *lines[]= +{ +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ÛÛÛÛÛÛÛÛÛÛ ÛÛÛÛÛÛÛÛÛÛ ÛÛÛÛÛÛÛÛÛÛ ", +" ÛÛÛÛÛÛÛÛÛÛ ÛÛÛÛÛÛÛÛÛÛ ÛÛÛÛÛÛÛÛÛÛ ", +" ÛÛÛÛ ÛÛÛÛ ÛÛÛÛ ", +" ÛÛÛÛ ÛÛÛÛ ÛÛÛÛ ", +" ÛÛÛÛÛÛÛÛÛÛ ÛÛÛÛÛÛÛ ÛÛÛÛ ", +" ÛÛÛÛÛÛÛÛÛÛ ÛÛÛÛ ÛÛÛÛ ", +" ÛÛÛÛ ÛÛÛÛ ÛÛÛÛ ", +" ÛÛÛÛ ÛÛÛÛ ÛÛÛÛ ", +" ÛÛÛÛÛÛÛÛÛÛ ÛÛÛÛÛÛÛÛÛÛ ÛÛÛÛ ", +" ÛÛÛÛÛÛÛÛÛÛ ÛÛÛÛÛÛÛÛÛÛ ÛÛÛÛ ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" " +}; + + +//======================================================================== +// class definitions +//------------------------------------------------------------------------ +class TApp : public TApplication { + // main application class + +public: + TApp(); + + static TMenuBar *initMenuBar( TRect r ); + static TDeskTop *initDeskTop( TRect r ); + void handleEvent( TEvent &event ); + void AboutDialog(); + +}; + +//------------------------------------------------------------------------ +class TNewDeskTop : public TDeskTop +{ // we derive a new desk top which will instantiate the background + // object with the character we select for the pattern + // also, the initBackground function is overridden to return + // our specialized TNewBackground +public: + TNewDeskTop( const TRect& r ); + static TBackground* initBackground( TRect r ); +}; + +//------------------------------------------------------------------------ +class TNewBackground : public TBackground +{ +public: + TNewBackground( const TRect& r, char pattern ); + void draw(); +}; + + + +//=========================================================================== +// Draw the background +//=========================================================================== +void TNewBackground::draw() +{ + + TDrawBuffer b; + + for(int i= 0; i < size.y; i++) + { + for( int j= 0; j < size.x; j++) + { + if (i<25 && j<80) + b.moveChar( j, lines[i][j], getColor(0x01), 1 ); + else + b.moveChar( j, ' ', getColor(0x01), 1 ); + } + writeLine( 0, i, size.x, 1, b ); + } + +} + + +TApp::TApp() : TProgInit( &TApplication::initStatusLine, + &TApp::initMenuBar, &TApp::initDeskTop ) +{ +} + + + +TMenuBar *TApp::initMenuBar( TRect r ) +{ + r.b.y = r.a.y + 1; + return( new TMenuBar( r, new TMenu( + *new TMenuItem( "~A~bout", cmAbout, kbAltA, hcNoContext, 0 ) + ) ) ); +} + +//------------------------------------------------------------------------ +// redefine desktop initialization to cause usage of newly +// defined desktop +//------------------------------------------------------------------------ +TDeskTop *TApp::initDeskTop( TRect r ) +{ + // initDeskTop is passed a TRect which is the size of the + // application's window - in our case the whole screen + r.a.y++; + r.b.y--; + return ( new TNewDeskTop( r ) ); + +} + +#ifdef TVOS_UNIX +void ResumeApp(int signum) +{ + TProgram::application->resume(); + TProgram::deskTop->setState(sfVisible,True); + TProgram::deskTop->redraw(); + TProgram::application->redraw(); +} +#endif + +void TApp::handleEvent (TEvent &event) +{ + // override the handleEvent so we can call the about box + TApplication::handleEvent( event ); + if( event.what == evCommand ) + { + switch( event.message.command ) + { + case cmAbout: + { + AboutDialog(); + clearEvent( event ); + break; + } + } + } + #ifdef TVOS_UNIX + else + if( event.what == evKeyDown && event.keyDown.keyCode == kbCtrlZ ) + { + suspend(); + signal(SIGCONT,ResumeApp); + kill(0,SIGSTOP); + } + #endif +} + +//------------------------------------------------------------------------ +// create modal About dialog box +//------------------------------------------------------------------------ +void TApp::AboutDialog() +{ + + TDialog *pd = new TDialog( TRect( 0, 0, 35, 12 ), "About" ); + if (pd) + { + pd->options |= ofCentered; + pd->insert( new TStaticText( TRect( 1, 2, 34, 7 ), + "\003Turbo Vision Example\n\003\n" + "\003Modifying the desk top\n\003\n" + "\003Borland Technical Support")); + pd->insert( new TButton( TRect( 3,9,32,11 ), "~O~k", + cmOK, bfDefault ) ); + deskTop->execView( pd ); + } + CLY_destroy( pd ); +} + +//======================================================================== +// implementation of TNewDeskTop +//------------------------------------------------------------------------ +TNewDeskTop::TNewDeskTop( const TRect& r ) : + TDeskInit( &initBackground ), + TDeskTop( r ) +{ +} + +//------------------------------------------------------------------------ + +TBackground *TNewDeskTop::initBackground( TRect r ) +{ + // initializing the TBackground object allows us + // to pass it a character for the desktop pattern + return new TNewBackground( r, PATTERN ); +} + + +//======================================================================== +// implementation of TNewBackground +//------------------------------------------------------------------------ + +TNewBackground::TNewBackground( const TRect& r, char pattern ) : + TBackground( r, pattern ) +{ +} + +//======================================================================== +int main(void) +{ + TApp myApp; + myApp.run(); + return 0; +} diff --git a/tvision/examples/desklogo/set-logo.gpr b/tvision/examples/desklogo/set-logo.gpr new file mode 100644 index 0000000..4bb5425 Binary files /dev/null and b/tvision/examples/desklogo/set-logo.gpr differ diff --git a/tvision/examples/desklogo/set-logo.mkf b/tvision/examples/desklogo/set-logo.mkf new file mode 100644 index 0000000..2dde95e --- /dev/null +++ b/tvision/examples/desklogo/set-logo.mkf @@ -0,0 +1,11 @@ +#!/usr/bin/make +# +# Copyright (c) 2003-2004 by Salvador E. Tropea. +# Covered by the GPL license. +# +vpath_src= +vpath_obj=. +INCLUDE_DIRS=../../include +COMMON_IMK=../../makes/common.imk +include $(COMMON_IMK) +include set-logo$(ExIMK) diff --git a/tvision/examples/desklogo/set-logo.umk b/tvision/examples/desklogo/set-logo.umk new file mode 100644 index 0000000..c9c4ca1 --- /dev/null +++ b/tvision/examples/desklogo/set-logo.umk @@ -0,0 +1,17 @@ +#!/usr/bin/make +# Automatically generated from RHIDE projects, don't edit +# + +OBJFILES=\ + ./set-logo$(ExOBJ) + +LIBRARIES= + +set-logo$(ExEXE):: \ + ./set-logo$(ExOBJ) \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_LINK) + +./set-logo$(ExOBJ):: set-logo.cc + $(RHIDE_COMPILE_CC) + diff --git a/tvision/examples/desklogo/tv_logo.bmk b/tvision/examples/desklogo/tv_logo.bmk new file mode 100644 index 0000000..9ba3d20 --- /dev/null +++ b/tvision/examples/desklogo/tv_logo.bmk @@ -0,0 +1,10 @@ +#!/usr/bin/make +# +# Copyright (c) 2003 by Salvador E. Tropea. +# Covered by the GPL license. +# +!include ../common.bmk +all: tv_logo.exe +!include ../../makes/common.bmk +!include tv_logo.umk + diff --git a/tvision/examples/desklogo/tv_logo.cc b/tvision/examples/desklogo/tv_logo.cc new file mode 100644 index 0000000..5010082 --- /dev/null +++ b/tvision/examples/desklogo/tv_logo.cc @@ -0,0 +1,258 @@ +//======================================================================== +// The following example routines have been provided by the Technical +// Support staff at Borland International. They are provided as a +// courtesy and not as part of a Borland product, and as such, are +// provided without the assurance of technical support or any specific +// guarantees. +//======================================================================== +// +// Ported and contributed by Joel +// I (SET) did some changes to show some details and hence make it more +// instructive. +// +//======================================================================== + +#define Uses_TApplication +#define Uses_TBackground +#define Uses_TButton +#define Uses_TKeys +#define Uses_TDeskTop +#define Uses_TDialog +#define Uses_TMenu +#define Uses_TMenuBar +#define Uses_TMenuItem +#define Uses_TRect +#define Uses_TStaticText +#define Uses_TStatusDef +#define Uses_TStatusItem +#define Uses_TStatusLine +#define Uses_TPalette + +#define Uses_string +#include + +#define PATTERN 177 + +const int cmAbout = 100; // User selected menu item 'About' + +// Following logo is just a simple text +const char *logo = "To the success of FSF "; + +//======================================================================== +// class definitions +//------------------------------------------------------------------------ +class TvApp : public TApplication { + // main application class + +public: + TvApp(); + + static TMenuBar *initMenuBar( TRect r ); + static TDeskTop *initDeskTop( TRect r ); + void handleEvent( TEvent &event ); + void AboutDialog(); + + virtual TPalette& getPalette() const; + +}; + +//------------------------------------------------------------------------ +class TNewDeskTop : public TDeskTop +{ // we derive a new desk top which will instantiate the background + // object with the character we select for the pattern + // also, the initBackground function is overridden to return + // our specialized TNewBackground +public: + TNewDeskTop( const TRect& r ); + static TBackground* initBackground( TRect r ); +}; + +//------------------------------------------------------------------------ +class TNewBackground : public TBackground +{ + +public: + TNewBackground( const TRect& r, char pattern ); + void draw(); +}; + +//=========================================================================== +// Draw the background +//=========================================================================== +void TNewBackground::draw() +{ +// Original Design +// TDrawBuffer b; +// +// for(int col= 0; col < size.y; col++) +// { +// for( int lin= 0; lin < size.x; lin++) +// { +// b.moveChar( lin, logo[(col + lin) % strlen(logo)], getColor(0x01), 1 ); +// } +// writeLine( 0, col, size.x, 1, b ); +// } +// End Original Design + +// Alternate Design +// This design was originaly implemented in the book: +// "TURBO VISION POUR C++" of G. Leblanc (Ed. EYROLLES) +// which I adapted for the choice of *logo (a C string) +// in place of *lines[] (a table of C string) + + #if 0 + TRect r = getClipRect(); // To refresh only what is necessary + + // SET: note that even when valid this aproach is very slow. The original + // approach is better oriented, but the call to getColor() inside the loop + // is a big mistake. Anyways, these are 2 examples. + for (int col=r.a.x; colredraw(); //SET: This extra redraw is needed to use the new palette +} + +TMenuBar *TvApp::initMenuBar( TRect r ) +{ + r.b.y = r.a.y + 1; + return( new TMenuBar( r, new TMenu( + *new TMenuItem( "~A~bout", cmAbout, kbAltA, hcNoContext, 0 ) + ) ) ); +} + +//------------------------------------------------------------------------ +// redefine desktop initialization to cause usage of newly +// defined desktop +//------------------------------------------------------------------------ +TDeskTop *TvApp::initDeskTop( TRect r ) +{ + // initDeskTop is passed a TRect which is the size of the + // application's window - in our case the whole screen + r.a.y++; + r.b.y--; + return ( new TNewDeskTop( r ) ); + +} + +void TvApp::handleEvent (TEvent &event) +{ + // override the handleEvent so we can call the about box + TApplication::handleEvent( event ); + if( event.what == evCommand ) + { + switch( event.message.command ) + { + case cmAbout: + { + AboutDialog(); + clearEvent( event ); + break; + } + } + } +} + +//------------------------------------------------------------------------ +// create modal About dialog box +//------------------------------------------------------------------------ +void TvApp::AboutDialog() +{ + TDialog *pd = new TDialog( TRect( 0, 0, 35, 12 ), "About" ); + if (pd) + { + pd->options |= ofCentered; + pd->insert( new TStaticText( TRect( 1, 2, 34, 7 ), + "\003Turbo Vision Example\n\003\n" + "\003Modifying the desk top\n\003\n" + "\003Borland Technical Support")); + pd->insert( new TButton( TRect( 3,9,32,11 ), "~O~k", + cmOK, bfDefault ) ); + deskTop->execView( pd ); + } + CLY_destroy( pd ); +} + + +TPalette& TvApp::getPalette() const +{ + // SET: The following isn't recommendable because that's executed too often + static TPalette palette(TApplication::getPalette()); + if (appPalette == apColor) + { // modification of application palette + palette[1] = 0x02; // Red on Blue for normal article + palette[2] = 0x14; + palette[5] = 0x52; // Green on Blue for preselected article + } + return palette; +} + +//======================================================================== +// implementation of TNewDeskTop +//------------------------------------------------------------------------ +TNewDeskTop::TNewDeskTop( const TRect& r ) : + TDeskInit( &initBackground ), TDeskTop( r ) +{ +} + +//------------------------------------------------------------------------ + +TBackground *TNewDeskTop::initBackground( TRect r ) +{ + // initializing the TBackground object allows us + // to pass it a character for the desktop pattern + return new TNewBackground( r, PATTERN ); +} + +//======================================================================== +// implementation of TNewBackground +//------------------------------------------------------------------------ + +TNewBackground::TNewBackground( const TRect& r, char pattern ) : + TBackground( r, pattern ) +{ +} + +//======================================================================== +int main(void) +{ + TvApp myApp; + myApp.run(); + return 0; +} diff --git a/tvision/examples/desklogo/tv_logo.gpr b/tvision/examples/desklogo/tv_logo.gpr new file mode 100644 index 0000000..4bae158 Binary files /dev/null and b/tvision/examples/desklogo/tv_logo.gpr differ diff --git a/tvision/examples/desklogo/tv_logo.mkf b/tvision/examples/desklogo/tv_logo.mkf new file mode 100644 index 0000000..9c65cc3 --- /dev/null +++ b/tvision/examples/desklogo/tv_logo.mkf @@ -0,0 +1,11 @@ +#!/usr/bin/make +# +# Copyright (c) 2003-2004 by Salvador E. Tropea. +# Covered by the GPL license. +# +vpath_src= +vpath_obj=. +INCLUDE_DIRS=../../include +COMMON_IMK=../../makes/common.imk +include $(COMMON_IMK) +include tv_logo$(ExIMK) diff --git a/tvision/examples/desklogo/tv_logo.umk b/tvision/examples/desklogo/tv_logo.umk new file mode 100644 index 0000000..2eb6e9a --- /dev/null +++ b/tvision/examples/desklogo/tv_logo.umk @@ -0,0 +1,17 @@ +#!/usr/bin/make +# Automatically generated from RHIDE projects, don't edit +# + +OBJFILES=\ + ./tv_logo$(ExOBJ) + +LIBRARIES= + +tv_logo$(ExEXE):: \ + ./tv_logo$(ExOBJ) \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_LINK) + +./tv_logo$(ExOBJ):: tv_logo.cc + $(RHIDE_COMPILE_CC) + diff --git a/tvision/examples/dlgdsn/codebldr.cc b/tvision/examples/dlgdsn/codebldr.cc new file mode 100644 index 0000000..be43cbb --- /dev/null +++ b/tvision/examples/dlgdsn/codebldr.cc @@ -0,0 +1,510 @@ +/*************************************************************************** + + codebldr.cc - Code builder? + --------------------------------------------------------------------- + May, 2000 + Copyright (C) 2000 by Warlei Alves + walves@usa.net + + Heavily modified by Salvador E. Tropea to compile without warnings. + Some warnings were in fact bugs. + For gcc 2.95.x and then 3.0.1. + + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "dsgobjs.h" +#include "propedit.h" +#include "propdlgs.h" +#include "dsgdata.h" +#include "consted.h" + +#define _commomget_(a, b, c) \ + ushort a = ((TViewData *)aObj->attributes)->a;\ + if (a != aObj->defaultData.a)\ + return buildStr(ctrlName, c, aObj->defaultData.a, a, &b);\ + else return blank\ + +static char * blank = ""; + +static int scrollCount = 0; + +typedef char * (*ccGetString)(ushort); + +const char * buildStr(const char * ctrlname, + const char * alabel, + ushort Default, + ushort value, + ccGetString f) +{ + static char buf1[255]; + static char buf2[100]; + strcpy(buf1, ""); + strcpy(buf2, ""); + if (value == Default) return blank; + if ((value & ~Default) != 0) + sprintf(buf1, " %s->%s |= (%s);\n", ctrlname, alabel, f(value &~ Default)); + if ((Default & ~value) != 0) + sprintf(buf2, " %s->%s &= ~(%s);\n", ctrlname, alabel, f(Default &~ value)); + return strcat(buf1, buf2); +} + +const char * getOptions(TDsgObj * aObj, char * ctrlName) +{ + _commomget_(options, OptionsStr, "options"); +} + +const char * getEventMask(TDsgObj * aObj, char * ctrlName) +{ + _commomget_(eventMask, EventMaskStr, "eventMask"); +} + +const char * getState(TDsgObj * aObj, char * ctrlName) +{ + _commomget_(state, StateStr, "state"); +} + +const char * getFlags(TDsgObj * aObj, char * ctrlName) +{ + if (aObj->viewType != vtDialog) return blank; + ushort flags = ((TDDialogData *)aObj->attributes)->flags; + if (flags != aObj->defaultData.flags) + return buildStr(ctrlName, "flags", + aObj->defaultData.flags, flags, &WindowFlagStr); + else return blank; +} + +const char * getGrowMode(TDsgObj * aObj, char * ctrlName) +{ + _commomget_(growMode, GrowModeStr, "growMode"); +} + +const char * getDragMode(TDsgObj * aObj, char * ctrlName) +{ + _commomget_(dragMode, DragModeStr, "dragMode"); +} + +const char * getHelpCtx(TDsgObj * aObj, char * ctrlName) +{ + ushort i = ((TViewData *)aObj->attributes)->helpCtx; + if (i == 0) return blank; + return (char *)HelpCtxsList()->getId(i); +} + +const char * getValidator(TDsgObj * aObj, char * ctrlName) +{ + if (aObj->viewType != vtInput) return blank; + + static char buf[255]; + switch (((TDInputData *)aObj->attributes)->validatorType) + { +// case 1: sprintf(strbuf, "vtUserDefined"); break; + case 2: + sprintf(buf, + " (TInputLine *)%s->SetValidator(\n" + " new TRangeValidator(%s));\n", + ctrlName, ((TDInputData *)aObj->attributes)->validatorData); + break; + case 3: + sprintf(buf, + " (TInputLine *)%s->SetValidator(\n" + " new TFilterValidator(%s));\n", + ctrlName, ((TDInputData *)aObj->attributes)->validatorData); + break; +// case 4: sprintf(strbuf, "vtPictureValidator"); break; + default: return blank; + } + return buf; +} + +const char * getCommand(TDsgObj * aObj) +{ + int i; + + if (aObj->viewType==vtButton) + { + i = ((TDButtonData *)aObj->attributes)->command; + return (char *)CommandsList()->getId(i); + } + return 0; +} + +const char * getPointerName(TDsgObj * aObj) +{ + return (char *)&((TViewData *)aObj->attributes)->thisName; +} + +const char * getTextParam(TDsgObj * aObj) +{ + static char buf[16383]; // 16k must be enough + static char itemstr[100]; + + TStringCollection * strs; + int i, ic; + + switch (aObj->viewType) + { + case vtLabel: return ((TDLabelData *)aObj->attributes)->text; + case vtStatic: return ((TDStaticData *)aObj->attributes)->text; + case vtButton: return ((TDButtonData *)aObj->attributes)->title; + case vtDialog: return ((TDDialogData *)aObj->attributes)->title; + case vtRadioButton: + case vtCheckBox: + if ( ((TDClusterData *)aObj->attributes)->items == 0 ) + strcpy(buf, "0"); + else + { + strcpy(buf, ""); +// strs = (TCollection *)((TDClusterData *)aObj->attributes)->items; + strs = (TStringCollection *)aObj->dsgGetData(); + for (i = 0; i < strs->getCount(); i++) + { + sprintf(itemstr, " TSItem(\x22%s\x22,", (char *)strs->at(i) ); + if (i == strs->getCount() - 1) strcat(itemstr, " 0 "); + else strcat(itemstr, "\n"); + strcat(buf, itemstr); + if (i == strs->getCount() - 1) + for (ic = 0; ic <= i; ic++) strcat(buf, ")"); + } + } + return buf; + default: return blank; + } +} + +const char * getRectStr(const TRect& r) +{ + static char buf[40]; + sprintf(buf, "TRect( %i, %i, %i, %i )", r.a.x, r.a.y, r.b.x, r.b.y); + return buf; +} + +const char * getDlgRectStr(TDsgObj * aObj, TView * v) +{ + if (((TDDialogData *)aObj->attributes)->options & ofCentered == ofCentered) + return getRectStr(v->getExtent()); else + return getRectStr(v->getBounds()); +} + +const char * getDlgViews(TDsgObj * aObj) +{ + static char buf[32767]; // 32k must be enough + + int c = ObjectLinker()->getCount(); + + strcpy(buf, ""); + if (c == 0) return buf; + for(int i = 0; i < c; i++) + buildCode(((TDsgLink *)ObjectLinker()->at(i))->d, buf); + return buf; +} + +const char * getDlgVariables(TDsgObj * aObj) +{ + TDsgLink * dlink; +/* TDsgObj * d; + TView *f, *w; + TDialog *dlg; */ + TViewData * vd; + static char buf[1024]; + bool hasLinks = false, hasOptions = false, hasValidators = false; + + int c = ObjectLinker()->getCount(); + + strcpy(buf, ""); + if (c == 0) return buf; + for(int i = 0; i < c; i++) + { + dlink = (TDsgLink *)ObjectLinker()->at(i); + if (dlink) + { + vd = (TViewData *)dlink->d->attributes; + if (dlink->d->viewType == vtVScroll || + dlink->d->viewType == vtHScroll) scrollCount++; + hasLinks = (dlink->d->viewType == vtLabel); + hasOptions = ( + (vd->options != dlink->d->defaultData.options) || + (vd->eventMask != dlink->d->defaultData.eventMask) || + (vd->growMode != dlink->d->defaultData.growMode) || + (vd->dragMode != dlink->d->defaultData.dragMode) || + (vd->state != dlink->d->defaultData.state) || + (vd->helpCtx != 0) ); + /*hasValidators = (dlink->d->viewType == vtInput &&\ + ((TDInputData *)dlink->d->attributes)->validatorType > 0);*/ + } + } + if (scrollCount > 1) strcat(buf, " TScrollBar * sb1, * sb2;\n"); else + if (scrollCount == 1) strcat(buf, " TScrollBar * sb1;\n"); else + if (hasLinks || hasOptions) strcat(buf, " TView * control;\n"); + if (hasLinks) strcat(buf, " TLabel * lb;\n"); + if ((scrollCount > 0) || hasLinks || hasValidators || hasOptions) + strcat(buf, "\n"); + return buf; +} + +const char * buildScroll(TDsgLink * Link) +{ + char hs[5], vs[5]; + static char tmp[255]; + strcpy(tmp, blank); + + if (Link == 0) return tmp; + + strcpy(vs, (scrollCount > 1) ? "sb2" : "sb1"); + strcpy(hs, "sb1"); + if (Link->d->viewType == vtVScroll) + sprintf(tmp, " d->insert( %s = new TScrollBar( %s ) );\n", vs, getRectStr( Link->v->getBounds() ) ); + else + sprintf(tmp, " d->insert( %s = new TScrollBar( %s ) );\n", hs, getRectStr( Link->v->getBounds() ) ); + return tmp; +} + +const char * ifScroll(TDsgObj * aObj) +{ + TDsgLink * l; + static char tmp[255]; + strcpy(tmp, blank); + + if (aObj->viewType == vtListBox) + { + l = ObjectLinker()->scrollFind( + ((TDListBoxData *)aObj->attributes)->scrollBar); + return buildScroll(l); + } + else if (aObj->viewType == vtMemo) + { + l = ObjectLinker()->scrollFind( + ((TDMemoData *)aObj->attributes)->hScroll); + strcpy(tmp, buildScroll(l)); + l = ObjectLinker()->scrollFind( + ((TDMemoData *)aObj->attributes)->vScroll); + strcat(tmp, buildScroll(l)); + } + //else return blank; + return blank; +} + +const char * ifLabel(TDsgObj * aObj) +{ + static char tmp[255]; + TDsgLink * l; + + strcpy(tmp, blank); + + l = ObjectLinker()->linkFind(((TViewData*)aObj->attributes)->thisName); + if (l) + { + sprintf(tmp, + " d->insert( new TLabel( %s, \x22%s\x22, control ) );\n", + getRectStr( l->v->getBounds() ), + ((TDLabelData *)l->d->attributes)->text + ); + } + return tmp; +} + +void viewCreate(TDsgObj * aObj, const char * aConstructor, char * to) +{ + static char buf[1023]; + char ctrlname[30]; + + strcpy(buf, ""); + +// if (aObj->viewType == vtHScroll) strcpy(ctrlname, "sb1"); else +// if (aObj->viewType == vtVScroll) strcpy(ctrlname, (scrollCount > 1) ? "sb2" : "sb1"); else +// if (aObj->viewType == vtLabel) strcpy(ctrlname, "lb"); +/* else*/strcpy(ctrlname, "control"); + + bool directInsert = false; + + directInsert = ( getOptions(aObj, 0) == blank && + getEventMask(aObj, 0) == blank && + getState(aObj, 0) == blank && + getGrowMode(aObj, 0) == blank && + getDragMode(aObj, 0) == blank && + getHelpCtx(aObj, 0) == blank /*&& + aObj->viewType != vtHScroll && + aObj->viewType != vtVScroll */); + +/* if (!directInsert) + { */ + if (ObjectLinker()->linkFind( ((TViewData *)aObj->attributes)->thisName )) + directInsert = false; + if (aObj->viewType == vtMemo && + ( strlen(((TDMemoData *)aObj->attributes)->hScroll) != 0 || + strlen(((TDMemoData *)aObj->attributes)->vScroll) != 0 ) ) + directInsert = false; + if (aObj->viewType == vtListBox && + ( strlen(((TDListBoxData *)aObj->attributes)->scrollBar) != 0 ) ) + directInsert = false; +/* } */ + + if (directInsert) + sprintf(buf, " d->insert( %s );\n", aConstructor); + else + { + sprintf(buf, "%s %s = %s;\n%s%s%s%s%s%s%s%s d->insert( %s );\n", + ifScroll(aObj), + ctrlname, + aConstructor, + getOptions(aObj, ctrlname), + getEventMask(aObj, ctrlname), + getState(aObj, ctrlname), + getGrowMode(aObj, ctrlname), + getDragMode(aObj, ctrlname), + getHelpCtx(aObj, ctrlname), + getValidator(aObj, ctrlname), + ifLabel(aObj), + ctrlname ); + } + strcat(to, buf); +} + + +const char * buildCode(TDsgObj * aObj, char * buffer) +{ + TView * v; + char tmp[65535]; + char viewConstructor[1023]; + char hs[5], vs[5]; + char *hi, *vi; + const char * var; + + strcpy(hs, "NULL"); + strcpy(vs, "NULL"); + strcpy(tmp, ""); + strcpy(viewConstructor, ""); + + if (aObj->viewType == vtLabel || + aObj->viewType == vtVScroll || + aObj->viewType == vtHScroll) return 0; + + if (aObj->viewType == vtDialog) + { + v = DialogEditor(); +// ObjectLinker()->sortForBuild(); + ObjectLinker()->doReOrder(); + } + else + v = ObjectLinker()->dsgObjFind(aObj)->v; + + switch(aObj->viewType) + { +//- User ------------------------------------------------------------------- + case vtOther: break; + sprintf(viewConstructor, "new %s( %s )", + ((TViewData *)aObj->attributes)->className, + getRectStr( v->getBounds()) ); + viewCreate(aObj, viewConstructor, tmp); + break; +/*- Label ------------------------------------------------------------------ + case vtLabel: + if (((TDLabelData *)aObj->attributes)->link < 0) return buffer; + sprintf(viewConstructor, "new TLabel( %s, \x22%s\x22, control )", + getRectStr( v->getBounds() ), getTextParam(aObj) ); + viewCreate(aObj, viewConstructor, tmp); + break; */ +//- InputLine -------------------------------------------------------------- + case vtInput: + sprintf(viewConstructor, "new TInputLine( %s, %i )", + getRectStr( v->getBounds() ), + ((TDInputData *)aObj->attributes)->maxLen ); + viewCreate(aObj, viewConstructor, tmp); + break; +//- Memo ------------------------------------------------------------------- + case vtMemo: + hi = ((TDMemoData *)aObj->attributes)->hScroll; + vi = ((TDMemoData *)aObj->attributes)->vScroll; + if (strcmp("", hi) != 0) strcpy(hs, "sb1"); + if (strcmp("", vi) != 0) + strcpy(vs, (scrollCount > 1) ? "sb2" : "sb1"); + sprintf(viewConstructor, "new TMemo( %s, %s, %s, NULL, %i )", + getRectStr( v->getBounds() ), // h s ind bs + hs, vs, ((TDMemoData *)aObj->attributes)->bufSize ); + viewCreate(aObj, viewConstructor, tmp); + break; +//- StaticText ------------------------------------------------------------- + case vtStatic: + sprintf(viewConstructor, "new TStaticText( %s, \x22%s\x22 )", + getRectStr( v->getBounds() ), getTextParam(aObj) ); + viewCreate(aObj, viewConstructor, tmp); + break; +//- Button ----------------------------------------------------------------- + case vtButton: + sprintf(viewConstructor, "new TButton( %s, \x22%s\x22, %s, %s )", + getRectStr( v->getBounds() ), getTextParam(aObj), + getCommand(aObj), ButtonFlagStr( + ((TDButtonData *)aObj->attributes)->flags) ); + viewCreate(aObj, viewConstructor, tmp); + break; +//- ListBoxes -------------------------------------------------------------- + case vtListBox: + vi = ((TDListBoxData *)aObj->attributes)->scrollBar; + if (strcmp("", vi) != 0) + strcpy(vs, (scrollCount > 1) ? "sb2" : "sb1"); + sprintf(viewConstructor, "new TListBox( %s, %i, %s )", + getRectStr( v->getBounds() ), + ((TDListBoxData *)aObj->attributes)->columns, vs); + viewCreate(aObj, viewConstructor, tmp); + break; +//- RadioButtons ----------------------------------------------------------- + case vtRadioButton: + sprintf(viewConstructor, "new TRadioButtons( %s, \n%s )", + getRectStr( v->getBounds() ), getTextParam(aObj) ); + viewCreate(aObj, viewConstructor, tmp); + break; +//- CheckBoxes ------------------------------------------------------------- + case vtCheckBox: + sprintf(viewConstructor, "new TCheckBoxes( %s, \n%s )", + getRectStr( v->getBounds() ), getTextParam(aObj) ); + viewCreate(aObj, viewConstructor, tmp); + break; +/*- ScrollBar -------------------------------------------------------------- + case vtVScroll: + sprintf(viewConstructor, "new TScrollBar( %s )", getRectStr( v->getBounds() ) ); + viewCreate(aObj, viewConstructor, tmp); + break; + case vtHScroll: + sprintf(viewConstructor, "new TScrollBar( %s )", getRectStr( v->getBounds() ) ); + viewCreate(aObj, viewConstructor, tmp); + break; */ +//- Dialog ----------------------------------------------------------------- + case vtDialog: + var = getDlgVariables(aObj); + sprintf(tmp, "TDialog * build%s()\n{\n" + "%s TDialog * d = new TDialog( %s, \x22%s\x22 );\n\n" + "%s%s%s%s%s%s%s%s\n d->selectNext(True);\n return d;\n}\n\n", + getPointerName(aObj), + var, //getDlgVariables(aObj), + getDlgRectStr(aObj, v), + getTextParam(aObj), + getOptions(aObj, "d"), + getEventMask(aObj, "d"), + getState(aObj, "d"), + getGrowMode(aObj, "d"), + getDragMode(aObj, "d"), + getHelpCtx(aObj, "d"), + getFlags(aObj, "d"), + getDlgViews(aObj) ); + scrollCount = 0; + break; + default: return buffer; + } + if (buffer) + { + strcat(buffer, tmp); + return buffer; + } else return newStr(tmp); +} +#undef _buildscroll_ +#undef _commomget_ diff --git a/tvision/examples/dlgdsn/consted.cc b/tvision/examples/dlgdsn/consted.cc new file mode 100644 index 0000000..d1270fe --- /dev/null +++ b/tvision/examples/dlgdsn/consted.cc @@ -0,0 +1,461 @@ +/*************************************************************************** + + consted.cc - Implements the constant listers and its editors + --------------------------------------------------------------------- + May, 2000 + Copyright (C) 2000 by Warlei Alves + walves@usa.net + + Heavily modified by Salvador E. Tropea to compile without warnings. + Some warnings were in fact bugs. + For gcc 2.95.x and then 3.0.1. + + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#define DEFAULT 0 +#define BY_ID 1 +#define BY_VALUE 2 + +#include +#include +#include + +#define Uses_TDialog +#define Uses_TButton +#define Uses_TRadioButtons +#define Uses_TSItem +#define Uses_TLabel +#define Uses_TListBox +#define Uses_TScrollBar +#define Uses_TCollection +#define Uses_TEvent +#define Uses_TCommands +#define Uses_TFilterValidator +#define Uses_TInputLine +#define Uses_TProgram +#define Uses_TDeskTop +#define Uses_MsgBox +#define Uses_TParamText + +#include + +#include "consted.h" + +const ushort + cmEdit = 200, + cmAdd = 201, + cmDel = 202, + cmCClear = 203; + +extern int execDialog(TDialog *, void *); + +static TConstCollection * CommandList; +static TConstCollection * HelpCtxList; + +typedef struct TConstData +{ + char * Id; + int Value; + int Order; + bool ReadOnly; +}; + +TDialog * ConstInputDlg(TValidator * aValid) +{ + TDialog * d = new TDialog( TRect(0, 0, 50, 8), __("Values editor") ); + TInputLine * ip_id = new TInputLine(TRect (10, 2, 48, 3), 50); + TInputLine * ip_vl = new TInputLine(TRect (10, 3, 17, 4), 5); + if (aValid) ip_vl->setValidator(aValid); + d->insert(new TLabel( TRect(1, 2, 10, 3), _("~I~dent:"), ip_id ) ); + d->insert(ip_id); + d->insert(new TLabel( TRect(1, 3, 10, 4), _("~V~alue:"), ip_id ) ); + d->insert(ip_vl); + d->insert(new TButton( TRect(28, 5, 38, 7), __("~O~k"), cmOK, bfDefault) ); + d->insert(new TButton( TRect(38, 5, 48, 7), __("~C~ancel"), cmCancel, 0) ); + d->options |= ofCentered; + d->selectNext(False); + return d; +} + + +void TIntConstListBox::getText(char *dest, ccIndex item, short maxChars) +{ + char * c = ( (TConstData *)(items->at(item)) )->Id; + strncpy(dest, c, maxChars); + dest[maxChars] = 0; +} + + +void TIntConstListBox::setData(void * data) +{ + TListBoxRec * p = (TListBoxRec *)data; + items = (TConstCollection *)p->items; + if (items != 0) setRange( items->getCount() ); + else setRange( 0 ); + if (p->selection < 0) p->selection = 0; + if (range > 0) focusItem(p->selection); + drawView(); +} + +void TIntConstListBox::getData(void * data) +{ + TListBoxRec * p = (TListBoxRec *)data; + TConstCollection * i = (TConstCollection *)items; + p->items = items; + p->selection = ((TConstData *)(i->at(focused)))->Value; +} + +TConstCollection::TConstCollection(const char * aListName): + TCollection(0, 1) +{ + listName = newStr(aListName); + sortmode = -1; +} + +TConstCollection::~TConstCollection() +{ + delete[] listName; +} + +void TConstCollection::change(int index, const char * Ident, int Value) +{ + if (count > 0 && index < count && !((TConstData *)at(index))->ReadOnly ) + { + delete[] ((TConstData *)at(index))->Id; + ((TConstData *)at(index))->Id = newStr(Ident); + ((TConstData *)at(index))->Value = Value; + } +} + +void TConstCollection::add(const char * Ident, int Value, bool IsReadOnly) +{ + TConstData * item = (TConstData *)calloc(1, sizeof(TConstData)); + item->Id = newStr(Ident); + item->Value = Value; + item->Order = count; + item->ReadOnly = IsReadOnly; + sort(DEFAULT); + insert(item); +} + + +static Boolean identMatch(void * item, void * ident) +{ + return (strcmp(((TConstData *)item)->Id, (char *)ident) == 0); +} + +static Boolean valueMatch(void * item, void *value) +{ + return (((TConstData *)item)->Value == (int)value); +} + +int TConstCollection::getIndex(char * Ident) +{ + void * i = firstThat(&identMatch, (void *)Ident); + if (i) return indexOf(i); else return -1; +} + +int TConstCollection::getIndex(int Value) +{ + void * i = firstThat(&valueMatch, (void *)&Value); + if (i) return indexOf(i); else return -1; +} + +char * TConstCollection::getId(int Value) +{ + if (getIndex(Value)!=-1) return ((TConstData*)at(getIndex(Value)))->Id; + else return 0; +} + +int TConstCollection::getValue(char * Ident) +{ + if (getIndex(Ident)!=-1) return ((TConstData*)at(getIndex(Ident)))->Value; + else return 0; +} + +void TConstCollection::freeItem(void * item) +{ + delete[] ((TConstData *)item)->Id; + ((TConstData *)item)->Id = 0; + free(item); +} + +static int compareOrder(const void * key1, const void * key2) +{ + TConstData * v1 = (TConstData *)key1; + TConstData * v2 = (TConstData *)key2; + return (v1->Order > v2->Order) - (v1->Order < v2->Order); +} + +static int compareId(const void * key1, const void * key2) +{ + TConstData * v1 = (TConstData *)key1; + TConstData * v2 = (TConstData *)key2; + return strcmp(v1->Id, v2->Id); +} + +static int compareValue(const void * key1, const void * key2) +{ + TConstData * v1 = (TConstData *)key1; + TConstData * v2 = (TConstData *)key2; + return (v1->Value > v2->Value) - (v1->Value < v2->Value); +} + +void TConstCollection::sort(int mode) +{ + if (mode == sortmode) return; + sortmode = mode; + switch (mode) + { + case DEFAULT : qsort(items, count, sizeof(void *), compareOrder); break; + case BY_ID : qsort(items, count, sizeof(void *), compareId); break; + case BY_VALUE: qsort(items, count, sizeof(void *), compareValue); + } +} + + +TConstEdit::TConstEdit(): + TWindowInit(&TConstEdit::initFrame), + TDialog( TRect(0, 0, 45, 16) , __("Constants") ) +{ + TScrollBar * sb; + + options |= ofCentered; + + sb = new TScrollBar(TRect(30, 2, 31, 13)); + List = new TIntConstListBox(TRect(2, 2, 30, 13), 1, sb); + LVal = new TParamText( TRect(33, 12, 43, 14) ); + LVal->options |= ofFramed; + EditBtn = new TButton(TRect(31, 2, 43, 4), __("~E~dit"), cmEdit, bfBroadcast ); + AddBtn = new TButton(TRect(31, 4, 43, 6), __("~A~dd"), cmAdd, bfBroadcast ); + ClearBtn = new TButton(TRect(31, 6, 43, 8), __("C~l~ear"), cmCClear, bfBroadcast ); + DelBtn = new TButton(TRect(31, 8, 43, 10), __("~D~elete"), cmDel, bfBroadcast ); + SortRB = new TRadioButtons(TRect(2, 14, 31, 15), new TSItem(__("None"), + new TSItem(__("Id"), + new TSItem(__("Value"), 0)))); + insert(sb); + insert(new TLabel( TRect(1, 1, 15, 2), _("~V~alue list:"), List ) ); + insert(LVal); + insert(List); + insert(new TLabel( TRect(1, 13, 12, 14), _("~O~rder by:"), SortRB ) ); + insert(SortRB); + insert(EditBtn); + insert(AddBtn); + insert(ClearBtn); + insert(DelBtn); + LVal->setText("Value:\n%s", ""); + cList = 0; + EditBtn->makeDefault(True); + selectNext(False); +} + + +void TConstEdit::Edit(TConstCollection * AItems) +{ + TListBoxRec rec; + + if (!AItems) return; + delete[] title; + + rec.items = AItems; + rec.selection = 0; + + title = newStr(AItems->listName); + AItems->sort(DEFAULT); + List->setData(&rec); + List->focused = 0; + + AddBtn->setState(sfDisabled, false); + ClearBtn->setState(sfDisabled, false); + DelBtn->setState(sfDisabled, false); + cList = AItems; + LVal->setText("Value:\n%s", ""); + TProgram::deskTop->insert(this); +} + + +void TConstEdit::handleEvent(TEvent& event) +{ + ushort sort; + int tmp=0; + TDialog * dlg; + + struct { + char id_value[50]; + char value[5]; + } datarec; + + TDialog::handleEvent(event); + + if (!cList) return; + + if (event.what == evBroadcast) + switch(event.message.command) + { + case cmListItemFocused: + if ( cList ) + { + tmp = ((TConstData *)(cList->at(List->focused)))->Value; + LVal->setText("Value:\n%i (%x)", tmp, tmp); + } + break; + case cmListItemSelected: + sort = cList->sortmode; + cList->sort(BY_VALUE); + if ( (cList->getCount() > 0) && (List->focused >= 0) ) + { + tmp = ((TConstData *)(cList->at(List->focused)))->Value; + sprintf(datarec.value, "%i", tmp); + strcpy(datarec.id_value, + ((TConstData *)(cList->at(List->focused)))->Id ); + } + dlg = ConstInputDlg(new TFilterValidator("0123456789-")); + if ( execDialog(dlg, &datarec) == cmOK ) + cList->change( List->focused, datarec.id_value, + atoi(datarec.value) ); else cList->sort(sort); + List->drawView(); + clearEvent(event); + break; + case cmClusterMovedTo: + case cmClusterPress: + ((TRadioButtons *)event.message.infoPtr)->getData(&sort); + cList->sort(sort); + List->drawView(); + clearEvent(event); + break; + case cmEdit: + if (cList->getCount() == 0) + { + event.message.command = cmAdd; + putEvent(event); + clearEvent(event); + } + else + { + AddBtn->makeDefault(False); + EditBtn->makeDefault(True); + event.message.command = cmListItemSelected; + putEvent(event); + clearEvent(event); + } + break; + case cmAdd: + sort = cList->sortmode; + cList->sort(BY_VALUE); + memset(&datarec, 0, sizeof(datarec)); + if ((cList->getCount() > 0) && (List->focused >= 0)) + { + tmp = ( (TConstData *)(cList->at(cList->getCount()-1)) )->Value; + tmp++; + sprintf(datarec.value, "%i", tmp); + } + dlg = ConstInputDlg(new TFilterValidator("0123456789-")); + if ( execDialog(dlg, &datarec) == cmOK ) + { + cList->add( datarec.id_value, atoi(datarec.value) ); + List->setRange(List->range + 1); + EditBtn->makeDefault(False); + AddBtn->makeDefault(True); + List->focusItem( cList->getCount() - 1 ); + } + else cList->sort(sort); + List->drawView(); + clearEvent(event); + break; + case cmDel: + if ( messageBox(__("Are you sure ?"), mfYesNoCancel) == cmYes ) + { + cList->atFree(List->focused); + clearEvent(event); + cList->pack(); + List->setRange(List->range - 1); + List->drawView(); + } + break; + case cmCClear: + if ( messageBox(__("Are you sure ?"), mfYesNoCancel) == cmYes ) + { + cList->freeAll(); + cList->pack(); + List->setRange(0); + List->drawView(); + } + clearEvent(event); + break; + } +} + + +TConstCollection * InitCommandLister() +{ + TConstCollection * rst = new TConstCollection(_("Commands")); + rst->add("cmValid", 0, true); + rst->add("cmQuit", 1, true); + rst->add("cmError", 2, true); + rst->add("cmMenu", 3, true); + rst->add("cmClose", 4, true); + rst->add("cmZoom", 5, true); + rst->add("cmResize", 6, true); + rst->add("cmNext", 7, true); + rst->add("cmPrev", 8, true); + rst->add("cmHelp", 9, true); + rst->add("cmOK", 10, true); + rst->add("cmCancel", 11, true); + rst->add("cmYes", 12, true); + rst->add("cmNo", 13, true); + rst->add("cmDefault", 14, true); + rst->add("cmCut", 20, true); + rst->add("cmCopy", 21, true); + rst->add("cmPaste", 22, true); + rst->add("cmUndo", 23, true); + rst->add("cmClear", 24, true); + rst->add("cmTile", 25, true); + rst->add("cmCascade", 26, true); + rst->add("cmReceivedFocus", 50, true); + rst->add("cmReleasedFocus", 51, true); + rst->add("cmCommandSetChanged", 52, true); + rst->add("cmScrollBarChanged", 53, true); + rst->add("cmScrollBarClicked", 54, true); + rst->add("cmSelecteWindowNum", 55, true); + rst->add("cmListItemSelected", 56, true); + rst->add("cmClosingWindow", 57, true); + rst->add("cmClusterMovedTo", 58, true); + rst->add("cmClusterPress", 59, true); + rst->add("cmRecordHistory", 60, true); + rst->add("cmListItemFocused", 61, true); + rst->add("cmGrabDefault", 62, true); + rst->add("cmReleaseDefault", 63, true); + return rst; +} + +TConstCollection * InitHelpCtxLister() +{ + TConstCollection * rst = new TConstCollection(_("Help contexts")); + rst->add("hcNoContext", 0, true); + return rst; +} + +TConstCollection * CommandsList() +{ + if (!CommandList) CommandList = InitCommandLister(); + return CommandList; +} + +TConstCollection * HelpCtxsList() +{ + if (!HelpCtxList) HelpCtxList = InitHelpCtxLister(); + return HelpCtxList; +} + +#undef DEFAULT +#undef BY_ID +#undef BY_VALUE diff --git a/tvision/examples/dlgdsn/consted.h b/tvision/examples/dlgdsn/consted.h new file mode 100644 index 0000000..5d79035 --- /dev/null +++ b/tvision/examples/dlgdsn/consted.h @@ -0,0 +1,91 @@ +/*************************************************************************** + + consted.h - Prototypes for constant listers and its editors + --------------------------------------------------------------------- + May, 2000 + Copyright (C) 2000 by Warlei Alves + walves@usa.net + + Modified by Salvador E. Tropea to compile without warnings. + + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#define Uses_TDialog +#define Uses_TStringCollection +#define Uses_TEvent +#define Uses_TButton +#define Uses_TListBox +#define Uses_TRadioButtons +#define Uses_TParamText + +#include + +class ipstream; +class opstream; + + +class TConstCollection: public TCollection +{ +public: + TConstCollection(const char * aListName); + ~TConstCollection(); + void add(const char * Ident, int Value, bool IsReadOnly = false); + void change(int index, const char * Ident, int Value); + int getIndex(char * Ident); + int getIndex(int Value); + char * getId(int Value); + int getValue(char * Ident); + virtual void freeItem(void * item); + void sort(int mode); + char * listName; + int sortmode; + virtual void * readItem(ipstream&) {return 0;}; + virtual void writeItem(void *, opstream&) { }; +}; + + +class TIntConstListBox: public TListBox +{ + TConstCollection * items; +public: + TIntConstListBox(const TRect& bounds, + ushort aNumCols, TScrollBar * aScrollBar): + TListBox(bounds, aNumCols, aScrollBar) { }; + virtual void getText(char *dest, ccIndex item, short maxChars); + virtual void setData(void * data); + virtual void getData(void * data); +}; + +class TConstEdit: public TDialog +{ + TConstCollection * Items; + TButton * EditBtn; + TButton * AddBtn; + TButton * ClearBtn; + TButton * DelBtn; + TIntConstListBox * List; + TRadioButtons * SortRB; + TConstCollection * cList; + TParamText * LVal; + int Select(TConstCollection * AItems, int32 Current); +public: + TConstEdit(); + void Edit(TConstCollection * AItems); +// int Select(TConstCollection * AItems, int Current); + int Select(TConstCollection * AItems, char * Current); + virtual void handleEvent(TEvent& event); +}; + +TConstCollection * CommandsList(); +TConstCollection * HelpCtxsList(); + + diff --git a/tvision/examples/dlgdsn/dsgdata.h b/tvision/examples/dlgdsn/dsgdata.h new file mode 100644 index 0000000..9736a97 --- /dev/null +++ b/tvision/examples/dlgdsn/dsgdata.h @@ -0,0 +1,136 @@ +/*************************************************************************** + + dsgdata.h - Editable structs prototypes for editable classes + --------------------------------------------------------------------- + May, 2000 + Copyright (C) 2000 by Warlei Alves + walves@usa.net + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#if !defined(_DSGDATA_HPP_) +#define _DSGDATA_HPP_ + +#define MAX_LABEL_LENGTH 30 +#define MAX_TITLE_LENGTH 62 + +typedef char TNameStr[MAX_LABEL_LENGTH]; +typedef char TTitleStr[MAX_TITLE_LENGTH]; + +typedef struct TPoint; + +#define _viewdata_() \ + TPoint origin; /* 8 */ \ + TPoint size; /* 8 */ \ + TNameStr className; /* 30 */ \ + TNameStr thisName; /* 30 */ \ + ushort options; /* 2 */ \ + ushort eventMask; /* 2 */ \ + ushort state; /* 2 */ \ + ushort growMode; /* 2 */ \ + ushort dragMode; /* 2 */ \ + ushort helpCtx /* 2 */ \ +// 88 % 4 = 0 +typedef struct TDefaultData +{ + ushort options; + ushort eventMask; + ushort state; + ushort growMode; + ushort dragMode; + ushort helpCtx; + ushort flags; +}; + +typedef struct TViewData // Wrapper struct +{ + _viewdata_(); +}; + +typedef struct TDsgObjData +{ + _viewdata_(); + int tabOrder; +}; + +typedef struct TDDialogData +{ + _viewdata_(); + TTitleStr title; + ushort flags; +}; + +typedef struct TDInputData +{ + _viewdata_(); + int tabOrder; + int maxLen; + ushort validatorType; + TNameStr validatorData; +}; + +typedef struct TDLabelData +{ + _viewdata_(); + TNameStr text; + TNameStr link; +}; + +typedef struct TDMemoData +{ + _viewdata_(); + int tabOrder; +// uint32 bufSize; +// TNameStr Indicator; + TNameStr hScroll; + TNameStr vScroll; + uint32 bufSize; +}; + +typedef struct TDStaticData +{ + _viewdata_(); + char * text; +}; + +typedef struct TDButtonData +{ + _viewdata_(); + int tabOrder; + TNameStr title; + ushort command; + ushort flags; +}; + +typedef struct TDClusterData +{ + _viewdata_(); + int tabOrder; + void * items; +}; + +typedef struct TDListBoxData +{ + _viewdata_(); + int tabOrder; + short columns; + TNameStr scrollBar; +}; + +#define TDCheckData TDClusterData +#define TDRadioData TDClusterData +#define TDVScrollData TViewData +#define TDHScrollData TViewData + +#undef _viewdata_ + +#endif // _DSGDATA_HPP_ diff --git a/tvision/examples/dlgdsn/dsgobjs.cc b/tvision/examples/dlgdsn/dsgobjs.cc new file mode 100644 index 0000000..3f74c4d --- /dev/null +++ b/tvision/examples/dlgdsn/dsgobjs.cc @@ -0,0 +1,1504 @@ +/*************************************************************************** + + dsgobjs.cc - Implements editable classes + --------------------------------------------------------------------- + May, 2000 + Copyright (C) 2000 by Warlei Alves + walves@usa.net + + Heavily modified by Salvador E. Tropea to compile without warnings. + Some warnings were in fact bugs. + For gcc 2.95.x and then 3.0.1. + + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#define Uses_string +#define Uses_stdio +#define Uses_stdlib +#define Uses_iostream + +#define Uses_TProgram +#define Uses_TApplication +#define Uses_TDeskTop +#define Uses_TKeys +#define Uses_TSItem +#define Uses_TEventQueue +#define Uses_MsgBox +#define Uses_TStringCollection +#define Uses_ofpstream +#define Uses_ifpstream + +#include + +#include "dsgobjs.h" +#include "propedit.h" +#include "dsgdata.h" +#include "strmoper.h" + +static int vtAttrSize[vtDialog + 1] = { sizeof(TDsgObjData), + sizeof(TDLabelData), + sizeof(TDInputData), + sizeof(TDMemoData), + sizeof(TDStaticData), + sizeof(TDButtonData), + sizeof(TDListBoxData), + sizeof(TDClusterData), + sizeof(TDClusterData), + sizeof(TViewData), + sizeof(TViewData), + sizeof(TDDialogData) }; + +static char * TheClassName[vtDialog + 1] = { "TUser", + "TLabel", + "TInputLine", + "TMemo", + "TStaticText", + "TButton", + "TListBox", + "TRadioButtons", + "TCheckBoxes", + "TScrollBar", + "TScrollBar", + "TDialog" }; + + +#if 0 // A useful visual map of AppPalette indexed by dialog and app + +/* The palette of an internal view is mapped in the palette of a group view + which owns it. + if you need to make an internal view visible out of the group for what + it was designed then you must to redefine the getPalette() method to + return a TPalette that is its real palette index in the global palette. */ + +// app "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + Attr "\x71\x70\x78\x74\x20\x28\x24\x17\x1F\x1A\x31\x31\x1E\x71\x00" +// app "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + Attr "\x37\x3F\x3A\x13\x13\x3E\x21\x00\x70\x7F\x7A\x13\x13\x70\x7F\x00" + +// Below the indices of our interest + +// app "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" +# dlg "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + Attr "\x70\x7F\x7A\x13\x13\x70\x70\x7F\x7E\x20\x2B\x2F\x78\x2E\x70\x30" + +// app "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" +# dlg "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" + Attr "\x3F\x3E\x1F\x2F\x1A\x20\x72\x31\x31\x30\x2F\x3E\x31\x13\x00\x00" + +#endif + +// Macros ******************************************************************* + +// Define the palette for editable objects using global index +#define cpDragLabel "\x26\x27\x28\x28" +#define cpDragInput "\x32\x33\x34\x35" +#define cpDragMemo "\x39\x3a" +#define cpDragStatic "\x25" +#define cpDragBtn "\x29\x2a\x2b\x2c\x2d\x2d\x2d\x2e" +#define cpDragLB "\x39\x39\x3a\x3b\x3c" +#define cpDragCluster "\x2f\x30\x31\x31\x3e" +#define cpDragScroll "\x23\x24\x24" + +// The palette to the selection state. Attr to this index (0x20) was changed +// in the app constructor. See freedsgn.cpp.TFreeDsgnApp::TFreeDsgnApp +#define cpSelLabel "\x20\x20\x20\x20" +#define cpSelInput "\x20\x20\x20\x20" +#define cpSelMemo "\x20\x20" +#define cpSelStatic "\x20" +#define cpSelBtn "\x20\x20\x20\x0d\x20\x20\x20\x0f" +#define cpSelLB "\x20\x20\x20\x20\x20" +#define cpSelCluster "\x20\x20\x20\x20\x20" +#define cpSelScroll "\x20\x20\x20" + +// Answers to ImOwned(TView *). Used to decide somethings +#define ByToolDlg 0 +#define ByDesktop 1 +#define ByEditor 2 + +// This state flags maybe removed in future +#define sfEditing 0x1000 +#define sfLoading 0x2000 + +// Commom event handler code fragment for editable classes +#define _h_(a)\ + if (ImOwned(this) == ByToolDlg) \ + { if (!HandleEventOnToolDlg(this, event, viewType)) \ + a::handleEvent(event); } \ + else if (ImOwned(this) == ByEditor) \ + { if (!HandleEventOnEditor(this, event, viewType)) a::handleEvent(event); } + +// Common getpalette function code fragment for editable classes +// SET: Palettes are supposed to be constants, so they should call members +// like here +#define _p_(a,b,c) \ + static TPalette palette( a, sizeof(a) - 1); \ + static TPalette pal_sel( b, sizeof(b) - 1); \ + if (owner == TProgram::deskTop) return palette; \ + else return c::getPalette(); +/* else if ((owner != TProgram::deskTop) && (getState(sfSelected))) \ + return pal_sel; else return c::getPalette();*/ + +// Commom changeBounds code fragment for editable classes +#define _chgbnds_(a) a::changeBounds(bounds); \ + setPos(origin, size); ObjEdit->CLY_Redraw(); \ + EditDlg->modified = true; + +// Commom setState code fragment for all editable classes +#define _setstate_(t) do { \ + t::setState(aState, enable); \ + if (aState & sfEditing && enable) \ +/*{*/ ObjectLinker()->add(this, this); /* <- was DsgObj */ \ +/* setViewData((TDsgObjData &)*attributes); } */ \ + if (aState & (sfFocused | sfSelected) ) \ + { if (owner != EditDlg) { drawView(); return; } \ + if (enable) ObjEdit->setObjData(this); drawView(); } } while(0) + +// Commom shutDown code fragment for all editable classes +#define _shutdown_(a) /* delete dsgObj; */ \ +/* TDsgLink * l = ObjectLinker()->viewFind(this); */ \ +/* if (l) delete l->d; */ \ + a::shutDown() + +// Static ******************************************************************* + +// This always points to Current Tool Dialog and Editor Dialog +static TDDialog * EditDlg; +static TDialog * ToolDlg; +static TObjEdit * ObjEdit; + +// To help keyboard driven object positionment +static TView * FloatingView; +static bool keyPut = false; + +// Counters used to define Labels +static int LabelCount = 0; +static int InputCount = 0; +static int MemoCount = 0; +static int StaticCount = 0; +static int ButtonCount = 0; +static int ListBoxCount = 0; +static int RadioCount = 0; +static int CheckCount = 0; +static int VScrollCount = 0; +static int HScrollCount = 0; +static int UserCount = 0; +static int DialogCount = 0; +static int TabOrder = 0; + +///extern TLinkList * ObjLink; + +// Holds the current mouse position on screen +static MouseEventType * Mouse; + +// Flag for visibility of grid in the Dialog Editor +static bool GridState = true; + +// Functions **************************************************************** + +// Set the visibility of Grid in the dialog editor +void SetGrid(bool enable) +{ + GridState = enable; + EditDlg->CLY_Redraw(); +} + +bool GetGrid() +{ + return GridState; +} + +// ToolDlg (Object Dialog) creation function +TDialog * CreateTool() +{ + TDialog * d = new TDialog(TRect(0, 0, 55, 6), "Obj"); + TDMemo * Memo; + TDListBox * LB; + TView * view; + TMemoData buf; + + d->flags &= ~wfClose; + // d->flags |= wfGrow; + d->insert(new TDInputLine(TRect(2, 1, 7, 2))); + d->insert(view = new TDLabel(TRect(8, 1, 13, 2))); + view->options |= ofSelectable; + d->insert(view = new TDStaticText(TRect(2, 3, 7, 4))); + view->options |= ofSelectable; + d->insert(new TDButton(TRect(7, 3, 13, 5))); + d->insert(new TDCheckBoxes(TRect(15, 1, 20, 2), new TSItem("", 0) )); + d->insert(new TDRadioButtons(TRect(15, 3, 20, 4), new TSItem("", 0) )); + d->insert(LB = new TDListBox(TRect(22, 1, 27, 4))); + d->insert(view = new TVScrollBar(TRect(28, 1, 29, 4))); + view->options |= ofSelectable; + view->growMode = 0; + d->insert(Memo = new TDMemo(TRect(31, 1, 37, 2))); + buf.length = 6; + strcpy(buf.buffer, " Memo "); + Memo->setData(&buf); + Memo->growMode = 0; + d->insert(view = new THScrollBar(TRect(31, 3, 37, 4))); + view->options |= ofSelectable; + view->select(); + view->growMode = 0; + d->selectNext(False); + return d; +} + +// Called to initialize the editor. if FileName = NULL creates a blank dialog +void InitDlgEditor(const char * FileName) +{ +/* if (EditDlg != 0) + { + if (!EditDlg->Save()) return; + TProgram::deskTop->remove(EditDlg); + TObject::destroy(EditDlg); + EditDlg = 0; + }*/ + + Mouse = &TEventQueue::curMouse; + + if (!ObjEdit) + { + ObjEdit = new TObjEdit(EditDlg); + TProgram::deskTop->insert(ObjEdit); + } + DialogCount++; + if (!EditDlg) EditDlg = new TDDialog(); + else if ((EditDlg) && EditDlg->modified) + { + if (!EditDlg->Save(cmCancel)) return; + TProgram::CLY_destroy(EditDlg); + EditDlg = new TDDialog(); + } + TProgram::deskTop->insert(EditDlg); + if (FileName != 0) EditDlg->loadFromFile(FileName); + if (!ToolDlg) + { + ToolDlg = CreateTool(); + TProgram::deskTop->insert(ToolDlg); + } +} + + +TDDialog * DialogEditor() { return EditDlg; } + +TDialog * ToolDialog() { return ToolDlg; } + +TWindow * ObjectEditor() { return ObjEdit; } + +/* DefineRect ------------------------------------------------------------*/ +// returns the initial bounds rect for each type of view +TRect DefineRect(TViewType vt, TPoint p) +{ + switch(vt) + { + case vtLabel: return TRect(p.x, p.y, p.x + 7, p.y + 1); + case vtInput: return TRect(p.x, p.y, p.x + 10, p.y + 1); + case vtStatic: return TRect(p.x, p.y, p.x + 12, p.y + 1); + case vtButton: return TRect(p.x, p.y, p.x + 12, p.y + 2); + case vtVScroll: return TRect(p.x, p.y, p.x + 1, p.y + 5); + case vtHScroll: return TRect(p.x, p.y, p.x + 10, p.y + 1); + default: return TRect(p.x, p.y, p.x + 10, p.y + 3); + } +} + +/* GetSizeLimits ---------------------------------------------------------*/ +// returns the size limits for each type of view +void GetSizeLimits(TPoint& min, TPoint& max, TViewType vt) +{ + max.x = max.y = INT_MAX; + switch(vt) + { + case vtButton: min.x = 5; min.y = 2; break; + case vtVScroll: min.x = 1; min.y = 3; break; + case vtHScroll: min.x = 3; min.y = 1; break; + default: min.x = 3; min.y = 1; + } +} + +/* InitObject ------------------------------------------------------------*/ +// returns a valid tview object of type vt +TView * InitObject(TPoint Position, TViewType vt, ushort mode) +{ + TView * rst; +#define _createobj_(o,c) if (mode != 0) c++;\ + rst = new o(DefineRect(vt, Position)); break +#define _createcluster_(o, c) if (mode != 0) c++;\ + rst = new o( DefineRect(vt, Position),\ + new TSItem("FreeDsgn",\ + new TSItem("For",\ + new TSItem("TVision", 0 ))) ); break + switch(vt) + { + case vtLabel: _createobj_(TDLabel, LabelCount); + case vtInput: _createobj_(TDInputLine, InputCount); + case vtMemo: _createobj_(TDMemo, MemoCount); + case vtStatic: _createobj_(TDStaticText, StaticCount); + case vtButton: _createobj_(TDButton, ButtonCount); + case vtListBox: _createobj_(TDListBox, ListBoxCount); + case vtRadioButton: _createcluster_(TDRadioButtons, RadioCount); + case vtCheckBox: _createcluster_(TDCheckBoxes, CheckCount); + case vtVScroll: _createobj_(TVScrollBar, VScrollCount); + case vtHScroll: _createobj_(THScrollBar, HScrollCount); + default: return 0; + } + return rst; +#undef _createobj_ +#undef _createcluster_ +} + +/* DragObject -----------------------------------------------------------*/ +// Drags the view from the ToolDlg to EditDlg across the desktop +void DragObject(TView * P, TEvent& Event, TViewType vt) +{ + TRect Limits; + TPoint Min, Max, mouse; + +//EditDlg->select(); + if (Event.what == evCommand) FloatingView = P; + TProgram::deskTop->insert(P); + Limits = TProgram::deskTop->getExtent(); + mouse = TProgram::deskTop->makeLocal(Event.mouse.where); + if (!FloatingView) P->moveTo(mouse.x, mouse.y); + P->state |= sfShadow; + P->sizeLimits(Min, Max); + P->dragView(Event, dmDragMove, Limits, Min, Max); + message(EditDlg, evBroadcast, cmItemDropped, (void *)vt); + TProgram::deskTop->remove(P); + FloatingView = NULL; + delete P; +} + +/* ImOwned --------------------------------------------------------------*/ + +ushort ImOwned(TView * view) +{ + if (view->owner == TProgram::deskTop) return ByDesktop; else + if (view->owner == EditDlg) return ByEditor; else + if (view->owner == ToolDlg) return ByToolDlg; + return 0; +} + +/* DsgDragView ----------------------------------------------------------*/ +// Move and resize the view v in the EditDlg +void DsgDragView(TView * v, ushort Mode, TEvent& event) +{ + TRect Limits; + TPoint Min, Max; + + Limits = v->owner->getExtent(); + Limits.grow(-1, -1); + v->sizeLimits(Min, Max); + v->dragView(event, v->dragMode | Mode, Limits, Min, Max); + v->clearEvent(event); +} + +/* HandleEventOnEditor --------------------------------------------------*/ +// Common event handler for editable views which are owned by EditDlg +bool HandleEventOnEditor(TView * view, TEvent& event, + TViewType vt) +{ + TPoint mouse; + TDsgLink * d; + + if ( (event.what == evMouseDown) && + (view->mouseInView(event.mouse.where)) ) + { + d = ObjectLinker()->viewFind(view); + if ((d) && ObjEdit->object != d->d) ObjEdit->setObjData(d->d); + view->select(); + if (event.mouse.buttons == mbRightButton) + { + mouse = view->makeLocal(event.mouse.where); + if ((mouse.x == view->size.x - 1) && + (mouse.y == view->size.y - 1)) + DsgDragView(view, dmDragGrow, event); + else + DsgDragView(view, dmDragMove, event); + } + return false; + } + else return false; +} + +/* HandleEventOnToolDlg --------------------------------------------------*/ +// Common event handler for editable views which are owned by ToolDlg +bool HandleEventOnToolDlg(TView * view, TEvent& event, TViewType vt) +{ + TRect Location; + TView * P; + + if ( (event.what == evMouseDown) || + ( (event.what == evCommand) && + (event.message.command == cmResizeObj) && + (view->getState(sfFocused|sfSelected)) ) ) + { + if (event.what == evMouseDown) + Location.a = view->makeGlobal(event.mouse.where); + else + { + keyPut = true; + Location.a = + TProgram::deskTop->makeLocal(view->owner->makeGlobal(view->origin)); + } + P = InitObject(Location.a, vt, 0); + if (P) DragObject(P, event, vt); + return true; + } + if (event.what == evKeyboard) + { + switch(event.keyDown.keyCode) + { + case kbUp: + view->owner->selectNext(true); + view->clearEvent(event); + return true; + case kbDown: + view->owner->selectNext(false); + view->clearEvent(event); + return true; + case kbLeft: + view->owner->selectNext(true); + view->clearEvent(event); + return true; + case kbRight: + view->owner->selectNext(false); + view->clearEvent(event); + return true; + case kbEnter: + view->clearEvent(event); + if (!keyPut) + { + keyPut = true; + message(view->owner, evCommand, cmResizeObj, 0); + } + keyPut = false; + return false; + default: return false; + } + } + return false; +} + +/* InsertLink -----------------------------------------------------------*/ +// returns true if a TDLabel was found linked to aView and insert both +bool InsertLink(char * aName, TView * aView, TDialog * aOwner) +{ + TLabel * l; + + TDsgLink * dl = ObjectLinker()->linkFind(aName); + if (dl) + { + l = (TLabel *)dl->d->createView(aView); + aOwner->insert(aView); + aOwner->insert(l); + return true; + } else return false; +} + +/* FindScroll -----------------------------------------------------------*/ +// Inserts and returns a valid TScrollBar if one named as aScroll was found +TScrollBar * FindScroll(char * aScroll, TDialog * aOwner) +{ + TScrollBar * sb; + + TDsgLink * dl = ObjectLinker()->scrollFind(aScroll); + if (dl) + { + sb = (TScrollBar *)dl->d->createView(0); + aOwner->insert(sb); + return sb; + } else return 0; +} + +/* StringsToSItems ------------------------------------------------------*/ +// Converts a TStringCollection to TSItems +TSItem * strCollToItems(TStringCollection * strs) +{ + TSItem *first, * cur, * last; + int i; + + first = cur = last = 0; + + if ((strs) && (strs->getCount() > 0)) + { + for (i = 0; i < strs->getCount(); i++) + { + cur = new TSItem(newStr((char *)strs->at(i)), 0); + if (!first) first = cur; + if (last) last->next = cur; + last = cur; + } + return first; + } else return 0; +} + +/* LoadObject ===========================================================*/ + +void * readDsgInfo( ipstream& s, TViewType vt ) +{ + void * rst = malloc(vtAttrSize[vt]); + s.readBytes(rst, vtAttrSize[vt]); + return rst; +} + +void readStrings( ipstream& s, TCollection * c, int limit ) +{ + ushort i, len; + char ch[100]; + c->freeAll(); + c->setLimit(limit); + for (i = 0; i < limit; i++) + { + s >> len; + s.readBytes(&ch, len); + ch[len] = 0; + c->atInsert(i, newStr(ch)); + } +} + +TView * LoadObject( ipstream& s ) +{ + TView * rst=0; + TDsgObj * obj; + static TViewType vt; + static int auxVt; + TStringCollection * items=0; + ushort Count; + char * Text; + TPoint p; + + s >> auxVt; + vt=(TViewType)auxVt; + if (vt == vtNone) return 0; + void * attr = readDsgInfo(s, vt); + if (!attr) return 0; + p.x = 0; p.y = 0; + if (vt != vtDialog) rst = InitObject( p, vt, 0 ); + rst->setState(sfEditing, True); + obj = ObjectLinker()->viewFind(rst)->d; + memcpy(obj->attributes, attr, vtAttrSize[vt]); + free(attr); + if (vt==vtStatic) + { + s >> Count; + if (Count > 0) + { + Text = (char *)malloc(Count); + s.readBytes(Text, Count); + delete[] ((TDStaticData *)obj->attributes)->text; + ((TDStaticData *)obj->attributes)->text = Text; + } + } + if (vt>=vtRadioButton && vt<=vtCheckBox) + { + s >> Count; + if (Count > 0 && Count <= 32) + { + items = (TStringCollection *)obj->dsgGetData(); + readStrings(s, items, Count); + } else items->freeAll(); + ((TDClusterData *)obj->attributes)->items = items; + } +// obj->dsgUpdate(); + return rst; +} + +void SaveObject( ofpstream& s, TDsgObj * obj ) +{ + ushort Count, i; + TStringCollection * items; + char * ch; + + s << (int)obj->viewType; + s.writeBytes(obj->attributes, vtAttrSize[obj->viewType]); + switch (obj->viewType) + { + case vtStatic: + ch = ((TDStaticData *)obj->attributes)->text; + Count = strlen(ch); + if (Count > 0) + { + s << Count + 1; + if (Count > 0) s.writeBytes( ch, Count + 1 ); + } + else s << Count; + break; + case vtRadioButton: + case vtCheckBox: + items = (TStringCollection *)((TDClusterData *)obj->attributes)->items; + Count = items->getCount(); + s << Count; + if (Count > 0) + for ( i = 0; i < items->getCount(); i++) + { + ch = (char *)items->at(i); + Count = strlen(ch); + s << Count; + s.writeBytes( ch, Count ); + } + default: return; + } +} + +/* TDFrame ==============================================================*/ + +TDFrame::TDFrame(const TRect& bounds): TFrame(bounds) { } + +void TDFrame::draw() +{ + TDrawBuffer bl, b; + ushort c, i; + + TFrame::draw(); + + if (!GridState) return; // Grid mode conditioner + + if ((owner->state & sfEditing) != 0) + { + for (i = 0; i <= size.x; i++) + { + c = ((i + 1) % 10 == 0) ? 0x7e : 0x78; + b.moveChar(i, 'ú', c, 1); + } + bl.moveChar(0, 'ú', 0x7e, size.x - 2); + for (i = 1; i <= size.y - 1; i++) + { + if (i % 10 == 0) + writeLine(1, i, size.x - 2, 1, bl); + else + writeLine(1, i, size.x - 2, 1, b); + } + for (i = 1; i <= size.y - 2; i++) + { + c = (i % 10 == 0) ? 0x7e : 0x78; + b.moveChar(0, (i % 10) + 48, c, 1); + writeLine(0, i, 1, 1, b); + } + for (i = 1; i <= size.x; i++) + { + c = (i % 10 == 0) ? 0x7e : 0x78; + b.moveChar(i - 1, (i % 10) + 48, c, 1); + } + writeLine(1, size.y - 1, size.x - 2, size.y, b); + } +} + +/* TDsgObj ==============================================================*/ + +void TDsgObj::buildName(TNameStr * name, int mode) +{ + char fmt[6]; + if (viewType == vtVScroll) strcpy(fmt, "V%s%i"); else + if (viewType == vtHScroll) strcpy(fmt, "H%s%i"); else strcpy(fmt, "%s%i"); + if (!mode) strcpy((char *)name, TheClassName[viewType]); + else sprintf((char *)name, fmt, + (char *)&(TheClassName[viewType][1]), nameIndex); +} + +TDsgObj::TDsgObj(TViewType ViewType) +{ +#define _allocattr_(t,c) \ + nameIndex = c; \ + attrSize = sizeof(t); \ + attributes = new t; break /* calloc(1, attrSize); + break; */ +// setViewData((TDsgObjData &)*attributes); + viewType = ViewType; + switch (viewType) + { + case vtOther: _allocattr_(TDsgObjData, UserCount); + case vtLabel: _allocattr_(TDLabelData, LabelCount); + case vtInput: _allocattr_(TDInputData, InputCount); + case vtMemo: _allocattr_(TDMemoData, MemoCount); + case vtStatic: _allocattr_(TDStaticData, StaticCount); + case vtButton: _allocattr_(TDButtonData, ButtonCount); + case vtListBox: _allocattr_(TDListBoxData, ListBoxCount); + case vtRadioButton: _allocattr_(TDRadioData, RadioCount); + case vtCheckBox: _allocattr_(TDCheckData, CheckCount); + case vtVScroll: _allocattr_(TDVScrollData, VScrollCount); + case vtHScroll: _allocattr_(TDHScrollData, HScrollCount); + case vtDialog: _allocattr_(TDDialogData, DialogCount); + case vtNone: break; + } + dsgObj = this; +#undef _allocattr_ +} + +void TDsgObj::setViewData(TDsgObjData& data) +{ + TView * me = Me(); + + buildName(&data.className, 0); // TName + buildName(&data.thisName, 1); // Name# + data.origin = me->origin; + data.size = me->size; + defaultData.options = data.options = me->options; + defaultData.eventMask = data.eventMask = me->eventMask; + defaultData.state = data.state = me->state; + defaultData.growMode = data.growMode = me->growMode; + defaultData.dragMode = data.dragMode = me->dragMode; + defaultData.helpCtx = data.helpCtx = me->helpCtx; + + switch(viewType) + { + case vtLabel: + strcpy( ((TDLabelData &)data).text, (char *)(this->dsgGetData()) ); + break; + case vtInput: + ((TDInputData &)data).maxLen = 0; + ((TDInputData &)data).validatorType = 0; + break; + case vtStatic: + ((TDStaticData &)data).text = (char *)this->dsgGetData(); + break; + case vtButton: + strcpy( ((TDButtonData &)data).title, (char *)this->dsgGetData() ); + ((TDButtonData &)data).command = ((TDButton *)me)->getCommand(); + ((TDButtonData &)data).flags = ((TDButton *)me)->getFlags(); + break; + case vtRadioButton: + ((TDRadioData &)data).items = ((TDRadioButtons *)me)->dsgGetData(); + break; + case vtCheckBox: + ((TDCheckData &)data).items = ((TDCheckBoxes *)me)->dsgGetData(); + break; + case vtDialog: + strcpy( ((TDDialogData &)data).title, ((TDialog *)me)->title); + ((TDDialogData &)data).flags = ((TDialog *)me)->flags; + default: return; + } +} + +void TDsgObj::setPos(TPoint neworigin, TPoint newsize) +{ + ((TDsgObjData *)attributes)->origin = neworigin; + ((TDsgObjData *)attributes)->size = newsize; + ((TDDialog *)Me()->owner)->setModified(True); +} + +TDsgObj::~TDsgObj() +{ + if (this!=EditDlg && ObjEdit->object == this) ObjEdit->setObjData(EditDlg); + ObjectLinker()->removeMe(this); // <- was DsgObj + delete (char *)attributes; +} + +char * TDsgObj::getScript(ushort ScriptType) +{ +// criar e retorna um texto script conforme o tipo + return 0; +} + +void TDsgObj::setupView(TView * View) +{ + TDsgObjData *editData = (TDsgObjData *)attributes; + View->options = editData->options; + View->growMode = editData->growMode; + View->dragMode = editData->dragMode; + View->state = editData->state; +} + +bool TDsgObj::tabStop() +{ + return ((viewType != vtLabel && + viewType != vtStatic && + viewType != vtVScroll && + viewType != vtHScroll) || + ( ((TDsgObjData *)attributes)->options & ofSelectable ) ); +} + +void TDsgObj::dsgUpdate() +{ + TView * me = Me(); + TDsgObjData * d = (TDsgObjData *)attributes; + TRect r = TRect(d->origin.x, d->origin.y, + d->origin.x + d->size.x, d->origin.y + d->size.y); + if (r != me->getBounds()) me->changeBounds(r); + if (tabStop()) ObjectLinker()->doReOrder(); + ((TDDialog *)me->owner)->setModified(True); + me->owner->CLY_Redraw(); +} + +/* TDDialog =============================================================*/ + +TDDialog::TDDialog(): + TWindowInit(TDDialog::initFrame), + TDialog( TRect(0, 6, 55, 23), "TVISION Dialog Editor"), + TDsgObj( vtDialog ) +{ + setViewData(*((TDsgObjData *)attributes)); + defaultData.flags = flags; + ObjEdit->setObjData(this); + flags &= ~wfClose; + flags |= wfGrow | wfZoom; +// options |= ofCentered; + state |= sfEditing; + EditDlg = this; + setModified(False); +} + +void TDDialog::shutDown() +{ + if (modified) Save(cmCancel); + if (fileName) delete[] fileName; + _shutdown_(TDialog); +} + +void TDDialog::setModified(Boolean aState) +{ + modified = aState; +} + +void TDDialog::handleEvent(TEvent& event) +{ + TView * P; + TPoint mouse; + + if (event.what == evKeyboard) + { + switch(event.keyDown.keyCode) + { + case kbUp: selectNext(true); clearEvent(event); break; + case kbDown: selectNext(false); clearEvent(event); break; + case kbLeft: selectNext(true); clearEvent(event); break; + case kbRight: selectNext(false); clearEvent(event); break; + case kbCtrlDel: + if (current) + { + P = current; + remove(current); + delete P; + clearEvent(event); + } + break; + case kbEnter: + if (current) DsgDragView(current, dmDragMove|dmDragGrow, event); + clearEvent(event); + break; + default: TDialog::handleEvent(event); + } + } + else + if (event.what == evBroadcast) + { + if (event.message.command == cmItemDropped) + { + P = NULL; + if (FloatingView) { mouse = FloatingView->origin; mouse.y++; } + else mouse = Mouse->where; + if ( mouseInView(mouse) && !ToolDlg->mouseInView(mouse) && + !ObjEdit->mouseInView(mouse) ) + P = InitObject(makeLocal(mouse), + (TViewType)event.message.infoLong, sfEditing); + if (P) dinsert(P); + } + } + TDialog::handleEvent(event); + if (event.what == evMouseDown) ObjEdit->setObjData(this); +} + +void TDDialog::draw() { TDialog::draw(); } + +TFrame * TDDialog::initFrame( TRect r ) { return new TDFrame(r); } + +void TDDialog::setState(ushort aState, Boolean enable) +{ + TDialog::setState(aState, enable); +} + +void doCloneView(void * v, void * d) +{ + TDsgObj * Dsg = ((TDsgLink *)v)->d; + if (Dsg->viewType == vtLabel || + Dsg->viewType == vtVScroll || Dsg->viewType == vtHScroll) return; + TView * rst = Dsg->createView((TDialog *)d); + if (rst) ((TDialog *)d)->insert(rst); +} + +void TDDialog::dlgRun() +{ + TDDialogData * editData = (TDDialogData *)attributes; + + TDialog * d = new TDialog( TRect( getBounds() ), editData->title ); + ObjectLinker()->forEach(&doCloneView, (void *)d); + setupView(d); + d->flags = editData->flags; + hide(); + d->selectNext(false); + TProgram::deskTop->execView(d); + changeBounds(d->getBounds()); + TObject::CLY_destroy(d); + show(); +} + +void TDDialog::dinsert(TView * aView) +{ + aView->options |= ofSelectable | ofFirstClick | ofPreProcess | ofPostProcess; + aView->growMode = 0; + aView->setState(sfEditing, true); + TDsgLink * dl = ObjectLinker()->viewFind(aView); + if ((dl) && dl->d->tabStop()) + { + ((TDsgObjData *)dl->d->attributes)->tabOrder = TabOrder; + TabOrder++; + } + insert(aView); + setModified(True); +} + +void TDDialog::changeBounds(const TRect& bounds) {_chgbnds_(TDialog); } + +TView * TDDialog::Me() { return this; } + +void TDDialog::dsgUpdate() +{ + TDsgObj::dsgUpdate(); + TDDialogData * d = (TDDialogData *)attributes; + delete[] title; + title = newStr(d->title); + frame->drawView(); + setModified(True); +} + +void * TDDialog::dsgGetData() { return (void *)title; } + +Boolean TDDialog::Save(int aCommand) +{ + char * f; + int cmd = aCommand; + if (modified) + { + if (cmd != cmYes) + cmd = messageBox(__("The current dialog was modified. Save it?"), + mfYesNoCancel | mfWarning); + if ( cmd == cmYes && (fileName == 0 || strlen(fileName) == 0) ) + { + f = getFileName(_("Save dialog"), "*.fdg", 1); + if (f) + { + delete[] fileName; + fileName = f; + return True; + } + } + switch (cmd) + { + case cmYes: saveToFile(fileName); return True; + case cmNo: return True; + case cmCancel: return False; + } + } //else return True; + return True; +} + +static void saveObject(void * v, void * d) +{ + TDsgLink * dsg = (TDsgLink *)v; +#if 0 + char buf[255]; + if (dsg) + { + sprintf(buf, "Salvando objeto %s.", + ((TViewData *)dsg->d->attributes)->thisName); + messageBox(buf, 0); + SaveObject((ofpstream &)*d, dsg->d); + } +#endif +#if 1 + if (dsg) SaveObject(*((ofpstream *)d), dsg->d); +#endif +} + +Boolean TDDialog::saveToFile(const char * FileName) +{ + ofpstream * S = initFile(FileName, fileName, dialogFileSig); + if (S != 0) + { + ofpstream& s = *S; + s << viewType; + s.writeBytes(attributes, vtAttrSize[viewType]); + s << (GridState ? (char)1 : (char)0); + s << LabelCount << InputCount << MemoCount + << StaticCount << ButtonCount << ListBoxCount << RadioCount + << CheckCount << VScrollCount << HScrollCount << UserCount; + ObjectLinker()->sortForBuild(); + ObjectLinker()->forEach(&saveObject, &s); + s << vtNone; + s.close(); + delete S; + return True; + setModified(False); + } else return False; +} + +Boolean TDDialog::loadFromFile(const char * FileName) +{ + static int vtAux; + static TViewType vt; + + if (!Save(cmYes)) return False; + + if (!FileName) return False; + + if (fileName) + { + if (strcmp(FileName, fileName) == 0) return True; + delete[] fileName; + } + fileName = newStr(FileName); + + ifpstream * S = openFile(FileName, dialogFileSig); + TView * v; + TView * p = last; + do { + TView * t = p->prev(); + if (p != frame) CLY_destroy(p); + p = t; + } while (first() != last); + + if (S != 0) + { + ifpstream& s = *S; + s >> vtAux; vt = (TViewType)vtAux; + if (vt != vtDialog) { s.close(); return False; } + void * attr = readDsgInfo(s, vt); + memcpy(attributes, attr, vtAttrSize[vt]); + free(attr); + char aux; + s >> aux; GridState=aux ? True : False; + s >> LabelCount >> InputCount >> MemoCount + >> StaticCount >> ButtonCount >> ListBoxCount >> RadioCount + >> CheckCount >> VScrollCount >> HScrollCount >> UserCount; + dsgUpdate(); + TabOrder = 0; + v = LoadObject(s); + while (v) + { + dinsert(v); + TDsgLink * dsg = ObjectLinker()->viewFind(v); + if (dsg) dsg->d->dsgUpdate(); + v = LoadObject(s); + } + if (fileName) delete[] fileName; + fileName = strdup(FileName); + selectNext(True); + setModified(False); + s.close(); + delete S; + } //else return False; + return False; +} + +/* TDLabel ==============================================================*/ + +TDLabel::TDLabel(const TRect& bounds): + TLabel(bounds, __("~L~abel"), EditDlg), + TDsgObj( vtLabel ) + { setViewData(*((TDsgObjData *)attributes)); } + +void TDLabel::shutDown() { _shutdown_(TLabel); } + +void TDLabel::handleEvent(TEvent& event) {_h_(TLabel); } + +TPalette& TDLabel::getPalette() const + {_p_(cpDragLabel, cpSelLabel, TLabel); } + +void TDLabel::sizeLimits(TPoint& min, TPoint& max) + { GetSizeLimits(min, max, viewType); } + +void TDLabel::setState(ushort aState, Boolean enable) {_setstate_(TLabel); } + +void TDLabel::changeBounds(const TRect& bounds) {_chgbnds_(TLabel); } + +TView * TDLabel::Me() { return this; } + +void TDLabel::dsgUpdate() +{ + TDLabelData * d = (TDLabelData *)attributes; + delete[] text; + text = newStr(d->text); +// drawView(); + TDsgObj::dsgUpdate(); +} + +void * TDLabel::dsgGetData() { return (void *)text; } + +TView * TDLabel::createView(TView * aLink) +{ + TDLabelData * d = (TDLabelData *)attributes; + TLabel * rst = new TLabel(getBounds(), (char *)d->text, aLink); + setupView(rst); + return rst; +} + +/* TDInputLine ==========================================================*/ + +TDInputLine::TDInputLine(const TRect& bounds): + TInputLine(bounds, 0), + TDsgObj( vtInput ) + { setViewData(*((TDsgObjData *)attributes)); } + +void TDInputLine::shutDown() { _shutdown_(TInputLine); } + +void TDInputLine::handleEvent(TEvent& event) {_h_(TInputLine); } + +TPalette& TDInputLine::getPalette() const + {_p_(cpDragInput, cpSelInput, TInputLine); } + +void TDInputLine::sizeLimits(TPoint& min, TPoint& max) + { GetSizeLimits(min, max, viewType); } + +void TDInputLine::setState(ushort aState, Boolean enable) + {_setstate_(TInputLine); } + +void TDInputLine::changeBounds(const TRect& bounds) {_chgbnds_(TInputLine); } + +TView * TDInputLine::Me() { return this; } + +TView * TDInputLine::createView(TView * aOwner) +{ + TDInputData * d = (TDInputData *)attributes; + TInputLine * rst = new TInputLine(getBounds(), d->maxLen); +// if (d->validatorType != vtNone) +// switch(d->validatorType) +// { +// +// } + setupView(rst); + if (InsertLink(d->thisName, rst, (TDialog *)aOwner)) + return 0; + else + return rst; +} + +/* TDMemo ===============================================================*/ + +TDMemo::TDMemo(const TRect& bounds): + TMemo(bounds, 0, 0, 0, 0), + TDsgObj( vtMemo ) + { setViewData(*((TDsgObjData *)attributes)); } + +void TDMemo::shutDown() { _shutdown_(TMemo); } + +void TDMemo::handleEvent(TEvent& event) {_h_(TMemo); } + +TPalette& TDMemo::getPalette() const {_p_(cpDragMemo, cpSelMemo, TMemo); } + +void TDMemo::sizeLimits(TPoint& min, TPoint& max) + { GetSizeLimits(min, max, viewType); } + +void TDMemo::setState(ushort aState, Boolean enable) {_setstate_(TMemo); } + +void TDMemo::changeBounds(const TRect& bounds) {_chgbnds_(TMemo); } + +TView * TDMemo::Me() { return this; } + +TView * TDMemo::createView(TView * aOwner) +{ + TDMemoData * d = (TDMemoData *)attributes; + TScrollBar * vsb = 0; + TScrollBar * hsb = 0; + if (d->hScroll >= 0) hsb = FindScroll(d->hScroll, (TDialog *)aOwner); + if (d->vScroll >= 0) vsb = FindScroll(d->vScroll, (TDialog *)aOwner); + TMemo * rst = new TMemo(getBounds(), hsb, vsb, 0, d->bufSize); + setupView(rst); + if (InsertLink(d->thisName, rst, (TDialog *)aOwner)) + return 0; + else + return rst; +} + +/* TDStaticText =========================================================*/ + +TDStaticText::TDStaticText(const TRect& bounds): + TStaticText(bounds, "StaticText"), + TDsgObj( vtStatic ) + { setViewData(*((TDsgObjData *)attributes)); } + +void TDStaticText::shutDown() { _shutdown_(TStaticText); } + +void TDStaticText::handleEvent(TEvent& event) {_h_(TStaticText); } + +TPalette& TDStaticText::getPalette() const + {_p_(cpDragStatic, cpSelStatic, TStaticText); } + +void TDStaticText::sizeLimits(TPoint& min, TPoint& max) + { GetSizeLimits(min, max, viewType); } + +void TDStaticText::setState(ushort aState, Boolean enable) + {_setstate_(TStaticText); } + +void TDStaticText::changeBounds(const TRect& bounds) {_chgbnds_(TStaticText); } + +TView * TDStaticText::Me() { return this; } + +void TDStaticText::dsgUpdate() +{ + TDStaticData * d = (TDStaticData *)attributes; +// delete[] text; +// text = newStr(d->text); + text = d->text; // If was changed the text has been freed by the object + // editor and the new pointer is in attributes data + TDsgObj::dsgUpdate(); +// drawView(); +} + +void * TDStaticText::dsgGetData() { return (void *)text; } + +TView * TDStaticText::createView(TView * aOwner) +{ + TDStaticData * d = (TDStaticData *)attributes; + TStaticText * rst = new TStaticText(getBounds(), d->text); + setupView(rst); + return rst; +} + +/* TDButton =============================================================*/ + +TDButton::TDButton(const TRect& bounds): + TButton(bounds, "~O~k", 0, 0), + TDsgObj( vtButton ) + { setViewData(*((TDsgObjData *)attributes)); } + +void TDButton::shutDown() { _shutdown_(TButton); } + +void TDButton::handleEvent(TEvent& event) {_h_(TButton); } + +TPalette& TDButton::getPalette() const + {_p_(cpDragBtn, cpSelBtn, TButton); } + +void TDButton::sizeLimits(TPoint& min, TPoint& max) + { GetSizeLimits(min, max, viewType); } + +void TDButton::setState(ushort aState, Boolean enable) {_setstate_(TButton); } + +void TDButton::changeBounds(const TRect& bounds) {_chgbnds_(TButton); } + +TView * TDButton::Me() { return this; } + +void TDButton::dsgUpdate() +{ + TDButtonData * d = (TDButtonData *)attributes; + delete[] title; + title = newStr(d->title); + TDsgObj::dsgUpdate(); +// drawView(); +} + +void * TDButton::dsgGetData() { return (void *)title; } + +ushort TDButton::getCommand() { return command; } +ushort TDButton::getFlags() { return flags; } + +TView * TDButton::createView(TView * aOwner) +{ + TDButtonData * d = (TDButtonData *)attributes; + TButton * rst = new TButton(getBounds(), d->title, d->command, d->flags); + setupView(rst); + return rst; +} + +/* TDListBox ============================================================*/ + +TDListBox::TDListBox(const TRect& bounds): + TListBox(bounds, 1, 0), + TDsgObj( vtListBox ) + { setViewData(*((TDsgObjData *)attributes)); } + +void TDListBox::shutDown() { _shutdown_(TListBox); } + +void TDListBox::handleEvent(TEvent& event) {_h_(TListBox); } + +TPalette& TDListBox::getPalette() const + {_p_(cpDragLB, cpSelLB, TListBox); } + +void TDListBox::sizeLimits(TPoint& min, TPoint& max) + { GetSizeLimits(min, max, viewType); } + +void TDListBox::setState(ushort aState, Boolean enable) {_setstate_(TListBox); } + +void TDListBox::changeBounds(const TRect& bounds) {_chgbnds_(TListBox); } + +TView * TDListBox::Me() { return this; } + +void TDListBox::dsgUpdate() +{ +// setRange(items->getCount()); +// if (items->getCount() > 0) focusItem(0); +// TDsgObj::dsgUpdate(); + drawView(); +} + +void * TDListBox::dsgGetData() { return items; } + +TView * TDListBox::createView(TView * aOwner) +{ + TDListBoxData * d = (TDListBoxData *)attributes; + TScrollBar * sb = 0; + int cols = (d->columns > 0) ? d->columns : 1; + if (d->scrollBar >= 0) sb = FindScroll(d->scrollBar, (TDialog *)aOwner); + TListBox * rst = new TListBox(getBounds(), cols, sb); +// rst->newList(items); + setupView(rst); + if (InsertLink(d->thisName, rst, (TDialog *)aOwner)) + return 0; + else + return rst; +} + +/* TDRadioButtons =======================================================*/ + +TDRadioButtons::TDRadioButtons(const TRect& bounds, TSItem * aStrings): + TRadioButtons(bounds, aStrings), + TDsgObj( vtRadioButton ) + { setViewData(*((TDsgObjData *)attributes)); } + +void TDRadioButtons::shutDown() { _shutdown_(TRadioButtons); } + +void TDRadioButtons::handleEvent(TEvent& event) {_h_(TRadioButtons); } + +TPalette& TDRadioButtons::getPalette() const + {_p_(cpDragCluster, cpSelCluster, TCluster); } + +void TDRadioButtons::sizeLimits(TPoint& min, TPoint& max) + { GetSizeLimits(min, max, viewType); } + +void TDRadioButtons::setState(ushort aState, Boolean enable) + {_setstate_(TRadioButtons); } + +void TDRadioButtons::changeBounds(const TRect& bounds) + {_chgbnds_(TRadioButtons); } + +TView * TDRadioButtons::Me() { return this; } + +void * TDRadioButtons::dsgGetData() { return strings; } + +TView * TDRadioButtons::createView(TView * aOwner) +{ + TDRadioData * d = (TDRadioData *)attributes; + TRadioButtons * rst = new TRadioButtons(getBounds(), strCollToItems(strings)); + rst->setData(&value); + setupView(rst); + if (InsertLink(d->thisName, rst, (TDialog *)aOwner)) + return 0; + else + return rst; +} + +/* TDCheckBoxes =========================================================*/ + +TDCheckBoxes::TDCheckBoxes(const TRect& bounds, TSItem * aStrings): + TCheckBoxes(bounds, aStrings), + TDsgObj( vtCheckBox ) + { setViewData(*((TDsgObjData *)attributes)); } + +void TDCheckBoxes::shutDown() { _shutdown_(TCheckBoxes); } + +void TDCheckBoxes::handleEvent(TEvent& event) {_h_(TCheckBoxes); } + +TPalette& TDCheckBoxes::getPalette() const + {_p_(cpDragCluster, cpSelCluster, TCluster); } + +void TDCheckBoxes::sizeLimits(TPoint& min, TPoint& max) + { GetSizeLimits(min, max, viewType); } + +void TDCheckBoxes::setState(ushort aState, Boolean enable) + { _setstate_(TCheckBoxes); } + +void TDCheckBoxes::changeBounds(const TRect& bounds) {_chgbnds_(TCheckBoxes); } + +TView * TDCheckBoxes::Me() { return this; } + +//void TDCheckBoxes::dsgUpdate() { TDsgObj::dsgUpDate(); } + +void * TDCheckBoxes::dsgGetData() { return strings; } + +TView * TDCheckBoxes::createView(TView * aOwner) +{ + TDCheckData * d = (TDCheckData *)attributes; + TCheckBoxes * rst = new TCheckBoxes(getBounds(), strCollToItems(strings)); + rst->setData(&value); + setupView(rst); + if (InsertLink(d->thisName, rst, (TDialog *)aOwner)) + return 0; + else + return rst; +} + +/* TVScrollBar ==========================================================*/ + +TVScrollBar::TVScrollBar(const TRect& bounds): + TScrollBar(bounds), + TDsgObj( vtVScroll ) + { setViewData(*((TDsgObjData *)attributes)); } + +void TVScrollBar::shutDown() { _shutdown_(TScrollBar); } + +void TVScrollBar::handleEvent(TEvent& event) {_h_(TScrollBar); } + +TPalette& TVScrollBar::getPalette() const + {_p_(cpDragScroll, cpSelScroll, TScrollBar); } + +void TVScrollBar::sizeLimits(TPoint& min, TPoint& max) + { GetSizeLimits(min, max, viewType); } + +void TVScrollBar::setState(ushort aState, Boolean enable) + {_setstate_(TScrollBar); } + +void TVScrollBar::changeBounds(const TRect& bounds) {_chgbnds_(TScrollBar); } + +TView * TVScrollBar::Me() { return this; } + +TView * TVScrollBar::createView(TView * aOwner) +{ + TScrollBar * rst = new TScrollBar(getBounds()); + setupView(rst); + return rst; +} + +/* THScrollBar ==========================================================*/ + +THScrollBar::THScrollBar(const TRect& bounds): + TScrollBar(bounds), + TDsgObj( vtHScroll ) + { setViewData(*((TDsgObjData *)attributes)); } + +void THScrollBar::shutDown() { _shutdown_(TScrollBar); } + +void THScrollBar::handleEvent(TEvent& event) {_h_(TScrollBar); } + +TPalette& THScrollBar::getPalette() const + {_p_(cpDragScroll, cpSelScroll, TScrollBar); } + +void THScrollBar::sizeLimits(TPoint& min, TPoint& max) + { GetSizeLimits(min, max, viewType); } + +void THScrollBar::setState(ushort aState, Boolean enable) + {_setstate_(TScrollBar); } + +void THScrollBar::changeBounds(const TRect& bounds) {_chgbnds_(TScrollBar); } + +TView * THScrollBar::Me() { return this; } + +TView * THScrollBar::createView(TView * aOwner) +{ + TScrollBar * rst = new TScrollBar(getBounds()); + setupView(rst); + return rst; +} + +/* Fim ==================================================================*/ + +#undef _h_ +#undef _p_ +#undef _chgbnds_ +#undef _setstate_ diff --git a/tvision/examples/dlgdsn/dsgobjs.h b/tvision/examples/dlgdsn/dsgobjs.h new file mode 100644 index 0000000..396e291 --- /dev/null +++ b/tvision/examples/dlgdsn/dsgobjs.h @@ -0,0 +1,369 @@ +/*************************************************************************** + + dsgobjs.h - Editable classes prototypes + --------------------------------------------------------------------- + May, 2000 + Copyright (C) 2000 by Warlei Alves + walves@usa.net + + Modified by Salvador E. Tropea to compile without warnings. + This header allocated a couple of structures in each file that used it. + + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#if !defined(_DSGOBJS_HPP_) +#define _DSGOBJS_HPP_ + +#include + +#define Uses_TDialog +#define Uses_TFrame +#define Uses_TPalette +#define Uses_TInputLine +#define Uses_TButton +#define Uses_TCheckBoxes +#define Uses_TRadioButtons +#define Uses_TScrollBar +#define Uses_TRect +#define Uses_TEvent +#define Uses_TStaticText +#define Uses_TListBox +#define Uses_TProgram +#define Uses_TMemo +#define Uses_TLabel +#define Uses_TSItem +#define Uses_TCollection +#define Uses_TMenuBar +#define Uses_TStatusLine +#define Uses_TDeskTop +#define Uses_TWindow + +#include + +#include "fdconsts.h" +#include "dsgdata.h" +#include "propedit.h" +/* +typedef short TViewType; + +const TViewType + vtNone = -1, + vtOther = 0, + vtLabel = 1, + vtInput = 2, + vtMemo = 3, + vtStatic = 4, + vtButton = 5, + vtListBox = 6, + vtRadioButton = 7, + vtCheckBox = 8, + vtVScroll = 9, + vtHScroll = 10, + vtDialog = 11; +*/ +enum TViewType { vtNone = -1, vtOther, vtLabel, vtInput, vtMemo, vtStatic, + vtButton, vtListBox, vtRadioButton, vtCheckBox, vtVScroll, vtHScroll, + vtDialog }; + + +class TEditCollection: public TCollection +{ +public: + TEditCollection(): TCollection(0, 1) { }; + virtual void * readItem(ipstream &) { return 0; }; + virtual void writeItem(void *, opstream &) { }; +}; + +class TAppWindow: public TWindow +{ + TDeskTop * deskTop; + TMenuBar * menuBar; + TStatusLine * statusLine; + void removeStatusLine(); + void removeMenuBar(); +public: + TAppWindow(); + ~TAppWindow(); + TEditCollection * dsgMenuBar; + TEditCollection * dsgSatusLine; + TEditCollection * dialogs; + static TFrame * initFrame(TRect r); + virtual TPalette& getPalette() const; + void setMenuBar(TEditCollection * aItems); + void setStatusLine(TEditCollection * aItems); + void setMenuBar(TMenuBar * aMenuBar); + void setStatusLine(TStatusLine * aStatusLine); + virtual void handleEvent(TEvent& event); + virtual void changeBounds(const TRect& bounds); +}; + +class TDFrame: public TFrame +{ +public: + TDFrame(const TRect& bounds); + virtual void draw(); +}; + +class opstream; + +class TDsgObj +{ +protected: + int attrSize; + int nameIndex; + void buildName(TNameStr * name, int mode); + virtual void setViewData(TDsgObjData& data); + virtual TView * Me() { return 0; }; + virtual void setupView(TView * View); +public: + TDsgObj(TViewType ViewType); + virtual ~TDsgObj(); + char * getScript(ushort ScriptType); + void setPos(TPoint neworigin, TPoint newsize); + virtual void dsgUpdate(); + virtual void * dsgGetData() { return 0; }; + virtual TView * createView(TView *) { return 0; }; + int getAttrSize() { return attrSize; }; + + void * attributes; + TViewType viewType; + TDefaultData defaultData; + TDsgObj * dsgObj; + bool tabStop(); +}; + +class TDDialog: public TDialog, public TDsgObj +{ + char * fileName; +protected: + virtual TView * Me(); +public: + TDDialog(); + virtual void shutDown(); + virtual void draw(); + static TFrame * initFrame(TRect r); + virtual void handleEvent(TEvent& event); + virtual void setState(ushort aState, Boolean enabled); +// void setCurrentClass(ushort aClass); + void dinsert(TView * aView); + virtual void changeBounds(const TRect& bounds); + void dlgRun(); + + virtual void dsgUpdate(); + virtual void * dsgGetData(); + Boolean saveToFile(const char * FileName); + Boolean Save(int aCommand = cmCancel); + Boolean loadFromFile(const char * FileName); + void setModified(Boolean); + Boolean modified; +}; + +//class TDsgView: public TView, public TDsgObj { }; + +class TDLabel: public TLabel, public TDsgObj +{ +protected: + virtual TView * Me(); +public: + TDLabel(const TRect& bounds); + virtual void shutDown(); + virtual void handleEvent(TEvent& event); + virtual TPalette& getPalette() const; + virtual void sizeLimits(TPoint& min, TPoint& max); + virtual void setState(ushort aState, Boolean enable); + virtual void changeBounds(const TRect& bounds); + + virtual void dsgUpdate(); + virtual void * dsgGetData(); + virtual TView * createView(TView * aLink); +}; + +class TDInputLine: public TInputLine, public TDsgObj +{ +protected: + virtual TView * Me(); +public: + TDInputLine(const TRect& bounds); + virtual void shutDown(); + virtual void handleEvent(TEvent& event); + virtual TPalette& getPalette() const; + virtual void sizeLimits(TPoint& min, TPoint& max); + virtual void setState(ushort aState, Boolean enable); + virtual void changeBounds(const TRect& bounds); + +// virtual void dsgUpdate(); +// virtual void * dsgGetData(); + virtual TView * createView(TView * aView); +}; + +class TDMemo: public TMemo, public TDsgObj +{ +protected: + virtual TView * Me(); +public: + TDMemo(const TRect& bounds); + virtual void shutDown(); + virtual void handleEvent(TEvent& event); + virtual TPalette& getPalette() const; + virtual void sizeLimits(TPoint& min, TPoint& max); + virtual void setState(ushort aState, Boolean enable); + virtual void changeBounds(const TRect& bounds); + +// virtual void dsgUpdate(); +// virtual void * dsgGetData(); + virtual TView * createView(TView * aView); +}; + +class TDStaticText: public TStaticText, public TDsgObj +{ +protected: + virtual TView * Me(); +public: + TDStaticText(const TRect& bounds); + virtual void shutDown(); + virtual void handleEvent(TEvent& event); + virtual TPalette& getPalette() const; + virtual void sizeLimits(TPoint& min, TPoint& max); + virtual void setState(ushort aState, Boolean enable); + virtual void changeBounds(const TRect& bounds); + + virtual void dsgUpdate(); + virtual void * dsgGetData(); + virtual TView * createView(TView * aView); +}; + + +class TDButton: public TButton, public TDsgObj +{ +protected: + virtual TView * Me(); +public: + TDButton(const TRect& bounds); + virtual void shutDown(); + virtual void handleEvent(TEvent& event); + virtual TPalette& getPalette() const; + virtual void sizeLimits(TPoint& min, TPoint& max); + virtual void setState(ushort aState, Boolean enable); + virtual void changeBounds(const TRect& bounds); + + ushort getCommand(); + ushort getFlags(); + virtual void dsgUpdate(); + virtual void * dsgGetData(); + virtual TView * createView(TView * aView); +}; + +class TDListBox: public TListBox, public TDsgObj +{ +protected: + virtual TView * Me(); +public: + TDListBox(const TRect& bounds); + virtual void shutDown(); + virtual void handleEvent(TEvent& event); + virtual TPalette& getPalette() const; + virtual void sizeLimits(TPoint& min, TPoint& max); + virtual void setState(ushort aState, Boolean enable); + virtual void changeBounds(const TRect& bounds); + + virtual void dsgUpdate(); + virtual void * dsgGetData(); + virtual TView * createView(TView * aView); +}; + + +class TDRadioButtons: public TRadioButtons, public TDsgObj +{ +protected: + virtual TView * Me(); +public: + TDRadioButtons(const TRect& bounds, TSItem * aStrings); + virtual void shutDown(); + virtual void handleEvent(TEvent& event); + virtual TPalette& getPalette() const; + virtual void sizeLimits(TPoint& min, TPoint& max); + virtual void setState(ushort aState, Boolean enable); + virtual void changeBounds(const TRect& bounds); + +// virtual void dsgUpdate(); + virtual void * dsgGetData(); + virtual TView * createView(TView * aView); +}; + + +class TDCheckBoxes: public TCheckBoxes, public TDsgObj +{ +protected: + virtual TView * Me(); +public: + TDCheckBoxes(const TRect& bounds, TSItem * aStrings); + virtual void shutDown(); + virtual void handleEvent(TEvent& event); + virtual TPalette& getPalette() const; + virtual void sizeLimits(TPoint& min, TPoint& max); + virtual void setState(ushort aState, Boolean enable); + virtual void changeBounds(const TRect& bounds); + +// virtual void dsgUpdate(); + virtual void * dsgGetData(); + virtual TView * createView(TView * aView); +}; + +class TVScrollBar: public TScrollBar, public TDsgObj +{ +protected: + virtual TView * Me(); +public: + TVScrollBar(const TRect& bounds); + virtual void shutDown(); + virtual void handleEvent(TEvent& event); + virtual TPalette& getPalette() const; + virtual void sizeLimits(TPoint& min, TPoint& max); + virtual void setState(ushort aState, Boolean enable); + virtual void changeBounds(const TRect& bounds); + virtual TView * createView(TView * aView); +}; + +class THScrollBar: public TScrollBar, public TDsgObj +{ +protected: + virtual TView * Me(); +public: + THScrollBar(const TRect& bounds); + virtual void shutDown(); + virtual void handleEvent(TEvent& event); + virtual TPalette& getPalette() const; + virtual void sizeLimits(TPoint& min, TPoint& max); + virtual void setState(ushort aState, Boolean enable); + virtual void changeBounds(const TRect& bounds); + virtual TView * createView(TView * aView); +}; + +void InitDlgEditor(const char * FileName); + +void DoneDialogEditor(); + +TDDialog * DialogEditor(); + +TDialog * ToolDialog(); + +TWindow * ObjectEditor(); + +void SetGrid(bool enable); + +bool GetGrid(); + +// Code builder functions +const char * buildCode(TDsgObj * aObj, char * buffer); + +#endif //_DSGOBJS_HPP_ + diff --git a/tvision/examples/dlgdsn/fdconsts.h b/tvision/examples/dlgdsn/fdconsts.h new file mode 100644 index 0000000..dc6757c --- /dev/null +++ b/tvision/examples/dlgdsn/fdconsts.h @@ -0,0 +1,105 @@ +/*************************************************************************** + + fdconsts.h - Commom application constants + --------------------------------------------------------------------- + May, 2000 + Copyright (C) 2000 by Warlei Alves + walves@usa.net + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#if !defined(_FDCONSTS_HPP_) +#define _FDCONSTS_HPP_ + +//---> FreeDsg constants + +const unsigned short + cmFirst = 100, + cmOpenProject = cmFirst + 1, + cmSaveProject = cmFirst + 2, + cmSaveProjectAs = cmFirst + 3, + cmOpenObj = cmFirst + 4, + cmSaveObj = cmFirst + 5, + cmSaveObjAs = cmFirst + 6, + + cmWriteObjFunc = cmFirst + 7, + cmWriteObjUnit = cmFirst + 8, + + cmShowGrid = cmFirst + 9, + + cmViewProject = cmFirst + 10, + cmMenuEditor = cmFirst + 11, + cmStatusEditor = cmFirst + 12, + cmHintsEditor = cmFirst + 13, + cmCommandEdit = cmFirst + 14, + cmHelpCtxEdit = cmFirst + 15, + cmAppOptions = cmFirst + 16, + cmBuildApp = cmFirst + 17, + cmViewAppWindow = cmFirst + 18, + + cmDialogEditor = cmFirst + 19, + cmObjects = cmFirst + 20, + cmObjEditor = cmFirst + 21, + cmNewProject = cmFirst + 22, + + cmEditEvents = cmFirst + 0xff, + cmItemDropped = cmEditEvents + 1, + cmResizeObj = cmEditEvents + 2, + cmValueChanged = cmEditEvents + 3, + cmDlgRun = cmEditEvents + 4, + + hcFirst = 1000, + hcOpenProject = hcFirst + 1, + hcSaveProject = hcFirst + 2, + hcSavePrjAs = hcFirst + 3, + hcChangeDir = hcFirst + 4, + hcOpenObj = hcFirst + 5, + hcSaveObj = hcFirst + 6, + hcSaveObjAs = hcFirst + 7, + hcQuit = hcFirst + 8, + + hcUndo = hcFirst + 9, + hcCopy = hcFirst + 10, + hcCut = hcFirst + 11, + hcPaste = hcFirst + 12, + + hcWriteCode = hcFirst + 13, + hcWriteFunc = hcFirst + 14, + hcWriteUnit = hcFirst + 15, + + hcHideShowGrid = hcFirst + 16, + + hcViewProject = hcFirst + 17, + hcMenuEdit = hcFirst + 18, + hcStatusEdit = hcFirst + 19, + hcHindEdit = hcFirst + 20, + hcCommandEdit = hcFirst + 21, + hcHelpCtxEdit = hcFirst + 22, + hcAppOptions = hcFirst + 23, + hcAppBuild = hcFirst + 24, + hcViewAppWindow = hcFirst + 25, + hcNewProject = hcFirst + 26, + +// Status defs contexts + hcDefs = hcFirst + 1000, + + hcCommandEditor = hcDefs + 1, + hcHelpCtxEditor = hcDefs + 2, + hcDlgTring = hcDefs + 3, + hcMenuEditor = hcDefs + 4, + hcStatusEditor = hcDefs + 5, + hcDlgEditor = hcDefs + 6, + hcObjWindow = hcDefs + 7, + hcObjEditor = hcDefs + 8; + +#endif // _FDCONSTS_HPP_ + diff --git a/tvision/examples/dlgdsn/freedsgn.cc b/tvision/examples/dlgdsn/freedsgn.cc new file mode 100644 index 0000000..2c2e7d5 --- /dev/null +++ b/tvision/examples/dlgdsn/freedsgn.cc @@ -0,0 +1,370 @@ +/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + \ /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ / + -----=====<<<| FREEDSGN - A Turbo Vision App Design Helper |>>>=====----- + -----=====<<<| Version 0.1 - copyright (c) 1999 Warlei Alves |>>>=====----- + / \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ \ + + w a l v e s @ u s a . n e t + + -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ + +/*************************************************************************** + * * + * 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 + +#define Uses_TApplication +#define Uses_TProgram +#define Uses_TDesktop +#define Uses_TRect +#define Uses_TView +#define Uses_MsgBox +#define Uses_TMenuBar +#define Uses_TSubMenu +#define Uses_TMenuItem +#define Uses_TStatusLine +#define Uses_TStatusItem +#define Uses_TStatusDef +#define Uses_TKeys +#define Uses_TEditor +#define Uses_TDialog +#define Uses_TCheckBoxes +#define Uses_TRadioButtons +#define Uses_TSItem +#define Uses_TFileDialog +#define Uses_TChDirDialog +#define Uses_ofpstream +#define Uses_ifpstream + +#include + +// Inclusoes locais =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + +#include "dsgobjs.h" +#include "consted.h" +#include "strmoper.h" + +class TFreeDsgnApp: public TApplication +{ +public: + TFreeDsgnApp(); + virtual void handleEvent(TEvent& event); + static TMenuBar * initMenuBar( TRect r ); + static TStatusLine * initStatusLine( TRect r ); + virtual void outOfMemory(); +// virtual void idle(); +private: + void viewBuffer(TMemoData& r); + TDialog * ToolDlg; + TDDialog * EditDialog; + TWindow * ObjEdit; + TWindow * srcWindow; + TEditor * srcBuffer; + TConstCollection * PrjCommands; + TConstCollection * PrjHelpCtxs; + TConstEdit * CommandEditor; + TConstEdit * HelpCtxEditor; + TWindow * HintsEditor; + TWindow * MenusEditor; + TWindow * StatusDefEditor; + TWindow * TextViewer; +}; + +TFreeDsgnApp::TFreeDsgnApp(): + TProgInit(&TFreeDsgnApp::initStatusLine, + &TFreeDsgnApp::initMenuBar, + &TApplication::initDeskTop), TApplication() +{ + PrjCommands = CommandsList(); + PrjHelpCtxs = HelpCtxsList(); + InitDlgEditor(0); + EditDialog = DialogEditor(); + ToolDlg = ToolDialog(); + ObjEdit = ObjectEditor(); + getPalette().data[0x3f] = 0x4f; + getPalette().data[0x3e] = 0x38; + CommandEditor = HelpCtxEditor = 0; + HintsEditor = MenusEditor = StatusDefEditor = srcWindow = 0; +} + +void TFreeDsgnApp::viewBuffer(TMemoData& rec) +{ + TRect r = deskTop->getExtent(); + srcWindow = new TWindow(r, "Dialog function", 0); + TScrollBar * vs = new TScrollBar( + TRect(r.b.x - 1, r.a.y + 1, r.b.x, r.b.y - 1) ); + TScrollBar * hs = new TScrollBar( + TRect(r.a.x + 1, r.b.y - 1, r.b.x - 1, r.b.y) ); + srcWindow->insert(vs); + srcWindow->insert(hs); + r.grow(-1, -1); + srcBuffer = new TEditor(r, hs, vs, 0, rec.length); + srcWindow->insert(srcBuffer); + srcBuffer->insertText(rec.buffer, rec.length, False); + deskTop->insert(srcWindow); +} + +void TFreeDsgnApp::handleEvent(TEvent& event) +{ + TDialog * d; + TWindow * w; + TRect r; + const char * str; + + if (( event.what == evCommand ) && ( event.message.command == cmQuit )) + { + if ( messageBox( __("Are you sure?"), + mfConfirmation | mfYesButton | mfCancelButton ) != cmYes ) + clearEvent(event); + } + + TApplication::handleEvent(event); + + if (event.what == evBroadcast) + { + switch(event.message.command) + { + case cmClosingWindow: + w = (TWindow *) event.message.infoPtr; + if (w == CommandEditor) CommandEditor = 0; + if (w == HelpCtxEditor) HelpCtxEditor = 0; + if (w == HintsEditor) HintsEditor = 0; + if (w == MenusEditor) MenusEditor = 0; + if (w == StatusDefEditor) StatusDefEditor = 0; + if (w == EditDialog) EditDialog = 0; + if (w == ObjEdit) ObjEdit = 0; + if (w == ToolDlg) ToolDlg = 0; + if (w == srcWindow) srcWindow = 0; + break; + default:; + } + } + else + if (event.what == evCommand ) + { + switch(event.message.command) + { + case cmNewProject: + InitDlgEditor(0); + break; + case cmShowGrid: + SetGrid(!GetGrid()); + break; +/* case cmStatic...cmVoid: + EditDialog->setCurrentClass(event.message.command); + break; */ + case cmDialogEditor: + if (!EditDialog) break; + if (!indexOf(EditDialog)) insert(EditDialog); + EditDialog->select(); + break; + case cmObjEditor: + if (!ObjEdit) break; + if (!indexOf(ObjEdit)) insert(ObjEdit); + ObjEdit->select(); + break; + case cmObjects: + if (!ToolDlg) break; + if (!indexOf(ToolDlg)) insert(ToolDlg); + ToolDlg->select(); + break; + case cmDlgRun: + if (EditDialog) EditDialog->dlgRun(); + break; +// case cmCalculator: +// break; + case cmCommandEdit: + if (CommandEditor) + CommandEditor->select(); + else + { + CommandEditor = new TConstEdit(); + CommandEditor->Edit(PrjCommands); + } + break; + case cmHelpCtxEdit: + if (HelpCtxEditor) + HelpCtxEditor->select(); + else + { + HelpCtxEditor = new TConstEdit(); + HelpCtxEditor->Edit(PrjHelpCtxs); + } + break; + case cmViewAppWindow: + w = new TAppWindow(); + r = w->getExtent(); +// r.b.y = r.a.y + 1; + ((TAppWindow *)w)->setMenuBar(initMenuBar(r)); +// r = w->getExtent(); +// r.a.y = r.b.y - 1; + ((TAppWindow *)w)->setStatusLine(initStatusLine(r)); + application->execView(w); + TObject::CLY_destroy(w); + break; + case cmChangeDir: + d = (TDialog *) validView( new TChDirDialog(0, 0) ); + if (d != 0) + { + deskTop->execView(d); + TObject::CLY_destroy(d); + } + break; + case cmOpenObj: + str = getFileName(_("Open a dialog"), "*.fd*", 0); + if (str != 0) InitDlgEditor(str); + delete[] str; + break; + case cmSaveObj: + if (EditDialog) EditDialog->Save(cmYes); + break; + case cmSaveObjAs: + if (EditDialog) + { + str = getFileName(_("Save dialog as"), "*.fdg", 1); + if (str) EditDialog->saveToFile(str); + delete[] str; + } + break; + case cmWriteObjFunc: + if (srcWindow != 0) break; + TMemoData r; + strcpy(r.buffer, ""); + buildCode(EditDialog, r.buffer); + r.length = strlen(r.buffer); + viewBuffer(r); + break; + case cmSave: + if (srcWindow) + { + str = getFileName(_("Save dialog as"), "*.src", 1); + if (str) + { + ofpstream * s = new ofpstream(str); + s->writeBytes(srcBuffer->buffer, srcBuffer->bufLen); + s->close(); + delete s; + delete[] str; + } + } + break; + default: return; + } + } + clearEvent(event); +} + +TMenuBar * TFreeDsgnApp::initMenuBar( TRect r ) +{ + TMenuItem& menuBuild = *new TSubMenu( __("~B~uild obj code..."), kbNoKey, hcNoContext) + + *new TMenuItem( __("As ~f~unction"), cmWriteObjFunc, kbNoKey, hcWriteFunc) + + *new TMenuItem( __("As f~i~le"), cmWriteObjUnit, kbNoKey, hcWriteUnit); + + TSubMenu& menuOptions = *new TSubMenu( __("~O~ptions"), kbNoKey, hcNoContext) + + *new TMenuItem( __("~G~rid On/Off"), cmShowGrid, kbNoKey, hcNoContext); + + TSubMenu& menuProject = *new TSubMenu( __("~P~roject"), kbNoKey, hcNoContext) + + *new TMenuItem( __("~V~iew..."), cmViewProject, kbNoKey, hcViewProject) + + *new TMenuItem( __("~M~enu editor..."), cmMenuEditor, kbNoKey, hcMenuEdit) + + *new TMenuItem( __("~S~tatus bar..."), cmStatusEditor, kbNoKey, hcStatusEdit) + + *new TMenuItem( __("H~i~nts..."), cmHintsEditor, kbNoKey, hcHindEdit) + + *new TMenuItem( __("~C~ommands..."), cmCommandEdit, kbNoKey, hcCommandEdit) + + *new TMenuItem( __("~H~elp contexts..."), cmHelpCtxEdit, kbNoKey, hcHelpCtxEdit) + + newLine() + + *new TMenuItem( __("~A~pp options..."), cmAppOptions, kbNoKey, hcAppOptions) + + *new TMenuItem( __("~G~enerate APP code..."), cmBuildApp, kbNoKey, hcAppBuild) + + newLine() + + *new TMenuItem( __("App ~W~indow"), cmViewAppWindow, kbNoKey, hcViewAppWindow); + + TSubMenu& menuEdit = *new TSubMenu( __("~E~dit"), kbNoKey, hcNoContext ) + +// *new TMenuItem( __("~U~ndelete"), cmUndo, kbAltBack, hcUndo, "Alt+BkSpc") + + *new TMenuItem( __("~C~opy"), cmCopy, kbShiftIns, hcCopy, "Shift+Ins") + + *new TMenuItem( __("C~u~t"), cmCut, kbShiftDel, hcCut, "Shift+Del") + + *new TMenuItem( __("~P~aste"), cmPaste, kbCtrlIns, hcPaste, "Ctrl+Ins") + + newLine() + + menuBuild; + + TSubMenu& menuFile = *new TSubMenu(__("~F~ile"), kbNoKey, hcNoContext ) + + *new TMenuItem( __("~N~ew project..."), cmNewProject, kbNoKey, hcNewProject ) + + *new TMenuItem( __("~O~pen project..."), cmOpenProject, kbNoKey, hcOpenProject ) + + *new TMenuItem( __("~S~ave project..."), cmSaveProject, kbNoKey, hcSaveProject ) + + *new TMenuItem( __("Sa~v~e project as..."), cmSaveProjectAs, kbNoKey, hcSavePrjAs ) + + newLine() + + *new TMenuItem( __("O~p~en object..."), cmOpenObj, kbNoKey, hcOpenObj ) + + *new TMenuItem( __("Save ~o~bject..."), cmSaveObj, kbNoKey, hcSaveObj ) + + *new TMenuItem( __("Save object ~a~s..."), cmSaveObjAs, kbNoKey, hcSaveObjAs ) + + *new TMenuItem( __("Save ~s~ource..."), cmSave, kbNoKey, hcNoContext ) + + newLine() + + *new TMenuItem( __("~C~hange directory..."), cmChangeDir, kbNoKey, hcChangeDir ) + + *new TMenuItem( __("~Q~uit"), cmQuit, kbNoKey, hcQuit ); + + r.b.y = r.a.y + 1; + return new TMenuBar( r, menuFile + + menuEdit + + menuProject + + menuOptions + ); +} + +TStatusLine * TFreeDsgnApp::initStatusLine( TRect r ) +{ +#define CommomHide() *new TStatusItem(__("~F1~ Help"), kbF1, cmHelp) + \ + *new TStatusItem(0, kbAltQ, cmQuit) + \ + *new TStatusItem(0, kbAltF3, cmClose) + \ + *new TStatusItem(0, kbF5, cmZoom) + \ + *new TStatusItem(0, kbCtrlF5, cmResize) + \ + *new TStatusItem(0, kbF6, cmNext) + \ + *new TStatusItem(0, kbShiftF6, cmPrev) +// r = deskTop->getExtent(); + r.a.y = r.b.y - 1; + return new TStatusLine(r, + *new TStatusDef( 0, 0xffff ) + + CommomHide() + + *new TStatusItem(__("~F7~ Objects"), kbF7, cmObjects ) + + *new TStatusItem(__("~F8~ Dialog"), kbF8, cmDialogEditor ) + + *new TStatusItem(__("~F9~ Obj Editor"), kbF9, cmObjEditor ) + + *new TStatusItem(__("~^F9~ Run dialog"), kbCtrlF9, cmDlgRun ) + + *new TStatusDef(hcDragging, hcDragging) + + *new TStatusItem(__("~PgUp/PgDn/Home/End~ to limits"), 0, 0) + + *new TStatusItem(__("~\x18\x19\x1a\x1b~ Move"), 0, 0 ) + + *new TStatusItem(__("~^+[\x18\x19\x1a\x1b]~ tab move"), 0, 0 ) + + *new TStatusItem(__("~Shift+[\x18\x19\x1a\x1b]~ Resize"), 0, 0 ) + + *new TStatusItem(__("~ENTER~ put"), 0, 0 ) + + *new TStatusItem(__("~ESC~ cancel"), 0, 0 ) + ); +} + +void TFreeDsgnApp::outOfMemory() +{ + messageBox( __("Not enough memory for this operation."), mfError | mfOKButton ); +} + + +int main() +{ + const char * _LocaleDir = TVIntl::bindTextDomain("mtv", NULL); + if (_LocaleDir) + { + char * LocaleDir = strdup(_LocaleDir); + setlocale(LC_ALL, ""); // Utilizando ambiente LANG + TVIntl::bindTextDomain("mtv", LocaleDir); // Ajusta o caminho + TVIntl::textDomain("mtv"); // Confirma o arquivo mo + free(LocaleDir); + } + TFreeDsgnApp *app = new TFreeDsgnApp(); + if (app) + { + app->run(); + delete app; + } + return 0; +} diff --git a/tvision/examples/dlgdsn/libtest.gpr b/tvision/examples/dlgdsn/libtest.gpr new file mode 100644 index 0000000..488bb61 Binary files /dev/null and b/tvision/examples/dlgdsn/libtest.gpr differ diff --git a/tvision/examples/dlgdsn/libtest.mkf b/tvision/examples/dlgdsn/libtest.mkf new file mode 100644 index 0000000..ca527ec --- /dev/null +++ b/tvision/examples/dlgdsn/libtest.mkf @@ -0,0 +1,11 @@ +#!/usr/bin/make +# +# Copyright (c) 2003-2004 by Salvador E. Tropea. +# Covered by the GPL license. +# +vpath_src= +vpath_obj=. +INCLUDE_DIRS=../../include +COMMON_IMK=../../makes/common.imk +include $(COMMON_IMK) +include libtest$(ExIMK) diff --git a/tvision/examples/dlgdsn/libtest.umk b/tvision/examples/dlgdsn/libtest.umk new file mode 100644 index 0000000..075fc5f --- /dev/null +++ b/tvision/examples/dlgdsn/libtest.umk @@ -0,0 +1,52 @@ +#!/usr/bin/make +# Automatically generated from RHIDE projects, don't edit +# + +OBJFILES=\ + ./codebldr$(ExOBJ) \ + ./consted$(ExOBJ) \ + ./dsgobjs$(ExOBJ) \ + ./freedsgn$(ExOBJ) \ + ./propdlgs$(ExOBJ) \ + ./propedit$(ExOBJ) \ + ./strmoper$(ExOBJ) \ + ./tappwnd$(ExOBJ) + +LIBRARIES= + +freedsgn$(ExEXE):: \ + ./codebldr$(ExOBJ) \ + ./consted$(ExOBJ) \ + ./dsgobjs$(ExOBJ) \ + ./freedsgn$(ExOBJ) \ + ./propdlgs$(ExOBJ) \ + ./propedit$(ExOBJ) \ + ./strmoper$(ExOBJ) \ + ./tappwnd$(ExOBJ) \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_LINK) + +./codebldr$(ExOBJ):: codebldr.cc + $(RHIDE_COMPILE_CC) + +./consted$(ExOBJ):: consted.cc + $(RHIDE_COMPILE_CC) + +./dsgobjs$(ExOBJ):: dsgobjs.cc + $(RHIDE_COMPILE_CC) + +./freedsgn$(ExOBJ):: freedsgn.cc + $(RHIDE_COMPILE_CC) + +./propdlgs$(ExOBJ):: propdlgs.cc + $(RHIDE_COMPILE_CC) + +./propedit$(ExOBJ):: propedit.cc + $(RHIDE_COMPILE_CC) + +./strmoper$(ExOBJ):: strmoper.cc + $(RHIDE_COMPILE_CC) + +./tappwnd$(ExOBJ):: tappwnd.cc + $(RHIDE_COMPILE_CC) + diff --git a/tvision/examples/dlgdsn/propdlgs.cc b/tvision/examples/dlgdsn/propdlgs.cc new file mode 100644 index 0000000..5d85fa5 --- /dev/null +++ b/tvision/examples/dlgdsn/propdlgs.cc @@ -0,0 +1,545 @@ +/*************************************************************************** + + propdlgs.cc - Implements the object property dialog editor + --------------------------------------------------------------------- + May, 2000 + Copyright (C) 2000 by Warlei Alves + walves@usa.net + + Modified by Salvador E. Tropea to compile without warnings. + For gcc 2.95.x and then 3.0.1. + + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 + +#define Uses_TDialog +#define Uses_TRect +#define Uses_TCheckBoxes +#define Uses_TButton +#define Uses_TView +#define Uses_TLabel +#define Uses_TSItem +#define Uses_TCluster +#define Uses_TRadioButtons +#define Uses_TScrollBar +#define Uses_MsgBox +#define Uses_TStringCollection +#define Uses_TMemo + +#include + +#include "consted.h" +#include "propedit.h" + +// String makers + +static char strbuf[1024]; + +#define _appendstr_(a) do { if (strlen(strbuf)) strcat(strbuf, " | ");\ + strcat(strbuf, a); } while(0) +/* +void _appendstr_(const char * s) +{ + strcat(strbuf, " | ", strcat(strbuf, s)); +} +*/ +char * OptionsStr(ushort aOptions) +{ + if (aOptions == 0) { strcpy(strbuf, ""); return strbuf; } + strcpy(strbuf, ""); + if (aOptions & ofSelectable) _appendstr_("ofSelectable"); + if (aOptions & ofTopSelect) _appendstr_("ofTopSelect"); + if (aOptions & ofFirstClick) _appendstr_("ofFirstClick"); + if (aOptions & ofFramed) _appendstr_("ofFramed"); + if (aOptions & ofPreProcess) _appendstr_("ofPreProcess"); + if (aOptions & ofPostProcess) _appendstr_("ofPostProcess"); + if (aOptions & ofBuffered) _appendstr_("ofBuffered"); + if (aOptions & ofTileable) _appendstr_("ofTileable"); + if ((aOptions & ofCentered) == ofCentered) + _appendstr_("ofCentered"); + else + { + if (aOptions & ofCenterX) _appendstr_("ofCenterX"); + if (aOptions & ofCenterY) _appendstr_("ofCenterY"); + } + return strbuf; +} + +char * EventMaskStr(ushort aEventMask) +{ + if (aEventMask == 0) { strcpy(strbuf, "evNothing"); return strbuf; } + strcpy(strbuf, ""); + if ((aEventMask & evMouse) == evMouse) _appendstr_("evMouse"); + else + { + if (aEventMask & evMouseDown) _appendstr_("evMouseDown"); + if (aEventMask & evMouseUp) _appendstr_("evMouseUp"); + if (aEventMask & evMouseMove) _appendstr_("evMouseMove"); + if (aEventMask & evMouseAuto) _appendstr_("evMouseAuto"); + } + if (aEventMask & evKeyboard) _appendstr_("evKeyboard"); + if (aEventMask & evCommand) _appendstr_("evCommand"); + if (aEventMask & evBroadcast) _appendstr_("evBroadcast"); + return strbuf; +} + +char * StateStr(ushort aState) +{ + if (aState == 0) { strcpy(strbuf, ""); return strbuf; } + strcpy(strbuf, ""); + if (aState & sfVisible) _appendstr_("sfVisible"); + if (aState & sfShadow) _appendstr_("sfShadow"); + if (aState & sfDisabled) _appendstr_("sfDisabled"); + if (aState & sfModal) _appendstr_("sfModal"); + if (aState & sfDefault) _appendstr_("sfDefault"); + return strbuf; +} + +char * GrowModeStr(ushort aGrowMode) +{ + if (aGrowMode == 0) { strcpy(strbuf, ""); return strbuf; } + strcpy(strbuf, ""); + if ((aGrowMode & gfGrowAll) == gfGrowAll) _appendstr_("gfGrowAll"); + else + { + if (aGrowMode & gfGrowLoX) _appendstr_("gfGrowLoX"); + if (aGrowMode & gfGrowLoY) _appendstr_("gfGrowLoY"); + if (aGrowMode & gfGrowHiX) _appendstr_("gfGrowHiX"); + if (aGrowMode & gfGrowHiY) _appendstr_("gfGrowHiY"); + } + if (aGrowMode & gfGrowRel) _appendstr_("gfGrowRel"); + return strbuf; +} + +char * DragModeStr(ushort aDragMode) +{ + if (aDragMode == 0) { strcpy(strbuf, ""); return strbuf; } + strcpy(strbuf, ""); + if (aDragMode & dmDragMove) _appendstr_("dmDragMove"); + if (aDragMode & dmDragGrow) _appendstr_("dmDragGrow"); + if ((aDragMode & dmLimitAll) == dmLimitAll) + _appendstr_("dmLimitAll"); + else + { + if (aDragMode & dmLimitLoX) _appendstr_("dmLimitLoX"); + if (aDragMode & dmLimitLoY) _appendstr_("dmLimitLoY"); + if (aDragMode & dmLimitHiX) _appendstr_("dmLimitHiX"); + if (aDragMode & dmLimitHiY) _appendstr_("dmLimitHiY"); + } + return strbuf; +} + +char * HelpCtxStr(ushort aHelpCtx) +{ + return HelpCtxsList()->getId(aHelpCtx); +} + +char * CommandStr(ushort aCommand) +{ + return CommandsList()->getId(aCommand); +} + +char * ButtonFlagStr(ushort aButtonFlag) +{ + strcpy(strbuf, "bfNormal"); + if (aButtonFlag == 0) return strbuf; else strcpy(strbuf, ""); + if (aButtonFlag & bfDefault) _appendstr_("bfDefault"); + if (aButtonFlag & bfLeftJust) _appendstr_("bfLeftJust"); + if (aButtonFlag & bfBroadcast) _appendstr_("bfBroadcast"); + return strbuf; +} + +char * WindowFlagStr(ushort aWindowFlag) +{ + if (aWindowFlag == 0) { strcpy(strbuf, ""); return strbuf; } + strcpy(strbuf, ""); + if (aWindowFlag & wfMove) _appendstr_("wfMove"); + if (aWindowFlag & wfGrow) _appendstr_("wfGrow"); + if (aWindowFlag & wfClose) _appendstr_("wfClose"); + if (aWindowFlag & wfZoom) _appendstr_("wfZoom"); + return strbuf; +} + +char * ValidatorStr(ushort aValidator) +{ + strcpy(strbuf, ""); + switch(aValidator) + { + case 0: strcpy(strbuf, ""); break; + case 1: strcpy(strbuf, "vtUserDefined"); break; + case 2: strcpy(strbuf, "vtRangeValidator"); break; + case 3: strcpy(strbuf, "vtFilterValidator"); break; + case 4: strcpy(strbuf, "vtPictureValidator"); break; + default: strcpy(strbuf, ""); + } + return strbuf; +} + +char * ItemsStr(void * aItemPtr) +{ + if (aItemPtr) sprintf(strbuf, "%s (%p)", "(void *)", aItemPtr); + else sprintf(strbuf, "%s", ""); + return strbuf; +} + +char * CharPtrStr(void * aItemPtr) +{ + if (aItemPtr) sprintf(strbuf, "%s (%p)", "(char *)", aItemPtr); + else sprintf(strbuf, "%s", ""); + return strbuf; +} + +#undef _appendstr_ + +// Properties editors + +TDialog * SelDialog(const char * Title, TView * c) +{ + int h = c->size.y; + + TDialog * d = new TDialog( TRect(1, 1, 26, 6 + h), Title ); + + d->options |= ofCentered; + d->flags &= ~wfClose; + c->options |= ofFramed; + d->insert(c); + d->insert( new TButton( TRect(1, d->size.y - 3, 12, d->size.y - 1), + __("~O~k"), cmOK, bfDefault ) ); + d->insert( new TButton( TRect(12, d->size.y - 3, 23, d->size.y - 1), + __("~C~ancel"), cmCancel, 0 ) ); + d->selectNext(False); + return d; +} + +TDialog * OptionsEditor() +{ + return SelDialog(_("Options"), + new TCheckBoxes( TRect( 1, 1, 24, 12), new TSItem("ofSelectable", + new TSItem("ofTopSelect", + new TSItem("ofFirstClick", + new TSItem("ofFramed", + new TSItem("ofPreProcess", + new TSItem("ofPostProcess", + new TSItem("ofBuffered", + new TSItem("ofTileable", + new TSItem("ofCenterX", + new TSItem("ofCenterY", + new TSItem("ofBeVerbose", 0 + )))))))))))) ); +} + +TDialog * EventMaskEditor() +{ + return SelDialog(_("Event masks"), + new TCheckBoxes( TRect( 1, 1, 24, 8), new TSItem("evMouseDown", + new TSItem("evMouseUp", + new TSItem("evMouseMove", + new TSItem("evMouseAuto", + new TSItem("evKeyDown", + new TSItem("evCommand", + new TSItem("evBroadcast", 0 + )))))))) ); +} + +TDialog * StateEditor() +{ + TCheckBoxes * t = + new TCheckBoxes( TRect( 1, 1, 24, 13), new TSItem("sfVisible", //0 + new TSItem("sfCursorVis", //1 + new TSItem("sfCursorIns", //2 + new TSItem("sfShadow", //3 + new TSItem("sfActive", //4 + new TSItem("sfSelected", //5 + new TSItem("sfFocused", //6 + new TSItem("sfDragging", //7 + new TSItem("sfDisabled", //8 + new TSItem("sfModal", //9 + new TSItem("sfDefault", //10 + new TSItem("sfExposed", 0 //11 + ))))))))))))); +#if 0 + t->setButtonState(5, false); + t->setButtonState(6, false); + t->setButtonState(7, false); +//t->setButtonState(9, false); + t->setButtonState(11, false); +#endif + return SelDialog(_("TView States"), t); +} + +TDialog * GrowModeEditor() +{ + return SelDialog(_("Grow modes"), + new TCheckBoxes( TRect( 1, 1, 24, 6), new TSItem("gfGrowLoX", + new TSItem("gfGrowLoY", + new TSItem("gfGrowHiX", + new TSItem("gfGrowHiY", + new TSItem("gfGrowRel", 0 + )))))) ); + +} + +TDialog * DragModeEditor() +{ + return SelDialog(_("Drag modes"), + new TCheckBoxes( TRect( 1, 1, 24, 7), new TSItem("dmDragMove", + new TSItem("dmDragGrow", + new TSItem("dmLimitLoX", + new TSItem("dmLimitLoY", + new TSItem("dmLimitHiX", + new TSItem("dmLimitHiY", 0 + ))))))) ); +} + +TDialog * DlgRefList(const char * aTitle) +{ + TRect r; + TScrollBar * sb = new TScrollBar( TRect(30, 1, 31, 10) ); + TIntConstListBox * l = new TIntConstListBox( TRect( 1, 1, 31, 10), 1, sb ); + TDialog * d = SelDialog(aTitle, l); + r = d->getBounds(); + r.b.x += 7; + d->changeBounds(r); + d->insert(sb); + return d; +} + +TDialog * HelpCtxEditor() +{ + return DlgRefList(_("Help contexts")); +} + +TDialog * CommandEditor() +{ + return DlgRefList(_("Commands")); +} + +TDialog * DlgObjList(const char * aTitle) +{ + TRect r; + TScrollBar * sb = new TScrollBar( TRect(30, 1, 31, 10) ); + TListBox * l = new TListBox( TRect( 1, 1, 31, 10), 1, sb ); + TDialog * d = SelDialog(aTitle, l); + r = d->getBounds(); + r.b.x += 7; + d->changeBounds(r); + d->insert(sb); + return d; +} + +TDialog * LinkEditor() +{ + return DlgObjList(_("Avail. views")); +} + +TDialog * ScrollEditor() +{ + return DlgObjList(_("Avail. scrolls")); +} + +TDialog * ButtonFlagEditor() +{ + return SelDialog(_("TButton flags"), + new TCheckBoxes( TRect( 1, 1, 24, 4), new TSItem("bfDefault", + new TSItem("bfLeftJust", + new TSItem("bfBroadcast", 0 + )))) ); +} + +TDialog * WindowFlagEditor() +{ + return SelDialog(_("TWindow flags"), + new TCheckBoxes( TRect( 1, 1, 24, 5), new TSItem("wfMove", + new TSItem("wfGrow", + new TSItem("wfClose", + new TSItem("wfZoom", 0 + ))))) ); +} + +TDialog * ValidatorEditor() +{ + return SelDialog(_("TValidators"), + new TRadioButtons( TRect( 1, 1, 24, 6), new TSItem("", + new TSItem("vtUserDefined", + new TSItem("vtRangeValidator", + new TSItem("vtFilterValidator", + new TSItem("vtPictureValidator", 0 + )))))) ); +} + +class ipstream; +class opstream; + +// TItemsEditor + +class TSafeListBox: public TListBox +{ +public: + TSafeListBox(const TRect& bounds, ushort aNumCols, TScrollBar * sb): + TListBox(bounds, aNumCols, sb) { }; + void getText(char *dest, ccIndex item, short maxLen) + { + if (strlen((char *)items->at(item)) > (size_t)maxLen) + { + strncpy(dest, (char *)items->at(item), maxLen); + dest[maxLen] = 0; + } else strcpy(dest, (char *)items->at(item)); + } +}; + +class TItemsEditor: public TDialog +{ + TStringCollection * cList; + TSafeListBox * List; +public: + TItemsEditor(); + virtual void setData(void *); + virtual void getData(void *) { }; + virtual void handleEvent(TEvent& event); +}; + +const ushort + cmEdit = 200, + cmAdd = 201, + cmDel = 202, + cmCClear = 203; + +TItemsEditor::TItemsEditor(): + TWindowInit(&TItemsEditor::initFrame), + TDialog( TRect(0, 0, 45, 16) , __("Items") ) +{ + TScrollBar * sb; + + options |= ofCentered; + + sb = new TScrollBar(TRect(30, 2, 31, 14)); + List = new TSafeListBox(TRect(2, 2, 30, 14), 1, sb); + insert(sb); + insert(new TLabel( TRect(1, 1, 15, 2), _("~I~tems list:"), List ) ); + insert(List); + insert( new TButton(TRect(31, 2, 43, 4), __("~O~k"), cmOK, 0 ) ); + insert( new TButton(TRect(31, 4, 43, 6), __("~C~ancel"), cmCancel, 0 ) ); + insert( new TButton(TRect(31, 6, 43, 8), __("~E~dit"), cmEdit, bfBroadcast ) ); + insert( new TButton(TRect(31, 8, 43, 10), __("~A~dd"), cmAdd, bfBroadcast ) ); + insert( new TButton(TRect(31, 10, 43, 12), __("C~l~ear"), cmCClear, bfBroadcast ) ); + insert( new TButton(TRect(31, 12, 43, 14), __("~D~elete"), cmDel, bfBroadcast ) ); + cList = 0; + selectNext(False); +} + +void TItemsEditor::setData(void * data) +{ + TListBoxRec rec; + + cList = (TStringCollection *)data; + rec.items = cList; + rec.selection = 0; + List->setData(&rec); +} + + +void TItemsEditor::handleEvent(TEvent& event) +{ + char buf[50]; + char * c; + TDialog::handleEvent(event); + + if (!cList) return; + + if (event.what == evBroadcast) + switch(event.message.command) + { + case cmListItemSelected: + if ( (cList->getCount() > 0) && (List->focused >= 0) ) + { + c = (char *)(cList->at(List->focused)); + strcpy(buf, c); + List->drawView(); + if (inputBox(_("Item Edit"), _("Item:"), buf, 50) == cmOK) + { + delete[] c; + cList->atPut(List->focused, newStr(buf)); + List->drawView(); + } + } + clearEvent(event); + break; + case cmEdit: + if (cList->getCount() == 0) + { + event.message.command = cmAdd; + putEvent(event); + clearEvent(event); + } + else + { + event.message.command = cmListItemSelected; + putEvent(event); + clearEvent(event); + } + break; + case cmAdd: + buf[0] = 0; + if (inputBox(_("Item Add"), _("Item:"), buf, 50) == cmOK) + { + cList->setLimit(cList->getCount() + 1); + cList->atInsert(cList->getCount(), newStr(buf)); + List->setRange(List->range + 1); + List->focusItem( cList->getCount() - 1 ); + List->drawView(); + } + clearEvent(event); + break; + case cmDel: + if ( messageBox(__("Are you sure ?"), mfYesNoCancel) == cmYes ) + { + cList->atFree(List->focused); + cList->pack(); + clearEvent(event); + List->setRange(List->range - 1); + List->drawView(); + } + break; + case cmCClear: + if ( messageBox(__("Are you sure ?"), mfYesNoCancel) == cmYes ) + { + cList->freeAll(); + List->setRange(0); + List->drawView(); + } + clearEvent(event); + break; + } +} + +TDialog * ItemsEditor() +{ + return new TItemsEditor(); +} + +TDialog * CharPtrEditor() +{ + TDialog * d = new TDialog( TRect(0, 0, 40, 20), __("Text editor") ); + TScrollBar * VS = new TScrollBar( TRect(38, 1, 39, 15) ); + TScrollBar * HS = new TScrollBar( TRect(1, 15, 38, 16) ); + d->insert( new TMemo( TRect(1, 1, 39, 15), VS, HS, 0, 1024 ) ); + d->insert(VS); + d->insert(HS); + d->insert( new TButton ( TRect(17, 17, 27, 19), __("~O~k"), cmOK, bfDefault ) ); + d->insert( new TButton ( TRect(28, 17, 38, 19), __("~C~ancel"), cmCancel, 0 ) ); + d->selectNext(False); + d->options |= ofCentered; + return d; +} + diff --git a/tvision/examples/dlgdsn/propdlgs.h b/tvision/examples/dlgdsn/propdlgs.h new file mode 100644 index 0000000..2f2bd2b --- /dev/null +++ b/tvision/examples/dlgdsn/propdlgs.h @@ -0,0 +1,56 @@ +/*************************************************************************** + + propdlgs.h - Functions prototypes for property editors + --------------------------------------------------------------------- + May, 2000 + Copyright (C) 2000 by Warlei Alves + walves@usa.net + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#if !defined(_PROPDLGS_HPP_) +#define _PROPDLGS_HPP_ + +class TDialog; + +// String maker functions - convert properties to its string representation +char * OptionsStr(ushort aOptions); +char * EventMaskStr(ushort aEventMask); +char * StateStr(ushort aState); +char * GrowModeStr(ushort aGrowMode); +char * DragModeStr(ushort aDragMode); +char * HelpCtxStr(ushort aHelpCtx); +char * CommandStr(ushort aCommand); +char * ButtonFlagStr(ushort aButtonFlag); +char * WindowFlagStr(ushort aWindowFlag); +char * ValidatorStr(ushort aWindowFlag); +char * ItemsStr(void * aItemPtr); +char * CharPtrStr(void * aItemPtr); + +// Properties editors +TDialog * OptionsEditor(); +TDialog * EventMaskEditor(); +TDialog * StateEditor(); +TDialog * GrowModeEditor(); +TDialog * DragModeEditor(); +TDialog * HelpCtxEditor(); +TDialog * CommandEditor(); +TDialog * ButtonFlagEditor(); +TDialog * WindowFlagEditor(); +TDialog * ValidatorEditor(); +TDialog * ItemsEditor(); +TDialog * CharPtrEditor(); +TDialog * LinkEditor(); +TDialog * ScrollEditor(); + +#endif // _PROPDLGS_HPP_ + diff --git a/tvision/examples/dlgdsn/propedit.cc b/tvision/examples/dlgdsn/propedit.cc new file mode 100644 index 0000000..a95e4c5 --- /dev/null +++ b/tvision/examples/dlgdsn/propedit.cc @@ -0,0 +1,1220 @@ +/*************************************************************************** + + propedit.cc - object properties editor + --------------------------------------------------------------------- + May, 2000 + Copyright (C) 2000 by Warlei Alves + walves@usa.net + + Heavily modified by Salvador E. Tropea to compile without warnings. + Some warnings were in fact bugs. + For gcc 2.95.x and then 3.0.1. + + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 + +#define Uses_TEvent +#define Uses_TProgram +#define Uses_TDeskTop +#define Uses_TView +#define Uses_TScrollBar +#define Uses_TKeys +#define Uses_TDrawBuffer +#define Uses_TDialog +#define Uses_TEventQueue +#define Uses_MsgBox +#define Uses_TListBox +#define Uses_TStringCollection +#define Uses_TCollection +#define Uses_TInputLine +#define Uses_TPalette +#define Uses_TValidator +#define Uses_TFilterValidator + +#include + +#include "dsgdata.h" +#include "propedit.h" +#include "dsgobjs.h" +#include "propdlgs.h" +#include "consted.h" +#include "fdconsts.h" + +enum TDataEditorType + { + etNone, + etStringEditor, // Short string value up to 60 bytes + etIntegerEditor, // Integer value + etOptionsEditor, // View options value + etEventMaskEditor, // View eventMask value + etStateEditor, // View initial state value ( some of them ) + etGrowModeEditor, // View growMode value + etDragModeEditor, // View dragMode value + etHelpCtxEditor, // hc## value + etCommandEditor, // cm## value + etButtonFlagEditor, // Button flag value + etWindowFlagEditor, // Window flag value + etValidatorEditor, // TValidator type value + etCharPtrEditor, // Null terminated string value + etValidatorDataEditor, // TValidator data value (Filter | range) + etStrCollectionEditor, // Generic string lists + etLinkEditor, // Links for TDLabel + etScrollBarEditor, // ScrollBars + }; + +// Objects that can be a link for a TDLabel +static TStringCollection * LinkList = 0; +// Available V and H scrollbars +static TStringCollection * ScrollList = 0; + +// Global object manager list +static TLinkList * ObjLink = 0; + +// Current object editor +static TObjEdit * ObjEdit; + +// To resolve (sprintf "%s") when there is nothing to do +static char * blank = ""; + +//extern int TabOrder; + +/* functions ==============================================================*/ + +// Standard execDialog without free the dialog +int execDialog_NoFree(TDialog * dialog, void *data) +{ + int rst; + + TView * d = TProgram::application->validView(dialog); + if (d) + { + if (data) d->setData(data); + rst = TProgram::deskTop->execView(d); + if ((rst!=cmCancel) && (data)) d->getData(data); + return rst; + } + else return cmCancel; +} + +// Standard execDialog +int execDialog(TDialog * dialog, void *data) +{ + int rst; + + TView * d = TProgram::application->validView(dialog); + if (d) + { + if (data) d->setData(data); + rst = TProgram::deskTop->execView(d); + if ((rst!=cmCancel) && (data)) d->getData(data); + TObject::CLY_destroy( d ); + return rst; + } + else return cmCancel; +} + +/* TLinkList ============================================================*/ + +// Sorter func by tabulation order +static int byTabOrder(const void * key1, const void * key2) +{ + TDsgObj * d1 = (TDsgObj *)((TDsgLink *)key1)->d; + TDsgObj * d2 = (TDsgObj *)((TDsgLink *)key2)->d; + + bool d1CanTab = d1->tabStop(); + bool d2CanTab = d2->tabStop(); + + if (!d1CanTab && d2CanTab) return -1; + if (!d1CanTab && !d2CanTab) return 0; + if (d1CanTab && !d2CanTab) return 1; + + short t1 = ((TDsgObjData *)d1->attributes)->tabOrder; + short t2 = ((TDsgObjData *)d2->attributes)->tabOrder; + + if (d1CanTab && d2CanTab) + { + if ((t1 > t2) - (t1 < t2) == 0) + { + if (d1 == ObjEdit->object) return 1; + if (d2 == ObjEdit->object) return -1; + } else return (t1 > t2) - (t1 < t2); + } + return 0; +} +/* +static int byCreationOrder(void * key1, void * key2) +{ + c1 = ((TDsgObj *)((TDataLink *&)*key1)->d)->creationOrder; + c2 = ((TDsgObj *)((TDataLink *&)*key2)->d)->creationOrder; + return (c1 > c2) - (c1 < c2); +} +*/ +// Test functions +static Boolean matchView(void * link, void * view) +{ + return (((TDsgLink *)link)->v == view); +} + +static Boolean matchDsgObj(void * link, void * dsgObj) +{ + return (((TDsgLink *)link)->d == dsgObj); +} + +static Boolean matchScroll(void * link, void * aName) +{ + TDsgObj * d = ((TDsgLink *)link)->d; + return ( + (d->viewType == vtVScroll || d->viewType == vtHScroll) && + strcmp( ((TDsgObjData*)d->attributes)->thisName, (char *)aName ) == 0 ); +} + +static Boolean matchLabel(void * link, void * aLink) +{ + TDsgObj * d = ((TDsgLink *)link)->d; + return ( d->viewType == vtLabel && + strcmp( ((TDLabelData *)d->attributes)->link, (char *)aLink ) == 0 ); +} + +// Find functions +TDsgLink * TLinkList::viewFind(void * aView) // by View +{ + return (TDsgLink *)firstThat(&matchView, aView); +} + +TDsgLink * TLinkList::dsgObjFind(void * aDsgObj) // by DsgObj +{ + return (TDsgLink *)firstThat(&matchDsgObj, aDsgObj); +} + +TDsgLink * TLinkList::linkFind(char * aName) // Look for a label +{ + return (TDsgLink *)firstThat(&matchLabel, aName); +} + +TDsgLink * TLinkList::scrollFind(char * aScroll) // Look for a ScrollBar +{ + return (TDsgLink *)firstThat(&matchScroll, aScroll); +} + +// Remove the object from and notificates all others in the list +void TLinkList::removeMe(TDsgObj * aDsgObj) +{ + int index; + + void * link = firstThat(&matchDsgObj, aDsgObj); + if (link) + { + TDsgObjData * data = (TDsgObjData *)aDsgObj->attributes; +// atFree(indexOf(link)); + this->free(link); + switch(aDsgObj->viewType) + { + case vtVScroll: + case vtHScroll: + if (ScrollList->search(&data->thisName, index)) + { + removeNotify(ScrollList, index); + ScrollList->atRemove(index); + } + break; + case vtStatic: break; + case vtLabel: break; + default: + if (LinkList->search(&data->thisName, index)) + { + removeNotify(LinkList, index); + LinkList->atRemove(index); + } + } + } +} + +// Inserts a pair of pointers from the (TView, TDsgObj) descendant to the list. +// This is necessary because one TView descendant that also inherits the +// TDsgObj code cannot be directly refered as a TDsgObj outside its context. +void TLinkList::add(TView * aView, TDsgObj * aDsgObj) +{ + if (!aView || !aDsgObj) return; + + if (viewFind(aView) != 0) return; + + TDsgLink * link = new TDsgLink; + link->v = aView; + link->d = aDsgObj; + insert(link); + + TDsgObjData * data = (TDsgObjData *)aDsgObj->attributes; + switch(aDsgObj->viewType) + { + case vtVScroll: + case vtHScroll: ScrollList->insert(&data->thisName); break; + case vtStatic: break; + case vtButton: break; + case vtLabel: + strcpy( ((TDLabelData *)aDsgObj->attributes)->link, blank ); + break; + case vtMemo: + strcpy( ((TDMemoData *)aDsgObj->attributes)->hScroll, blank ); + strcpy( ((TDMemoData *)aDsgObj->attributes)->vScroll, blank ); + LinkList->insert(&data->thisName); + break; + case vtListBox: + strcpy( ((TDListBoxData *)aDsgObj->attributes)->scrollBar, blank ); + LinkList->insert(&data->thisName); + break; + default: LinkList->insert(&data->thisName); + } +} + +void TLinkList::freeItem(void * item) +{ + delete (char *)item; +} + +// To reorganize the views in a correct tabulation order +void TLinkList::doReOrder() +{ + short Tab = 0; + int i; + TDsgLink * dsg; + TDsgObjData * dsgData; + + if (count == 0) return; + + sort(byTabOrder); + + for (i = 0; i < count; i++) + { + dsg = (TDsgLink *)at(i); + dsgData = (TDsgObjData *)dsg->d->attributes; + if (dsg->d->tabStop()) + { + dsgData->tabOrder = Tab; + Tab++; + } + } + for (i = count - 1; i > 0; i--) + { + dsg = (TDsgLink *)at(i); + dsg->v->makeFirst(); + } +} + +// Sorting with qsort +void TLinkList::sort(ccSortFunc Compare) +{ + qsort(items, count, sizeof(void *), Compare); +} + +// Try to reorganize the objects in an ideal creation order +void TLinkList::sortForBuild() +{ +#if 0 +#define _item_move_(a) do { remove(tmp); atInsert(a, tmp); i++; } while(0) + int i = 0; + char * s1, * s2; + TViewData * attr = 0; + + if (count <= 1) return; + + doReOrder(); + void * tmp; + do { + attr = (TViewData *)((TDsgLink *)items[i])->d->attributes; + if (tmp = linkFind(attr->thisName)) _item_move_( ((i + 1) < count) ? i + 1 : i ); + i++; + } while (i < count); + i = 0; + do { + s1 = blank; + s2 = blank; + attr = (TViewData *)((TDsgLink *)items[i])->d->attributes; + if ((((TDsgLink *)items[i])->d)->viewType == vtListBox) + s1 = ((TDListBoxData *)attr)->scrollBar; + else if ((((TDsgLink *)items[i])->d)->viewType == vtMemo) + { + s1 = ((TDMemoData *)attr)->vScroll; + s2 = ((TDMemoData *)attr)->hScroll; + } + if (tmp = scrollFind(s2)) + { _item_move_( ((i - 1) >= 0) ? i - 1: 0 ); if (s1 != blank) i--; } + if (tmp = scrollFind(s1)) + { _item_move_( ((i - 1) >= 0) ? i - 1: 0 ); } + i++; + } while (i < count); +#undef _item_move_ +#endif +} + +// Called by removeMe to notify dependencies +void TLinkList::removeNotify(TCollection * aCollection, int Index) +{ + int i; + TDsgObj * d; + for (i = 0; i < count; i++) + { + d = (TDsgObj *)((TDsgLink *)at(i))->d; + if (aCollection == LinkList && d->viewType == vtLabel) + { + if ( strcmp( ((TDLabelData *)d->attributes)->link, + (char *)aCollection->at(Index) ) == 0 ) + strcpy ( ((TDLabelData *)d->attributes)->link, blank ); + } + else if (aCollection == ScrollList && d->viewType == vtListBox) + { + if ( strcmp( ((TDListBoxData *)d->attributes)->scrollBar, + (char *)aCollection->at(Index) ) == 0 ) + strcpy ( ((TDListBoxData *)d->attributes)->scrollBar, blank ); + } + else if (aCollection == ScrollList && d->viewType == vtMemo) + { + if ( strcmp( ((TDMemoData *)d->attributes)->hScroll, + (char *)aCollection->at(Index) ) == 0 ) + strcpy ( ((TDMemoData *)d->attributes)->hScroll, blank ); + if ( strcmp( ((TDMemoData *)d->attributes)->hScroll, + (char *)aCollection->at(Index) ) == 0 ) + strcpy ( ((TDMemoData *)d->attributes)->vScroll, blank ); + } + } +} + +// Called when an object has its "name" changed in the editor +void TLinkList::linkChangedName(char * oldName, char * newName) +{ + int i; + + pack(); + + for (i = 0; i < count; i++) + { + TDsgLink * d = (TDsgLink *)items[i]; + TDsgObj * obj = d->d; + if (obj->viewType == vtListBox) + { + if (strcmp( (char *)((TDListBoxData *)obj->attributes)->scrollBar, + oldName ) == 0) strcpy( + (char *)((TDListBoxData *)obj->attributes)->scrollBar, newName); + } + else if (obj->viewType == vtMemo) + { + if (strcmp( (char *)((TDMemoData *)obj->attributes)->hScroll, + oldName ) == 0) strcpy( + (char *)((TDMemoData *)obj->attributes)->hScroll, newName); + if (strcmp( (char *)((TDMemoData *)obj->attributes)->vScroll, + oldName ) == 0) strcpy( + (char *)((TDMemoData *)obj->attributes)->vScroll, newName); + } + else if (obj->viewType == vtLabel) + { + if (strcmp( (char *)((TDLabelData *)obj->attributes)->link, + oldName ) == 0) strcpy( + (char *)((TDLabelData *)obj->attributes)->link, newName); + } + } +} + +/* ObjectLinker -----------------------------------------------------------*/ + +TLinkList * ObjectLinker() { return ObjLink; } + +/* TInplaceEdit ===========================================================*/ +// A quick editor for int values and short string values +// Nor Nor Sel Arrows +#define cpInplaceEdit "\x06\x06\x07\x05" + + +TInPlaceEdit::TInPlaceEdit(const TRect& bounds, ushort aMaxLen, + TValidator * aValidator): + TInputLine(bounds, aMaxLen) + { setValidator(aValidator); } + +void TInPlaceEdit::handleEvent(TEvent& event) +{ + if (event.what == evKeyDown) + { + switch(event.keyDown.keyCode) + { + case kbEnter: + endState = cmOK; + clearEvent(event); + break; + case kbEsc: + endState = cmCancel; + clearEvent(event); + break; + case '-': if ((validator) && curPos != 0) clearEvent(event); + } + } + if ((event.what == evMouseDown) && + (!containsMouse(event)) ) endState = cmCancel; + TInputLine::handleEvent(event); +} + +TPalette& TInPlaceEdit::getPalette() const +{ + static TPalette palette( cpInplaceEdit, sizeof(cpInplaceEdit) - 1 ); + return palette; +} + +ushort TInPlaceEdit::execute() +{ + TEvent e; + + endState = 0; + + do + { + getEvent(e); + handleEvent(e); + } while (endState == 0); + + return endState; +} + +/* Inplace editors --------------------------------------------------------*/ + +bool IntegerEditor(int& value, TPoint place, TGroup * host) +{ + bool rst = false; + char strval[20]; + + TRect r(place.x, place.y, place.x + + (host->size.x - place.x - 1), place.y + 1); + + sprintf(strval, "%i", value); + + TFilterValidator * val = new TFilterValidator("-0123456789"); + + TInPlaceEdit * editor = new TInPlaceEdit(r, 6, val); + + editor->setData(&strval); + rst = ( host->execView(editor) == cmOK ); + if (rst) + { + editor->getData(&strval); + value = atoi(strval); + } + TObject::CLY_destroy( editor ); + return rst; +} + +bool StringEditor(char * string, TPoint place, TGroup * host, ushort aMaxLen) +{ + bool rst = false; + + TRect r(place.x, place.y, place.x + + (host->size.x - place.x - 1), place.y + 1); + + TInPlaceEdit * editor = new TInPlaceEdit(r, aMaxLen, 0); + + editor->setData(string); + rst = ( host->execView(editor) == cmOK ); + if (rst) editor->getData(string); + TObject::CLY_destroy( editor ); + return rst; +} + +/* TStructMap =============================================================*/ +// Configurable data mapper used to edit values in the TDsgObj::attributes +// field +class TStructMap +{ +public: + TStructMap(const char * Label, +// int OffSet, + int DataSize, + TDataEditorType aEditorType, + bool ReadOnly = false, + TStructMap *Next = 0); + ~TStructMap(); + + TStructMap * prev; + TStructMap * next; + int index; + int offset; + int dataSize; + int editorType; + char * label; + bool readOnly; +}; + +TStructMap::TStructMap(const char * Label, + int DataSize, + TDataEditorType aEditorType, + bool ReadOnly , + TStructMap *Next ) +{ + label = newStr(Label); + offset = 0; + dataSize = DataSize; + editorType = aEditorType; + index = 0; + readOnly = ReadOnly; + prev = NULL; + next = Next; + if (next != 0) + { + next->prev = this; + next->offset = offset + dataSize; + next->index = index + 1; + } +} + +TStructMap::~TStructMap() +{ + delete[] label; + if (next) delete(next); +} + +TStructMap& operator + ( TStructMap& map1, TStructMap& map2 ) +{ + TStructMap *map = &map1; + while (map->next) map = map->next; + map->next = &map2; + map2.offset = map->offset + map->dataSize; + map2.prev = map; + if (map2.dataSize > 0) + { + while ((map->dataSize == 0) && (map->prev)) map = map->prev; + map2.index = map->index + 1; + } + return map2; +} + +/* Data mappers -----------------------------------------------------------*/ + +// Commom TView data map initialization code fragment +#define _separator_(a) *new TStructMap(a, 0, etNone, true, 0) + +#define _viewmap_() \ + _separator_("TView data")+ \ + *new TStructMap("Left", sizeof(int), etIntegerEditor)+\ + *new TStructMap("Top", sizeof(int), etIntegerEditor)+\ + *new TStructMap("Width", sizeof(int), etIntegerEditor)+\ + *new TStructMap("Height", sizeof(int), etIntegerEditor)+\ + *new TStructMap("ClassName", MAX_LABEL_LENGTH, etStringEditor, true)+\ + *new TStructMap("Name", MAX_LABEL_LENGTH, etStringEditor)+\ + *new TStructMap("Options", sizeof(ushort), etOptionsEditor)+\ + *new TStructMap("EventMask", sizeof(ushort), etEventMaskEditor)+\ + *new TStructMap("State", sizeof(ushort), etStateEditor)+\ + *new TStructMap("GrowMode", sizeof(ushort), etGrowModeEditor)+\ + *new TStructMap("DragMode", sizeof(ushort), etDragModeEditor)+\ + *new TStructMap("HelpContext", sizeof(ushort), etHelpCtxEditor) + +/* TPoint origin;\ + TPoint size;\ + TNameStr className;\ + TNameStr thisName;\ + ushort options;\ + ushort eventMask;\ + ushort state;\ + ushort growMode;\ + ushort dragMode;\ + ushort helpCtx\ */ + +static const TStructMap * TViewMap = &(_viewmap_()); + +static const TStructMap * TDialogMap = &( + _viewmap_()+ + _separator_("TDialog data") + + *new TStructMap("Title", MAX_TITLE_LENGTH, etStringEditor) + + *new TStructMap("Flags", sizeof(ushort), etWindowFlagEditor, 0) ); + +static const TStructMap * TLabelMap = &( + _viewmap_()+ + _separator_("TLabel data")+ + *new TStructMap("Text", MAX_LABEL_LENGTH, etStringEditor)+ + *new TStructMap("Link", MAX_LABEL_LENGTH, etLinkEditor, 0) ); + +static const TStructMap * TInputMap = &( + _viewmap_()+ + _separator_("TInputLine data") + + *new TStructMap("TabOrder", sizeof(int), etIntegerEditor) + + *new TStructMap("MaxLen", sizeof(int), etIntegerEditor) + + *new TStructMap("Validator", sizeof(ushort), etValidatorEditor) + + *new TStructMap("ValidatorData", MAX_LABEL_LENGTH, etValidatorDataEditor, 0) ); + +static const TStructMap * TMemoMap = &( + _viewmap_()+ + _separator_("TMemo data") + + *new TStructMap("TabOrder", sizeof(int), etIntegerEditor) + + *new TStructMap("HScroll", MAX_LABEL_LENGTH, etScrollBarEditor, 0) + + *new TStructMap("VScroll", MAX_LABEL_LENGTH, etScrollBarEditor, 0) + + *new TStructMap("BufSize", sizeof(uint32), etIntegerEditor) ); +// *new TStructMap("Text", sizeof(char *), etCharPtrEditor, 0) ); + +static const TStructMap * TStaticMap = &( + _viewmap_()+ + _separator_("TStaticText data") + + *new TStructMap("Text", sizeof(char *), etCharPtrEditor, 0) ); + +static const TStructMap * TButtonMap = &( + _viewmap_()+ + _separator_("TButton data") + + *new TStructMap("TabOrder", sizeof(int), etIntegerEditor) + + *new TStructMap("Title", MAX_LABEL_LENGTH, etStringEditor) + + *new TStructMap("Command", sizeof(ushort), etCommandEditor) + + *new TStructMap("Flags", sizeof(ushort), etButtonFlagEditor) ); + +static const TStructMap * TListBoxMap = &( + _viewmap_()+ + _separator_("TListBox Data") + + *new TStructMap("TabOrder", sizeof(int), etIntegerEditor) + + *new TStructMap("Columns", sizeof(short), etIntegerEditor) + + *new TStructMap("ScrollBar", MAX_LABEL_LENGTH, etScrollBarEditor) ); + +static const TStructMap * TClusterMap = &( + _viewmap_()+ + _separator_("TCluster Data") + + *new TStructMap("TabOrder", sizeof(int), etIntegerEditor) + + *new TStructMap("Items", sizeof(void *), etStrCollectionEditor) ); + +#undef _viewmap_ + +/* TObjEditView ===========================================================*/ + +TObjEditView::TObjEditView(const TRect& bounds, TScrollBar * v): + TView(bounds) +{ + sb = v; + separator = size.x / 2; + eventMask = evMouse | evKeyboard | evCommand | evBroadcast; + currentMap=0; +} + +void TObjEditView::setMap(const TStructMap * aMap, void * Data) +{ + data = Data; + if (!data) + { + dataMap = 0; + currentMap = 0; + drawView(); + return; + } + while (aMap->next) aMap = aMap->next; + sb->setRange(1, aMap->index); + while (aMap->prev) aMap = aMap->prev; + dataMap = aMap; + if (aMap->dataSize == 0) + while ((aMap->next) && (aMap->dataSize == 0)) aMap = aMap->next; + currentMap = aMap; + drawView(); +} + +void calcPlace(TPoint& p, short column, short line, const TStructMap * map) +{ + p.x = column + 1; + p.y = line; + while (map->next) + { + if (map->dataSize == 0) p.y++; + map = map->next; + if (map->index >= line) break; + } +} + +int findStr(TCollection * col, const char * cmp) +{ + int i, c = col->getCount(); + if (c == 0) return -1; + for (i = 0; i < c; i++) + if (strcmp(cmp, (char *)col->at(i)) == 0) return i; + return 0; +} + +void TObjEditView::editItem(const TStructMap * map) +{ + ushort Val; + TListBoxRec rec; + void * v; + TMemoData m; + char * c; + int i; + TPoint place; + char oldName[30]; + +#define _editlink_(list, editor) \ + if (list->getCount() == 0) break; \ + rec.items = list; \ + rec.selection = findStr(list, (char*)ldata); \ + if (rec.selection < 0) break; \ + chg = (execDialog(editor(), &rec) == cmOK); \ + if (chg) strcpy((char *)ldata, (char *)list->at(rec.selection)); \ + break; + +#define _do_(editor) chg = (execDialog(editor(), ldata) == cmOK); break; +#define _constsel_(list, editor) \ + rec.items = list(); \ + rec.selection = list()->getIndex((ushort)(int)ldata); \ + chg = (execDialog(editor(), &rec) == cmOK); \ + if (chg) memcpy(ldata, &rec.selection, sizeof(ushort)); break; + + + if (map->readOnly) + { + messageBox("Ops! Read only value.", mfOKButton); + return; + } + + void * ldata = (void *)((char *)data + map->offset); + bool chg = false; + + switch(map->editorType) + { + case etStringEditor: + calcPlace(place, separator, map->index, dataMap); + if (map->index == 6) strcpy(oldName, (char *)ldata); + chg = StringEditor((char *)ldata, place, owner, map->dataSize); + if ( (chg) && (map->index == 6 || vtCurrent == vtVScroll || + vtCurrent == vtHScroll ) ) + { + if (strlen((char *)ldata) == 0) + { + strcpy((char *)ldata, oldName); + chg = false; + break; + } + else if (strcmp((char *)ldata, oldName) != 0) + ObjLink->linkChangedName(oldName, (char *)ldata); + } + if (chg) message(owner, evMessage, cmValueChanged, 0); + break; + case etIntegerEditor: + calcPlace(place, separator, map->index, dataMap); + if (vtCurrent == vtListBox && map->index == 14) + i = (short)(int)ldata; else i = (int)ldata; + chg = IntegerEditor(i, place, owner); + if (vtCurrent == vtListBox && map->index == 14) + ldata = (void *)i; else ldata = (void *)i; + if (chg) message(owner, evMessage, cmValueChanged, 0); + break; + case etOptionsEditor: _do_(OptionsEditor); + case etEventMaskEditor: + memcpy(&Val, ldata, sizeof(ushort)); + if (Val & evCommand) { Val &= ~evCommand; Val |= 0x20; } + if (Val & evBroadcast) { Val &= ~evBroadcast; Val |= 0x40; } + chg = (execDialog(EventMaskEditor(), ldata) == cmOK); + if (chg) + { + if (Val & 0x20) { Val &= ~0x20; Val |= evCommand; } + if (Val & 0x40) { Val &= ~0x40; Val |= evBroadcast; } + memcpy(ldata, &Val, sizeof(ushort)); + } + break; + case etStateEditor: _do_(StateEditor); + case etGrowModeEditor: _do_(GrowModeEditor); + case etDragModeEditor: _do_(DragModeEditor); + case etHelpCtxEditor: _constsel_(HelpCtxsList, HelpCtxEditor); + case etCommandEditor: _constsel_(CommandsList, CommandEditor); + case etButtonFlagEditor: _do_(ButtonFlagEditor); + case etWindowFlagEditor: _do_(WindowFlagEditor); + case etValidatorEditor: _do_(ValidatorEditor); + case etValidatorDataEditor: break; + case etStrCollectionEditor: + chg = (execDialog(ItemsEditor(), ldata) == cmOK); + if (chg) message(owner, evMessage, cmValueChanged, 0); + break; + case etCharPtrEditor: + c = (char *)ldata; + strcpy(m.buffer, c); + c = (char *)m.buffer; + v = c; + while (c[0]) // Turning '\x3' to "\x3" + { + if (c[0] == 3/*&& (c + 3 - v) < 1024*/) + { + memmove(c + 3, c + 1, strlen(c) + 1); + memcpy(c, "\\x3", 3); + } + c++; + } + c = (char *)v; + m.length = strlen(c); + chg = (execDialog(CharPtrEditor(), &m) == cmOK); + if (chg) + { + if (m.length == 0) strcpy(c, ""); + else // Turning simbolic chars to raw + { + delete[] c; + c = (char *)m.buffer; + while (c[0]) // eating CR chars + { + if (c[0] == '\x0d') memmove(c, c + 1, strlen(c - 1)); + c++; + } + c = (char *)m.buffer; + while (c[0]) // Turning "\x3" to '\x3' + { + i = 0; + if (c[0]==92) + { + while (c[i] != '3') { if (c[i] == 0) break; i++; } + if (i <= 4) + { + c[0] = 3; + memmove(&c[1], &c[i+1], strlen(c) - i); + } + } + c++; + } + ldata=(void *)newStr(m.buffer); + } + message(owner, evMessage, cmValueChanged, 0); + } + break; + case etLinkEditor: _editlink_(LinkList, LinkEditor); + case etScrollBarEditor: _editlink_(ScrollList, ScrollEditor); + } + if (chg) drawView(); +#undef _editlink_ +#undef _do_ +} + +const char * TObjEditView::getValueFor(const TStructMap * map) +{ + static char buf[60]; + static ushort ushrtval; + static int intval; + static void * ptrval; + static void * ldata; + + ldata = data; + ldata = (void *)((char *)ldata + map->offset); + + strcpy(buf, ""); + + if (map->editorType == etIntegerEditor) + { + memcpy(&intval, ldata, map->dataSize); + sprintf(buf, "%i", intval); + } + else if ((map->editorType >= etOptionsEditor) && + (map->editorType <= etValidatorEditor)) + { + memcpy(&ushrtval, ldata, map->dataSize); + switch(map->editorType) + { + case etOptionsEditor: return OptionsStr(ushrtval); + case etEventMaskEditor: return EventMaskStr(ushrtval); + case etStateEditor: return StateStr(ushrtval); + case etGrowModeEditor: return GrowModeStr(ushrtval); + case etDragModeEditor: return DragModeStr(ushrtval); + case etHelpCtxEditor: return HelpCtxStr(ushrtval); + case etCommandEditor: return CommandStr(ushrtval); + case etButtonFlagEditor: return ButtonFlagStr(ushrtval); + case etWindowFlagEditor: return WindowFlagStr(ushrtval); + case etValidatorEditor: return ValidatorStr(ushrtval); + } + } + else if (map->editorType == etStrCollectionEditor || + map->editorType == etCharPtrEditor) + { + memcpy(&ptrval, ldata, map->dataSize); + if (map->editorType == etCharPtrEditor) + return CharPtrStr(ptrval); else return ItemsStr(ptrval); + } + else if ( map->editorType == etStringEditor || + map->editorType == etValidatorDataEditor ) + { + memset(&buf, 0, 60); + memcpy(&buf, ldata, map->dataSize); + return buf; + } + else if ( map->editorType == etScrollBarEditor || + map->editorType == etLinkEditor ) + { + if (strlen((char *)ldata) > 0) return strcpy(buf, (char *)ldata); + } + return buf; +} + +class TLDrawBuffer: public TDrawBuffer +{ +public: + ushort getData(ushort i) { return data[i]; } +}; + +#define _lo_(a) ((uchar *)&a)[0] + +void TObjEditView::draw() +{ + TLDrawBuffer b; + const TStructMap * curMap; + const TStructMap * cur; + int r, l, tmp, line = 0; + char lstr[100], rstr[100]; + char lfmt[10], rfmt[10]; + ushort attr; + + if (separator > size.x) separator = size.x / 2; + r = (size.x - separator) + separator; + l = separator; + + curMap = currentMap; + if ((curMap) && size.y > 0) + { + cur = curMap; + while (cur->prev) cur = cur->prev; + do + { + if (cur->dataSize == 0) + { + tmp = (size.x - strlen(cur->label)) / 2; + b.moveChar(0, 0x20, 0x3e, tmp); + b.moveBuf(tmp, cur->label, 0x3e, strlen(cur->label)); + b.moveChar(tmp + strlen(cur->label), 0x20, 0x3e, tmp + 1); + attr = b.getData(l); + if (_lo_(attr) == 0x20) b.moveChar(l, 0xb3, 0x31, 1); + writeLine(0, line, size.x, 1, b); + line++; + } + else + { + sprintf(lfmt, "%%-%is", l - 1); + sprintf(lstr, lfmt, cur->label); + sprintf(rfmt, "%%-%is", r); + char *tmp=newStr(getValueFor(cur)); + if (tmp && strlen(tmp)>=(size_t)r) + tmp[r-1]=0; + sprintf(rstr, rfmt, tmp ? tmp : "ERROR"); + DeleteArray(tmp); + if (cur == curMap) + attr = 0x71; else attr = 0x1f; + b.moveBuf(0, lstr, attr, l); + if (cur == curMap) + attr = 0x71; else attr = 0x13; + b.moveChar(l, 0xb3, attr, 1); + if (cur == curMap) + attr = 0x71; else attr = 0x1e; + b.moveBuf(l + 1, rstr, attr, r); + writeLine(0, line, size.x, 1, b); + line++; + } + if (line > size.y - 1) break; + cur = cur->next; + } while (cur); + b.moveChar(0, 0x20, 0x1f, size.x); + b.moveChar(l, 0xb3, 0x13, 1); + writeLine(0, line, size.x, size.y - line, b); + } + else TView::draw(); +} + +#undef _lo_ + +const TStructMap * itemForLine(int line, const TStructMap * Map) +{ + ushort i = 1; + + if (line == 0 || Map == 0) return 0; + while (Map->next) + { + Map = Map->next; + if (i++ == line) break; + } + if (Map->dataSize != 0) return Map; else return 0; +} + +#define _endcase_(a) if (currentMap->dataSize == 0) \ + while ((currentMap->a) && (currentMap->dataSize == 0))\ + currentMap = currentMap->a; sb->setValue(currentMap->index); \ + drawView(); clearEvent(event) + +void TObjEditView::handleEvent(TEvent& event) +{ + const TStructMap * t; + ushort i; + + TView::handleEvent(event); + + if (!currentMap) return; + + TPoint Locate; + if (event.what == evBroadcast && + event.message.command == cmScrollBarChanged && + event.message.infoPtr == sb) + { + i = sb->value; + t = dataMap; + while ((t->index != i) && (t->next)) t = t->next; + if ((t->index == i) && (t != currentMap)) + { + currentMap = t; + drawView(); + } + } + else + if (event.what == evMouseDown) + { + Locate = makeLocal(event.mouse.where); + if (Locate.x == separator) + { + do + { + Locate = makeLocal(event.mouse.where); + if ((Locate.x >= 1) && (Locate.x <= (size.x - 2))) + { separator = Locate.x; drawView(); } + } while ( mouseEvent( event, evMouseMove ) ); + } + else + { + t = itemForLine(Locate.y, dataMap); + if ((t) && t != currentMap) + { + sb->setValue(t->index); + currentMap = t; + drawView(); + } + else if ((t == currentMap) && (event.mouse.doubleClick) && + (event.mouse.buttons == mbLeftButton)) editItem(currentMap); + } + } + else + if (event.what == evKeyboard) + { + switch(event.keyDown.keyCode) + { + case kbUp: + if (currentMap->prev) + { + currentMap = currentMap->prev; + if (currentMap->dataSize == 0) + if (currentMap->prev) currentMap = currentMap->prev; + _endcase_(next); + } + break; + case kbDown: + if (currentMap->next) + { + currentMap = currentMap->next; + _endcase_(next); + } + break; + case kbPgUp: + while (currentMap->prev) currentMap = currentMap->prev; + _endcase_(next); + break; + case kbPgDn: + while (currentMap->next) currentMap = currentMap->next; + _endcase_(prev); + break; + case kbEnter: + clearEvent(event); + if (currentMap->dataSize > 0) editItem(currentMap); + break; + case kbDel: + if (currentMap->editorType == etScrollBarEditor || + currentMap->editorType == etLinkEditor) + strcpy((char *)data + currentMap->offset, blank); + drawView(); + clearEvent(event); + break; + } + } +} + +#undef _endcase_ + +/* TObjedit ===============================================================*/ + +TObjEdit::TObjEdit(TDsgObj * Obj): + TWindowInit(&TObjEdit::initFrame), + TWindow( TRect(55, 0, 80, 23), _("Object editor"), 0 ) +{ + flags &= ~wfClose; + flags |= wfGrow; + if (!LinkList) LinkList = new TStringCollection(0, 1); + else LinkList->removeAll(); + if (!ScrollList) ScrollList = new TStringCollection(0, 1); + else ScrollList->removeAll(); + LinkList->duplicates = False; + ScrollList->duplicates = False; + if (!ObjLink) ObjLink = new TLinkList(); + else ObjLink->removeAll(); + TScrollBar * sb = new TScrollBar( TRect(24, 1, 25, 19) ); + insert(sb); + sb->growMode |= gfGrowHiY; + TRect r = getExtent(); + r.grow(-1, -1); + r.b.y -= 3; + dataView = new TObjEditView( r, sb ); + dataView->growMode |= (gfGrowHiY | gfGrowHiX); + dataView->options |= ofPreProcess | ofPostProcess | ofFramed; + ObjEdit = this; + insert(dataView); + setObjData(Obj); +} + +void TObjEdit::handleEvent(TEvent& event) +{ + TWindow::handleEvent(event); + if (object == 0) return; + if (event.what == evMessage && + event.message.command == cmValueChanged) + { + object->dsgUpdate(); + clearEvent(event); + } +} + +void TObjEdit::setObjData(TDsgObj * Obj) +{ + const TStructMap * Map = 0; + + if ((!Obj) || object == Obj) return; + + dataView->setMap(0, 0); + + object = Obj; + + switch (Obj->viewType) + { + case vtLabel: Map = TLabelMap; break; + case vtInput: Map = TInputMap; break; + case vtMemo: Map = TMemoMap; break; + case vtStatic: Map = TStaticMap; break; + case vtButton: Map = TButtonMap; break; + case vtListBox: Map = TListBoxMap; break; + case vtRadioButton: Map = TClusterMap; break; + case vtCheckBox: Map = TClusterMap; break; + case vtDialog: Map = TDialogMap; break; + default: Map = TViewMap; + } + if (!Map) + { + messageBox("Sem mapa!", mfOKButton); + dataView->setMap(0, 0); + return; + } + +#if 0 + int i = 0; + TStructMap * m = Map; + char c[100]; + m = Map; + while (m->prev) m = m->prev; + while (m) { i += m->dataSize; m = m->next; }; + if (i != Obj->getAttrSize()) + { + sprintf(c, "diferenca mapa: %i registro: %i", i, Obj->getAttrSize()); + messageBox(c, mfOKButton); + } +#endif + dataView->vtCurrent = Obj->viewType; + dataView->setMap(Map, Obj->attributes); +} + + diff --git a/tvision/examples/dlgdsn/propedit.h b/tvision/examples/dlgdsn/propedit.h new file mode 100644 index 0000000..51722ea --- /dev/null +++ b/tvision/examples/dlgdsn/propedit.h @@ -0,0 +1,122 @@ +/*************************************************************************** + + propedit.h - Prototype for object editor + --------------------------------------------------------------------- + May, 2000 + Copyright (C) 2000 by Warlei Alves + walves@usa.net + + Modified by Salvador E. Tropea to compile without warnings. + + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#if !defined(_PROPEDIT_HPP_) +#define _PROPEDIT_HPP_ + +#define Uses_TWindow +#define Uses_TDialog +#define Uses_TEvent +#define Uses_TListBox +#define Uses_TScrollBar +#define Uses_TStringCollection +#define Uses_TCollection +#define Uses_TInputLine +#define Uses_TValidator +#define Uses_opstream +#define Uses_ipstream + +#include + +class TDsgObj; +class TStructMap; + +// Sort function prototype +typedef int (* ccSortFunc)(const void *, const void *); + +typedef struct TDsgLink +{ + TView * v; + TDsgObj * d; +}; + +// The manager for TDsgObj<->TView linked list. +// Editable objects are descendants from TView and TDsgObj. +// It's make easy some operations but one can't be externaly +// referenced as other. To make that we need this class. +class TLinkList: public TCollection +{ +public: + TLinkList(): TCollection(0, 1) { }; + TDsgLink * viewFind(void * aView); // Find the link for a TView + TDsgLink * dsgObjFind(void * aDsgObj); // Find the link for a TDsgObj + TDsgLink * scrollFind(char *); // Find the scrollbar by index + TDsgLink * linkFind(char *); // Returns the TDLabel linked to + void removeMe(TDsgObj * aDsgObj); // Remove the link for a TDsgObj + void add(TView * aView, TDsgObj * aDsgObj); // Add new link + virtual void freeItem(void * item); + virtual void * readItem(ipstream &) { return 0; }; // It not need be loaded or... + virtual void writeItem(void *, opstream &) { }; // saved + void sort(ccSortFunc Compare); // Tabulation + void doReOrder(); // methods + void removeNotify(TCollection * aCollection, int Index); + void sortForBuild(); + void linkChangedName(char * oldName, char * newName); +}; + +// Ordinary number and short string editor +// Is a TInputLine descendant to be executed in a TWindow +class TInPlaceEdit: public TInputLine +{ + ushort endState; +public: + TInPlaceEdit(const TRect& bounds, ushort aMaxLen, + TValidator * aValidator); + virtual ushort execute(); + virtual void handleEvent(TEvent& event); + virtual TPalette& getPalette() const; +}; + +// A grid style viewer and editor for objects +class TObjEditView: public TView +{ + const char * getValueFor(const TStructMap * map); + void editItem(const TStructMap * map); + int separator; + TScrollBar * sb; + const TStructMap * dataMap; + const TStructMap * currentMap; + void * data; +public: + TObjEditView(const TRect& bounds, TScrollBar * v); + virtual void handleEvent(TEvent& event); + virtual void draw(); + void setMap(const TStructMap * aMap, void * Data); + int vtCurrent; +}; + +// A TWindow to host the object editor +class TObjEdit: public TWindow +{ + void editItem(TStructMap * map); + TObjEditView * dataView; +public: + TObjEdit(TDsgObj * Obj); + void setObjData(TDsgObj * DsgObj); + virtual void handleEvent(TEvent& event); + TDsgObj * object; +}; + +int execDialog(TDialog * dialog, void *data); + +TLinkList * ObjectLinker(); + +#endif // _PROPEDIT_HPP_ diff --git a/tvision/examples/dlgdsn/rhide.env b/tvision/examples/dlgdsn/rhide.env new file mode 100644 index 0000000..56091d7 --- /dev/null +++ b/tvision/examples/dlgdsn/rhide.env @@ -0,0 +1,5 @@ +# +# This include file have rhide options for all the subprojects. +# +include ../rhide.env + diff --git a/tvision/examples/dlgdsn/strmoper.cc b/tvision/examples/dlgdsn/strmoper.cc new file mode 100644 index 0000000..1cc36e2 --- /dev/null +++ b/tvision/examples/dlgdsn/strmoper.cc @@ -0,0 +1,108 @@ +/*************************************************************************** + + strmoper.cc - Stream operations + --------------------------------------------------------------------- + May, 2000 + Copyright (C) 2000 by Warlei Alves + walves@usa.net + + Modified by Salvador E. Tropea to compile without warnings. + For gcc 2.95.x and then 3.0.1. + + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#define Uses_stdio +#define Uses_string +// didn't find std::ios (AP) +#define Uses_iostream + +#define Uses_MsgBox +#define Uses_TFileDialog +#define Uses_TProgram +#define Uses_TApplication +#define Uses_TDeskTop +#define Uses_ofpstream +#define Uses_ifpstream + +#include +#include "strmoper.h" + +UsingNamespaceStd + +bool fileExists(const char * FileName) +{ + FILE * test; + + bool rst = ((test = fopen(FileName, "r")) != 0); + if (rst) fclose(test); + return rst; +} + +// SET: This function was originaly declared as const char * and returned a +// pointer to a temporal variable in the stack. Nicola Asuni found it and +// suggested a partial workaround. I then modified the function to return +// a char * using newStr to allocate it. I also modified all the points +// where this function is used (at least all that I found) to release the +// returned value. +char * getFileName(const char * aTitle, const char * ext, int Mode) +{ + TFileDialog *d = 0; + int cmd = cmCancel; + + if (Mode == 0) + d = (TFileDialog *) TProgram::application->validView( new + TFileDialog(ext, aTitle, _("File"), fdOpenButton, 100) ); + else + d = (TFileDialog *) TProgram::application->validView( new + TFileDialog(ext, aTitle, _("File"), fdOKButton, 100) ); + if (d != 0) cmd = TProgram::deskTop->execView( d ); + if ( cmd != cmCancel ) + { + char fileName[PATH_MAX]; + d->getFileName( fileName ); + delete d; + return newStr( fileName ); + } + else return NULL; +} + + +ifpstream * openFile(const char * FileName, char * Signature) +{ + if (!fileExists(FileName)) return 0; + ifpstream * rst = new ifpstream( FileName, ios::in|ios::binary ); + char buf[50]; + if (rst) + { + rst->readBytes(&buf, strlen(Signature) + 1); + if (strcmp(buf, Signature) != 0) + { + delete rst; + return 0; + } + } + return rst; +} + +ofpstream * initFile(const char * FileName, char * current, char * Signature) +{ + if ( fileExists(FileName) && + ( current == 0 || strcmp(FileName, current) != 0 ) ) + { + if ( messageBox(__("The file already exists. Overwrite it?"), + mfYesNoCancel) != cmYes ) return 0; + } + ofpstream * rst = new ofpstream( FileName, ios::in|ios::binary ); + if (rst) rst->writeBytes(Signature, strlen(Signature) + 1); + return rst; +} + diff --git a/tvision/examples/dlgdsn/strmoper.h b/tvision/examples/dlgdsn/strmoper.h new file mode 100644 index 0000000..e7292d4 --- /dev/null +++ b/tvision/examples/dlgdsn/strmoper.h @@ -0,0 +1,33 @@ +/*************************************************************************** + + strmoper.h - Stream operations + --------------------------------------------------------------------- + May, 2000 + Copyright (C) 2000 by Warlei Alves + walves@usa.net + + Modified by Salvador E. Tropea to compile without warnings. + + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#define dialogFileSig "FreeDsgn Dialog File\x1a" +#define menuFileSig "FreeDsgn Menu File\x1a" +#define statusLineFileSig "FreeDsgn StatusLine File\x1a" +#define constanstFileSig "FreeDsgn Constants File\x1a" +#define helpCtxFileSig "FreeDsgn Help Contexts File\x1a" +#define AppDataFileSig "FreeDsgn App Data File\x1a" +#define hintsDataFileSig "FreeDsgn Hints File\x1a" + +ifpstream * openFile(const char * FileName, char * Signature); +ofpstream * initFile(const char * FileName, char * current, char * Signature); +char * getFileName(const char * aTitle, const char * ext, int Mode); + diff --git a/tvision/examples/dlgdsn/tappwnd.cc b/tvision/examples/dlgdsn/tappwnd.cc new file mode 100644 index 0000000..9f42ef9 --- /dev/null +++ b/tvision/examples/dlgdsn/tappwnd.cc @@ -0,0 +1,159 @@ +/*************************************************************************** + + tappwnd.cc - Application window + --------------------------------------------------------------------- + May, 2000 + Copyright (C) 2000 by Warlei Alves + walves@usa.net + + Modified by Salvador E. Tropea to compile without warnings. + + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "dsgobjs.h" + +#define cpAppWnd\ + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" \ + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" \ + "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" \ + "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" \ + +TAppWindow::TAppWindow(): + TWindowInit(&TAppWindow::initFrame), + TWindow( TRect(0, 0, 60, 20), "", 0 ), + menuBar( 0 ), + statusLine( 0 ) +{ + options |= ofCentered; + TRect r = getExtent(); + r.grow(0, -1); + deskTop = new TDeskTop( r ); + deskTop->growMode = gfGrowHiX | gfGrowHiY; + insert(deskTop); +} + +TAppWindow::~TAppWindow() +{ + removeMenuBar(); + removeStatusLine(); +} + +TFrame * TAppWindow::initFrame(TRect r) +{ + return 0; +} + +TPalette& TAppWindow::getPalette() const +{ + static TPalette p( cpAppWnd, sizeof(cpAppWnd) - 1 ); + return p; +} + +void TAppWindow::changeBounds(const TRect& bounds) +{ + TWindow::changeBounds(bounds); + TRect r = getExtent(); + r.a.y = r.b.y - 1; + statusLine->changeBounds(r); + deskTop->redraw(); +} + +void TAppWindow::removeStatusLine() +{ + if (statusLine != 0) + { + remove(statusLine); + delete statusLine; + statusLine = 0; + } +} + +void TAppWindow::removeMenuBar() +{ + if (menuBar != 0) + { + remove(menuBar); + delete menuBar; + menuBar = 0; + } +} + +void TAppWindow::setMenuBar(TEditCollection * aItems) +{ + removeMenuBar(); + if (aItems == 0) return; +} + +void TAppWindow::setStatusLine(TEditCollection * aItems) +{ + removeStatusLine(); + if (aItems == 0) return; +} + +void TAppWindow::setMenuBar(TMenuBar * aMenuBar) +{ + removeMenuBar(); + if (aMenuBar == 0) return; + menuBar = aMenuBar; + menuBar->growMode = gfGrowHiX; + insert(menuBar); +} + +void TAppWindow::setStatusLine(TStatusLine * aStatusLine) +{ + removeStatusLine(); + if (aStatusLine == 0) return; + statusLine = aStatusLine; + statusLine->growMode = gfGrowRel; + insert(statusLine); +} + +int lmessageBox(const char * msg, TGroup * aOwner) +{ + TDialog * d = new TDialog( TRect(0, 0, 40, 9), __("Confirm") ); + d->insert( new TStaticText( TRect(3, 2, d->size.x - 2, d->size.y - 3), msg) ); + d->options |= ofCentered; + TRect r = TRect(0, 0, 10, 2); + r.move((d->size.x / 2) - 11, d->size.y - 3); + d->insert( new TButton( r, __("~Y~es"), cmYes, 0) ); + r.a.x += 11; r.b.x+= 11; + d->insert( new TButton( r, __("~C~ancel"), cmCancel, 0) ); + d->selectNext(false); + int rst = aOwner->execView(d); + TObject::CLY_destroy( d ); + return rst; +} + +void TAppWindow::handleEvent(TEvent& event) +{ + TWindow * w; + + TWindow::handleEvent(event); + + if (event.what == evCommand) + { + switch (event.message.command) + { + case cmQuit: + if ( lmessageBox( __("Are you sure?"), deskTop ) == cmYes ) + endModal(cmQuit); + break; + case cmViewAppWindow: + w = new TWindow( TRect( 0, 0, 30, 10), "Teste", 0 ); + w->options |= ofCentered; + deskTop->insert(w); + break; + } + clearEvent(event); + } +} + diff --git a/tvision/examples/dyntxt/dyntext.bmk b/tvision/examples/dyntxt/dyntext.bmk new file mode 100644 index 0000000..a291a1a --- /dev/null +++ b/tvision/examples/dyntxt/dyntext.bmk @@ -0,0 +1,10 @@ +#!/usr/bin/make +# +# Copyright (c) 2003 by Salvador E. Tropea. +# Covered by the GPL license. +# +!include ../common.bmk +all: dyntext.exe +!include ../../makes/common.bmk +!include dyntext.umk + diff --git a/tvision/examples/dyntxt/dyntext.cpp b/tvision/examples/dyntxt/dyntext.cpp new file mode 100644 index 0000000..56b1f20 --- /dev/null +++ b/tvision/examples/dyntxt/dyntext.cpp @@ -0,0 +1,89 @@ +// Copyright (c) 1992 by James H. Price, All rights reserved +// +// DYNTEXT.CPP +// +// Member functions for DynamicText class +// + +#define Uses_string +#define Uses_TView +#define Uses_TStreamableClass +#define Uses_TPalette +#include + +#include "dyntext.h" + +#define cpDynamicText "\x06" + +DynamicText::DynamicText( const TRect& r, const char *aText, + Boolean rj ) : TView( r ), text( new char[size.x+1] ), + rightJustify( rj ) +{ + strncpy( text, aText, size.x ); + text[size.x] = EOS; +} + +DynamicText::~DynamicText() +{ + delete text; +} + +void DynamicText::draw() +{ + TDrawBuffer b; + uchar color = getColor(1); + int offset = ( rightJustify ) ? size.x-strlen(text) : 0; + + b.moveChar( 0, ' ', color, size.x ); + b.moveStr( offset, text, color ); + writeBuf( 0, 0, size.x, 1, b ); +} + +TPalette& DynamicText::getPalette() const +{ + static TPalette palette( cpDynamicText, sizeof( cpDynamicText )-1 ); + return palette; +} + +void DynamicText::setText( const char *s ) +{ + setData( (void *)s ); + drawView(); +} + +void DynamicText::setData( void *rec ) +{ + memmove( text, rec, size.x+1 ); + text[size.x] = EOS; +} + +void DynamicText::getData( void *rec ) +{ + strcpy( (char *)rec, text ); +} + +unsigned DynamicText::dataSize() +{ + return( size.x+1 ); +} + +void DynamicText::write( opstream& os ) +{ + TView::write( os ); + os.writeString( text ); + os << (int)rightJustify; +} + +void *DynamicText::read( ipstream& is ) +{ + int rj; + TView::read( is ); + text = is.readString(); + is >> rj; + rightJustify = Boolean( rj ); + return this; +} + +const char * const DynamicText::name = "DynamicText"; +TStreamableClass RDynamicText( DynamicText::name, + DynamicText::build, __DELTA(DynamicText) ); diff --git a/tvision/examples/dyntxt/dyntext.gpr b/tvision/examples/dyntxt/dyntext.gpr new file mode 100644 index 0000000..1914f92 Binary files /dev/null and b/tvision/examples/dyntxt/dyntext.gpr differ diff --git a/tvision/examples/dyntxt/dyntext.h b/tvision/examples/dyntxt/dyntext.h new file mode 100644 index 0000000..c87a9be --- /dev/null +++ b/tvision/examples/dyntxt/dyntext.h @@ -0,0 +1,59 @@ +// Copyright (c) 1992 by James H. Price, All rights reserved +// +// DYNTEXT.H +// +// Dynmaic text class +// + +#if !defined( __DYNTEXT_H ) +#define __DYNTEXT_H + +#define Uses_TView +#include + +class TStreamable; +class TPalette; + +class DynamicText : public TView { + +public: + + DynamicText( const TRect& r, const char *aText, Boolean rj=True ); + ~DynamicText(); + + void draw(); + TPalette& getPalette() const; + unsigned dataSize(); + void getData( void *rec ); + void setData( void *rec ); + void setText( const char *s ); + +protected: + + char *text; + Boolean rightJustify; + +private: + virtual const char *streamableName() const { return name; } +protected: + DynamicText( StreamableInit ) : TView( streamableInit ) {} + virtual void write( opstream& ); + virtual void *read( ipstream& ); +public: + static const char * const name; + static TStreamable *build() + { return new DynamicText( streamableInit ); } +}; + +inline ipstream& operator >> ( ipstream& is, DynamicText& cl ) + { return is >> (TStreamable&)cl; } +inline ipstream& operator >> ( ipstream& is, DynamicText*& cl ) + { return is >> (void *&)cl; } +inline opstream& operator << ( opstream& os, DynamicText& cl ) + { return os << (TStreamable&)cl; } +inline opstream& operator << ( opstream& os, DynamicText* cl ) + { return os << (TStreamable *)cl; } + + +#endif + diff --git a/tvision/examples/dyntxt/dyntext.mkf b/tvision/examples/dyntxt/dyntext.mkf new file mode 100644 index 0000000..c82eba8 --- /dev/null +++ b/tvision/examples/dyntxt/dyntext.mkf @@ -0,0 +1,11 @@ +#!/usr/bin/make +# +# Copyright (c) 2003-2004 by Salvador E. Tropea. +# Covered by the GPL license. +# +vpath_src= +vpath_obj=. +INCLUDE_DIRS=../../include +COMMON_IMK=../../makes/common.imk +include $(COMMON_IMK) +include dyntext$(ExIMK) diff --git a/tvision/examples/dyntxt/dyntext.umk b/tvision/examples/dyntxt/dyntext.umk new file mode 100644 index 0000000..25dea27 --- /dev/null +++ b/tvision/examples/dyntxt/dyntext.umk @@ -0,0 +1,22 @@ +#!/usr/bin/make +# Automatically generated from RHIDE projects, don't edit +# + +OBJFILES=\ + ./dyntext$(ExOBJ) \ + ./testdyn$(ExOBJ) + +LIBRARIES= + +dyntext$(ExEXE):: \ + ./dyntext$(ExOBJ) \ + ./testdyn$(ExOBJ) \ + $(MAKEFILE_DEPS) + $(RHIDE_COMPILE_LINK) + +./dyntext$(ExOBJ):: dyntext.cpp + $(RHIDE_COMPILE_CC) + +./testdyn$(ExOBJ):: testdyn.cpp + $(RHIDE_COMPILE_CC) + diff --git a/tvision/examples/dyntxt/readme b/tvision/examples/dyntxt/readme new file mode 100644 index 0000000..7596869 --- /dev/null +++ b/tvision/examples/dyntxt/readme @@ -0,0 +1,54 @@ +Dynamic Text Demonstration +Copyright (C) 1992 by James H. Price, all rights reserved + +Introduction + + This program implements a "dynamic text" class. + + The demo consists of the following files: + + DYNTEXT.H Header file for DynamicText + DYNTEXT.CPP Member functions for HintStatusLine + TESTDYN.CPP A simple TurboVision demo program + TESTDYN.PRJ Project file for the demo + README This file + + +Operation: + +DynamicText is a simple descendent of TView. In my current app, I +use it primarily to display totals under a column of input lines, +with the totals updated on the fly as the user inputs data. + +A couple of notes on its use: + +1. It has an optional "right justify" flag. If set to True (the +default), the text will be drawn at the right edge of the view; +otherwise it's drawn at the left edge. + +2. Unlike TStaticText, it has getData() and setData functions, so if +you use it in a TDialog (the expected case) you'll need to add a +field for it in any structure you pass to the dialog via +TDialog::getData() and TDialog::setData. + +3. It has a simple draw function: no centering, no wrapping across +multiple lines, etc, the way TStaticText does. + +4. Note that the length of the text string is set by the value +passed in the TRect parameter. If the string passed is larger than +the TRect width, the string is truncated. + +Other: + +I'll be happy to answer questions about the program, but I don't +intend to really 'support' it. Extending and/or maintaining the code +is left as an exercise for the user! + +Any rights which Borland may have to TurboVision-based code remain in +force. Otherwise, feel free to use this code as you see fit. I'm +reasonably certain that it works as described, but of course, you use +it at your own risk. If you distribute this as source code, please +include this file. + +Jim Price 76264,3534 +21 Sept 92 diff --git a/tvision/examples/dyntxt/rhide.env b/tvision/examples/dyntxt/rhide.env new file mode 100644 index 0000000..56091d7 --- /dev/null +++ b/tvision/examples/dyntxt/rhide.env @@ -0,0 +1,5 @@ +# +# This include file have rhide options for all the subprojects. +# +include ../rhide.env + diff --git a/tvision/examples/dyntxt/testdyn.cpp b/tvision/examples/dyntxt/testdyn.cpp new file mode 100644 index 0000000..fa12a2b --- /dev/null +++ b/tvision/examples/dyntxt/testdyn.cpp @@ -0,0 +1,195 @@ +// Copyright (C) 1992 James H. Price, All rights reserved +// +// TESTDYN.CPP +// +// Test program for dynamic text +// + +#define Uses_MsgBox +#define Uses_TEvent +#define Uses_TApplication +#define Uses_TKeys +#define Uses_TRect +#define Uses_TMenu +#define Uses_TMenuBar +#define Uses_TMenuItem +#define Uses_TStatusLine +#define Uses_TStatusItem +#define Uses_TStatusDef +#define Uses_TDeskTop +#define Uses_TDialog +#define Uses_TInputLine +#define Uses_TButton +#include + +#include "dyntext.h" + +const int cmAbout = 100; +const int cmTest = 101; + + +//////////////////////////////////////////////////////////////////////// +//////////////////////// Usual TurboVision Stuff /////////////////////// + +class Shell : public TApplication { + +public: + + Shell(); + static TMenuBar *initMenuBar( TRect r ); + static TStatusLine *initStatusLine( TRect r ); + void handleEvent( TEvent& event ); + void idle(); + +private: + + void About(); + void Test(); +}; + +Shell::Shell() : TProgInit ( + &Shell::initStatusLine, + &Shell::initMenuBar, + &Shell::initDeskTop + ) +{ +} + +TMenuBar *Shell::initMenuBar( TRect r ) +{ + r.b.y = r.a.y + 1; + + TMenuItem& mI = + *new TMenuItem( "~T~est", cmTest, kbNoKey, hcNoContext ); + + return new TMenuBar( r, new TMenu( mI ) ); +} + +TStatusLine *Shell::initStatusLine( TRect r ) +{ + r.a.y = r.b.y - 1; + + TStatusLine *sL = new TStatusLine( r, + *new TStatusDef(0, 0xFFFF) + + *new TStatusItem( 0, kbF10, cmMenu ) + + *new TStatusItem( "~Alt-X~ Quit", kbAltX, cmQuit ) ); + + return sL; +} + +void Shell::handleEvent( TEvent &event ) +{ + TApplication::handleEvent(event); + + if (event.what == evCommand) + { + switch (event.message.command) + { + case cmAbout: + About(); + break; + case cmTest: + Test(); + break; + default: + break; + } + } +} + +void Shell::About() +{ + messageBox( "\003Dynamic Text Demo", + mfInformation | mfOKButton ); +} + +void Shell::idle() +{ + TProgram::idle(); + + // select menu bar if deskTop empty + + if( deskTop->current == 0 + && !menuBar->getState( sfSelected ) ) + { + TEvent event; + event.what = evCommand; + event.message.command = cmMenu; // put a cmMenu event in queue + putEvent( event ); + } +} + + +////////////////////////////////////////////////////////////////////////// +//////////////////////// Simple Test Dialog Box //////////////////////// + +class TestDialog : public TDialog { +public: + TestDialog(); + void handleEvent( TEvent& event ); +private: + TInputLine *master; + DynamicText *slave; +}; + +TestDialog::TestDialog() : + TWindowInit( &TestDialog::initFrame ), + TDialog( TRect(0,0,40,10), "Dynamic Text" ) +{ + options |= ofCentered; + + master = new TInputLine( TRect(10,2,32,3), 21 ); + insert( master ); + + // This allocates a 21 byte string (20 + 1 for null). The 'False' + // argument indicates that it should be left-justified + slave = new DynamicText( TRect(11,4,31,5), "Initial text", False ); + insert(slave); + + insert( new TButton( TRect(15,6,25,8), "O~K~", cmOK, bfNormal ) ); + + master->select(); +} + +void TestDialog::handleEvent( TEvent& event ) +{ + if( event.what == evKeyDown + && event.keyDown.keyCode == kbTab ) + { + char buf[30]; + master->getData( buf ); // read the input + slave->setText( buf ); // write it into static text + } + TDialog::handleEvent( event ); +} + +/////////////////////////////////////////////////////////////////////////// +///////////////////////// Test routine //////////////////////////////////// + +void Shell::Test() +{ + TestDialog *d = new TestDialog; // create dialog + deskTop->execView( d ); // execute it + CLY_destroy( d ); // destroy it + + // Note: This doesn't illustrate the getData() and setData() + // functions, which work as usual for TVision objects. If you + // use TDialog::getData and setData, you *must* have space in + // void *rec structure for any DynamicText objects, +} + +/////////////////////////////////////////////////////////////////////////// +////////////////////////////// main() function //////////////////////////// + +int main() +{ + TEvent init; + init.what = evCommand; + init.message.command = cmAbout; // make a cmAbout command event + + Shell shell; + shell.putEvent(init); // put it in the queue to pop up + shell.run(); // About box when program starts + return 0; +} + diff --git a/tvision/examples/eterm/menus.cfg b/tvision/examples/eterm/menus.cfg new file mode 100644 index 0000000..9e5f6cd --- /dev/null +++ b/tvision/examples/eterm/menus.cfg @@ -0,0 +1,93 @@ + +begin menu + title Font + begin menuitem + text "5x7" + action string "\e]50;#0" + end + begin menuitem + text "6x12" + action string "\e]50;#1" + end + begin menuitem + text "7x14" + action string "\e]50;#2" + end + begin menuitem + text "8x16" + action string "\e]50;#3" + end + begin menuitem + text "10x20" + action string "\e]50;#4" + end + begin menuitem + text "12x24" + action string "\e]50;#5" + end +end +begin menu + title Eterm + begin menuitem + text "Font" + action submenu "Font" + end + begin menuitem + text "Terminal" + action submenu "Terminal" + end + - + begin menuitem + text "New Eterm Window" + action script "spawn(Eterm)" + end + begin menuitem + text "Version" + action string "\e[8n" + end + begin menuitem + text "Status" + action string "\e[9n" + end + separator + begin menuitem + text "Save User Settings..." + action script "save" + end + begin menuitem + text "Save Theme Settings..." + action script "save(theme)" + end + begin menuitem + text "Exit" + action script "exit" + end +end +begin menu + title "Eterm Operations" + begin menuitem + text "New Eterm Window" + action script "spawn(Eterm)" + end + begin menuitem + text "Version" + action string "\e[8n" + end + begin menuitem + text "Status" + action string "\e[9n" + end + separator + begin menuitem + text "Save User Settings..." + action script "save" + end + begin menuitem + text "Save Theme Settings..." + action script "save(theme)" + end + begin menuitem + text "Exit" + action script "exit" + end +end diff --git a/tvision/examples/eterm/theme.cfg b/tvision/examples/eterm/theme.cfg new file mode 100644 index 0000000..2c8b691 --- /dev/null +++ b/tvision/examples/eterm/theme.cfg @@ -0,0 +1,620 @@ + +# +# This the sample Eterm config file adapted to be used with TV applications. +# The resulting terminal is fine tunned to run a TV application and not for +# general use. +# What's changed? +# +# * Font sizes, most have 0.5 aspect ratio. +# * Colors to match VGA BIOS values. +# * Removed scroll bar, actually the only way I know to scroll in this setup +# is using the mouse wheel. Don't know how to assign it to a key if you +# know please tellme. +# * A lot of key combinations defined. +# * The menu is reduced to just a few items. +# +# I didn't remove all original comments so you can customize it. +# +# IMPORTANT!! The keys assignments are good for TV and what my system defines +# as TERM=Eterm, it doesn't mean it will work on any system. +# I tested it Using Debian GNU/Linux Woody. +# +# As always, the authors guarantee absolutely nothing and take +# no responsibility for anything that might happen to you, your +# computer, your dog, your sex life, or anyone or anything else +# directly or indirectly through the use of, or inability to use, +# this program. Use at your OWN risk. + +# Define the color properties +begin color + +# Foreground, background, cursor, scrollbar, pointer colors + foreground #aaaaaa + background black + cursor #ffff00 + cursor_text #880000 + pointer white + +# video attribute can either be "normal" or "reverse" + video normal + +# Redefine the 16 basic colors, if you really feel the need +# First word is "color", next is the number (0-15, BD, or UL), +# then the values for red, green, and blue separated by spaces +# Numbers are base 10 unless preceded by "0x" (base 16) or '0' +# (base 8). Alternatively, you can use color names or #xxxxxx +# format. + +# SET: The default Eterm palette doesn't match the VGA BIOS one, I think +# Eterm is wrong. +# + color 0 0 0 0 + color 1 0xa8 0 0 + color 2 0 0xa8 0 + color 3 0xa8 0x54 0 + color 4 0 0 0xa8 + color 5 0xa8 0 0xa8 + color 6 0 0xa8 0xa8 + color 7 0xa8 0xa8 0xa8 + color 8 0x54 0x54 0x54 + color 9 0xfc 0x54 0x54 + color 10 0x54 0xfc 0x54 + color 11 0xfc 0xfc 0x54 + color 12 0x54 0x54 0xfc + color 13 0xfc 0x54 0xfc + color 14 0x54 0xfc 0xfc + color 15 #ffffff + color bd #ffffff + color ul #ffffff + +end color + +# The X11 attributes section. Should be fairly self-explanatory, +# but if not, consult the X man page. +begin attributes + +# Geometry == widthxheight+x_offset+y_offset, offsets from top left +# if +, bottom right if - +# geometry 132x50+100+100 +# title %appname() +# name %appname() +# iconname Eterm + +# Set the fonts. These must be monospace fonts. The values shown are +# the Eterm defaults. The "bold" font is the font used if color BD has +# not been set and Eterm cannot map the foreground color to one of the +# high-intensity colors (8-15). + font default 4 + font 0 5x7 + font 1 6x12 + font 2 7x14 + font 3 8x16 +# font 4 9x18 Fails on my system + font 4 10x20 + font 5 12x24 +# font bold 7x14 +end attributes + +# The Multichar support options. Same goes for these fonts as for the normal +# ones. The "encoding" attribute can be either "eucj" or "sjis" or "euckr" +# or big5 or gb +begin multichar + font 0 -misc-fixed-medium-r-normal--7-70-75-75-c-50-iso10646-1 + font 1 -misc-fixed-medium-r-normal--10-100-75-75-c-60-iso10646-1 + font 2 -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1 + font 3 -misc-fixed-medium-r-normal--14-130-75-75-c-70-iso10646-1 + font 4 -misc-fixed-medium-r-normal--15-140-75-75-c-90-iso10646-1 + encoding iso-10646 +end multichar + +# Define the imageclasses. +begin imageclasses + +# You must define this before setting any images that use it. This is the $PATH-style variable +# that determines where Eterm looks for image files. + path "./pix/:~/.Eterm/:~/.Eterm/themes/Eterm/pix:~/.Eterm/pix/:/usr/share/Eterm/pix/" + +# If you want a different icon than the standard Eterm one, set this. +# icon Eterm.xpm + +# This is the background animator. See the man page for the syntax. +# anim 3 foo1 foo2 foo3 + +# The rest of the images. + begin image + type trough + mode image allow image trans viewport auto + state normal + color black #666666 + file bar_vertical_3.png +# Here is how you specify the geometry string separately. See the man page for its syntax. + geom 100 + border 2 2 2 3 + end image + begin image + type anchor + mode image allow image auto + state normal + color black #666666 + file bar_vertical_1.png + geom 100 + border 2 2 2 3 + state selected + file bar_vertical_2.png + geom 100 + border 2 2 2 3 + end image + begin image + type thumb + mode image allow image auto + state normal + color black #666666 + file thumb_1.png + geom 100 + border 3 3 3 3 + state selected + file thumb_2.png + geom 100 + border 3 3 3 3 + end image + begin image + type up_arrow + mode image allow image auto + state normal + color black #666666 + file button_arrow_up_1.png + geom 100 + border 2 2 2 2 + state selected + file button_arrow_up_2.png + geom 100 + border 2 2 2 2 + state clicked + file button_arrow_up_3.png + geom 100 + border 2 2 2 2 + end image + begin image + type down_arrow + mode image allow image auto + state normal + color black #666666 + file button_arrow_down_1.png + geom 100 + border 2 2 2 2 + state selected + file button_arrow_down_2.png + geom 100 + border 2 2 2 2 + state clicked + file button_arrow_down_3.png + geom 100 + border 2 2 2 2 + end image + begin image + type menu + #mode auto allow image auto + mode image allow image auto + state normal + #color #AAAAAA #999999 + color black #999999 + file bar_horizontal_1.png + geom 100 + border 2 3 2 3 + state selected + file bar_horizontal_2.png + geom 100 + border 2 3 2 3 + end image + begin image + type submenu + #mode auto allow image auto + mode image allow image auto + state normal + #color #AAAAAA #999999 + color black #999999 + file menu1.png + geom 100 + border 3 15 3 3 + padding 3 15 3 3 + state selected + file menu2.png + geom 100 + border 3 15 3 3 + padding 3 15 3 3 + state clicked + file menu3.png + geom 100 + border 3 15 3 3 + padding 3 15 3 3 + end image + begin image + type button_bar + #mode auto allow image auto + mode image allow image auto + state normal + #color #AAAAAA #999999 + color black #999999 + file bar_horizontal_1.png + geom 100 + border 2 3 2 2 + state disabled + color white #333333 + cmod image 0xc0 + border 2 3 2 2 + end image + begin image + type button + #mode auto allow image auto + mode image allow image auto + state normal + #color #AAAAAA #999999 + color black #cccccc + file bar_horizontal_1.png + geom 100 + border 2 3 2 2 + state selected + file bar_horizontal_2.png + geom 100 + border 2 3 2 2 + state clicked + file bar_horizontal_3.png + geom 100 + border 2 3 2 2 + end image +end + +%include "menus.cfg" + +# This section *must* come after the menu definitions if you want +# menu actions to work. C'est la vie. :-) +# +# Syntax: bind [ { | anymod } ] { | |