diff --git a/configure.ac b/configure.ac index e15bb28a0..4ca87e58b 100644 --- a/configure.ac +++ b/configure.ac @@ -324,6 +324,7 @@ lib/sectionsdclient/Makefile lib/timerdclient/Makefile lib/libcoolstream/Makefile lib/libtuxtxt/Makefile +lib/libtuxtxt_mp/Makefile lib/libdvbsub/Makefile lib/libupnpclient/Makefile lib/libiw/Makefile diff --git a/lib/Makefile.am b/lib/Makefile.am index 037c33c38..18e0a0b70 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -8,7 +8,6 @@ SUBDIRS = \ libnet \ xmltree \ jsoncpp \ - libtuxtxt \ libiw \ libdvbsub \ luaclient @@ -20,5 +19,9 @@ endif if BOXTYPE_COOL SUBDIRS += \ - libcoolstream + libcoolstream \ + libtuxtxt +else +SUBDIRS += \ + libtuxtxt_mp endif diff --git a/lib/libtuxtxt/Makefile.am b/lib/libtuxtxt/Makefile.am index f40d16044..7ea232ad1 100644 --- a/lib/libtuxtxt/Makefile.am +++ b/lib/libtuxtxt/Makefile.am @@ -1,8 +1,6 @@ AM_CPPFLAGS = \ -I$(top_builddir) \ -I$(top_srcdir) \ - -I$(top_srcdir)/lib \ - -I$(top_srcdir)/lib/libconfigfile \ -I$(top_srcdir)/src \ -I$(top_srcdir)/src/zapit/include \ $(FREETYPE_CFLAGS) \ diff --git a/lib/libtuxtxt/libtuxtxt.cpp b/lib/libtuxtxt/libtuxtxt.cpp index 40af36282..27111f618 100644 --- a/lib/libtuxtxt/libtuxtxt.cpp +++ b/lib/libtuxtxt/libtuxtxt.cpp @@ -37,8 +37,6 @@ int tuxtxt_init() tuxtxt_cache.vtxtpid = -1; tuxtxt_cache.thread_id = 0; tuxtxt_cache.dmx = -1; - /* not sure if this is correct here... */ - tuxtxt_cache.page = 0x100; return 1;//tuxtxt_init_demuxer(); } diff --git a/lib/libtuxtxt/teletext.h b/lib/libtuxtxt/teletext.h index 6bc3dc590..fe94e902c 100644 --- a/lib/libtuxtxt/teletext.h +++ b/lib/libtuxtxt/teletext.h @@ -1,3 +1,12 @@ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if !HAVE_COOL_HARDWARE +#include +#else + #ifndef __teletext_h__ #define __teletext_h__ @@ -12,3 +21,4 @@ void tuxtx_pause_subtitle(bool pause = 1); void tuxtx_set_pid(int pid, int page, const char * cc); #endif +#endif diff --git a/lib/libtuxtxt/tuxtxt.cpp b/lib/libtuxtxt/tuxtxt.cpp index b26e48e37..91722ee88 100644 --- a/lib/libtuxtxt/tuxtxt.cpp +++ b/lib/libtuxtxt/tuxtxt.cpp @@ -11,8 +11,6 @@ * * * ported 2009 to HD1 by Coolstream LTD * * * - * TD, SPARK and AZbox port (C) 2010-2013 Stefan Seyfried * - * * ******************************************************************************/ #include "teletext.h" @@ -21,19 +19,12 @@ #include #include #include -#include /* same as in rcinput.h... */ #define KEY_TTTV KEY_FN_1 #define KEY_TTZOOM KEY_FN_2 #define KEY_REVEAL KEY_FN_D -#ifdef HAVE_SPARK_HARDWARE -#define MARK_FB(a, b, c, d) if (p == lfb) CFrameBuffer::getInstance()->mark(a, b, (a) + (c), (b) + (d)) -#else -#define MARK_FB(a, b, c, d) -#endif - extern cVideo * videoDecoder; static pthread_t ttx_sub_thread; @@ -44,24 +35,11 @@ static int sub_pid, sub_page; static bool use_gui; static int cfg_national_subset; -static int screen_x, screen_y, screen_w, screen_h; - //#define USE_FBPAN // FBIOPAN_DISPLAY seems to be working in current driver -unsigned char *getFBp(int *y) -{ - if (*y < (int)var_screeninfo.yres) - return lfb; - - *y -= var_screeninfo.yres; - return lbb; -} - void FillRect(int x, int y, int w, int h, int color) { - unsigned char *p = getFBp(&y); - MARK_FB(x, y, w, h); - p += x*4 + y * fix_screeninfo.line_length; + unsigned char *p = lfb + x*4 + y * fix_screeninfo.line_length; #if !HAVE_TRIPLEDRAGON unsigned int col = bgra[color][3] << 24 | bgra[color][2] << 16 | bgra[color][1] << 8 | bgra[color][0]; #else @@ -76,7 +54,6 @@ void FillRect(int x, int y, int w, int h, int color) } } - void FillBorder(int color) { int ys = (var_screeninfo.yres-var_screeninfo.yoffset); @@ -202,9 +179,6 @@ int toptext_getnext(int startpage, int up, int findgroup) nextgrp = nextblk = 0; current = startpage; - if (startpage == 0) - return 0; - do { if (up) tuxtxt_next_dec(¤t); @@ -245,13 +219,6 @@ void RenderClearMenuLineBB(char *p, tstPageAttr *attrcol, tstPageAttr *attr) #if 0 RenderCharBB(' ', attr); /* separator */ #endif - /* the fontwidth_topmenusmall is not correctly calculated: the navigation - * indicator ' ' is not considered and thus the font is slightly too wide. - * Shift the topmenu to the left instead of using a smaller font, since - * the worst that can happen is that the indicator is partly obscured and - * that looks better than empty space on the right of the topmenu. - */ - PosX = screen_x + screen_w - TOPMENUCHARS * fontwidth_topmenusmall; for(col = 0; col < TOPMENUCHARS; col++) { RenderCharBB(*p++, attr); @@ -274,8 +241,7 @@ void ClearFB(int /*color*/) //never used void ClearB(int color) { - FillRect(0, 0, var_screeninfo.xres, var_screeninfo.yres, color); /* framebuffer */ - FillRect(0, var_screeninfo.yres, var_screeninfo.xres, var_screeninfo.yres, color); /* backbuffer */ + FillRect(0,0,var_screeninfo.xres,var_screeninfo.yres*2,color); } #endif int GetCurFontWidth() @@ -283,7 +249,6 @@ int GetCurFontWidth() int mx = (displaywidth)%(40-nofirst); // # of unused pixels int abx = (mx == 0 ? displaywidth+1 : (displaywidth)/(mx+1));// distance between 'inserted' pixels int nx= abx+1-((PosX-sx) % (abx+1)); // # of pixels to next insert - return fontwidth+(((PosX+fontwidth+1-sx) <= displaywidth && nx <= fontwidth+1) ? 1 : 0); } @@ -1568,7 +1533,7 @@ static void* reader_thread(void * /*arg*/) void tuxtx_pause_subtitle(bool pause) { if(!pause) { - //printf("TuxTxt subtitle unpause, running %d pid %d page %d\n", reader_running, sub_pid, sub_page); + printf("TuxTxt subtitle unpause, running %d pid %d page %d\n", reader_running, sub_pid, sub_page); ttx_paused = 0; if(!reader_running && sub_pid && sub_page) tuxtx_main(0, sub_pid, sub_page); @@ -1605,8 +1570,8 @@ void tuxtx_set_pid(int pid, int page, const char * cc) sub_page = page; cfg_national_subset = GetNationalSubset(cc); -#if 0 printf("TuxTxt subtitle set pid %d page %d lang %s (%d)\n", sub_pid, sub_page, cc, cfg_national_subset); +#if 0 ttx_paused = 1; if(sub_pid && sub_page) tuxtx_main(0, sub_pid, sub_page); @@ -1630,7 +1595,7 @@ int tuxtx_subtitle_running(int *pid, int *page, int *running) return ret; } -int tuxtx_main(int /*_rc*/, int pid, int page, int source) +int tuxtx_main(int _rc, int pid, int page, int source) { char cvs_revision[] = "$Revision: 1.95 $"; @@ -1654,18 +1619,14 @@ int tuxtx_main(int /*_rc*/, int pid, int page, int source) printf("TuxTxt %s\n", versioninfo); printf("for 32bpp framebuffer\n"); - fb = -1; -#ifdef USE_FBPAN if ((fb=open("/dev/fb/0", O_RDWR)) == -1) { perror("TuxTxt "); return 0; } -#endif - CFrameBuffer *fbp = CFrameBuffer::getInstance(); - lfb = (unsigned char *)fbp->getFrameBufferPointer(); - lbb = (unsigned char *)fbp->getBackBufferPointer(); + rc = _rc; + lfb = (unsigned char *) CFrameBuffer::getInstance()->getFrameBufferPointer(); tuxtxt_cache.vtxtpid = pid; @@ -1674,7 +1635,8 @@ int tuxtx_main(int /*_rc*/, int pid, int page, int source) else printf("[tuxtxt] using PID %x page %d\n", tuxtxt_cache.vtxtpid, tuxtxt_cache.page); -#if 0 /* just get it from the framebuffer class */ + fcntl(rc, F_SETFL, fcntl(rc, F_GETFL) | O_EXCL | O_NONBLOCK); + /* get fixed screeninfo */ if (ioctl(fb, FBIOGET_FSCREENINFO, &fix_screeninfo) == -1) { @@ -1688,12 +1650,7 @@ int tuxtx_main(int /*_rc*/, int pid, int page, int source) perror("TuxTxt "); return 0; } -#else - struct fb_var_screeninfo *var; - var = fbp->getScreenInfo(); - memcpy(&var_screeninfo, var, sizeof(struct fb_var_screeninfo)); - fix_screeninfo.line_length = var_screeninfo.xres * sizeof(fb_pixel_t); -#endif + /* set variable screeninfo for double buffering */ var_screeninfo.yoffset = 0; #if 0 @@ -1702,15 +1659,10 @@ int tuxtx_main(int /*_rc*/, int pid, int page, int source) ex = x + w - 10; ey = y + h - 10; #endif - screen_x = fbp->getScreenX(); - screen_y = fbp->getScreenY(); - screen_w = fbp->getScreenWidth(); - screen_h = fbp->getScreenHeight(); - - int x = screen_x; - int y = screen_y; - int w = screen_w; - int h = screen_h; + int x = CFrameBuffer::getInstance()->getScreenX(); + int y = CFrameBuffer::getInstance()->getScreenY(); + int w = CFrameBuffer::getInstance()->getScreenWidth(); + int h = CFrameBuffer::getInstance()->getScreenHeight(); int tx = 0; if (!screen_mode1) @@ -1771,7 +1723,6 @@ int tuxtx_main(int /*_rc*/, int pid, int page, int source) SwitchTranspMode(); break; /* and evaluate key */ - case RC_TTTV: case RC_MUTE: /* regular toggle to transparent */ case RC_TEXT: break; @@ -1844,25 +1795,20 @@ int tuxtx_main(int /*_rc*/, int pid, int page, int source) case RC_7: case RC_8: case RC_9: - PageInput(CRCInput::getNumericValue(RCCode)); + PageInput(RCCode - RC_0); break; case RC_RED: ColorKey(prev_100); break; case RC_GREEN: ColorKey(prev_10); break; case RC_YELLOW: ColorKey(next_10); break; case RC_BLUE: ColorKey(next_100); break; - case RC_TTZOOM: case RC_PLUS: SwitchZoomMode(); break; - case RC_SPLIT: case RC_MINUS: SwitchScreenMode(-1);prevscreenmode = screenmode; break; - case RC_TTTV: case RC_MUTE: SwitchTranspMode(); break; case RC_TEXT: if(transpmode == 1) RCCode = RC_HOME; SwitchTranspMode(); break; - case RC_TTREVEAL: - case RC_INFO: case RC_HELP: SwitchHintMode(); break; case RC_DBOX: ConfigMenu(0); break; case RC_HOME: @@ -1879,8 +1825,7 @@ int tuxtx_main(int /*_rc*/, int pid, int page, int source) /* exit */ CleanUp(); - if (fb >= 0) - close(fb); + close(fb); #if 1 if ( initialized ) @@ -1916,10 +1861,10 @@ FT_Error MyFaceRequester(FTC_FaceID face_id, FT_Library plibrary, FT_Pointer /*r ******************************************************************************/ extern std::string ttx_font_file; static bool ft_init_done = false; -static int oldfontheight = 0; int Init(int source) { int error, i; + unsigned char magazine; static std::string font_file; /* init data */ @@ -1927,13 +1872,12 @@ int Init(int source) //page_atrb[32] = transp<<4 | transp; inputcounter = 2; -#if TUXTXT_CFG_STANDALONE - unsigned char magazine; for (magazine = 1; magazine < 9; magazine++) { tuxtxt_cache.current_page [magazine] = -1; tuxtxt_cache.current_subpage [magazine] = -1; } +#if TUXTXT_CFG_STANDALONE /* init data */ memset(&tuxtxt_cache.astCachetable, 0, sizeof(tuxtxt_cache.astCachetable)); memset(&tuxtxt_cache.subpagetable, 0xFF, sizeof(tuxtxt_cache.subpagetable)); @@ -2083,7 +2027,7 @@ int Init(int source) fontwidth_topmenumain = (TV43STARTX-sx) / 40; fontwidth_topmenusmall = (TVENDX - TOPMENUSTARTX) / TOPMENUCHARS; //fontwidth_small = (TV169FULLSTARTX-sx) / 40; - fontwidth_small = (screen_w / 2) / 40; + fontwidth_small = (CFrameBuffer::getInstance()->getScreenWidth()/2) / 40; ymosaic[0] = 0; /* y-offsets for 2*3 mosaic */ ymosaic[1] = (fontheight + 1) / 3; ymosaic[2] = (fontheight * 2 + 1) / 3; @@ -2125,7 +2069,7 @@ int Init(int source) } } #endif - if(!ft_init_done || font_file != ttx_font_file || fontheight != oldfontheight) { + if(!ft_init_done || font_file != ttx_font_file) { printf("TuxTxt: init fontlibrary\n"); if(ft_init_done) { FTC_Manager_Done(manager); @@ -2175,7 +2119,6 @@ int Init(int source) } font_file = ttx_font_file; ft_init_done = true; - oldfontheight = fontheight; ascender = (usettf ? fontheight * face->ascender / face->units_per_EM : 16); } @@ -2248,6 +2191,7 @@ int Init(int source) #else tuxtxt_start(tuxtxt_cache.vtxtpid, source); #endif + fcntl(rc, F_SETFL, O_NONBLOCK); gethotlist(); if(use_gui) @@ -2841,7 +2785,7 @@ void Menu_Init(char *menu, int current_pid, int menuitem, int hotindex) void ConfigMenu(int Init) { - int menuitem = M_Start; + int val, menuitem = M_Start; int current_pid = 0; int hotindex; int oldscreenmode, oldtrans = 0; @@ -2895,18 +2839,23 @@ void ConfigMenu(int Init) clearbbcolor = black; Menu_Init(menu, current_pid, menuitem, hotindex); + /* set blocking mode */ + val = fcntl(rc, F_GETFL); + fcntl(rc, F_SETFL, val &~ O_NONBLOCK); + /* loop */ do { if (GetRCCode() == 1) { - int rc_num = -1; - if (CRCInput::isNumeric(RCCode)) - rc_num = CRCInput::getNumericValue(RCCode) -1; /* valid: 1 to M_MaxDirect */ - if (rc_num >= 0 && rc_num <= M_MaxDirect) /* direct access */ + if ( +#if (RC_1 > 0) + RCCode >= RC_1 && /* generates a warning... */ +#endif + RCCode <= RC_1+M_MaxDirect) /* direct access */ { Menu_HighlightLine(menu, MenuLine[menuitem], 0); - menuitem = rc_num; + menuitem = RCCode-RC_1; Menu_HighlightLine(menu, MenuLine[menuitem], 1); if (menuitem != M_PID) /* just select */ @@ -3367,6 +3316,7 @@ void ConfigMenu(int Init) current_service = current_pid; // RenderMessage(ShowServiceName); + fcntl(rc, F_SETFL, O_NONBLOCK); RCCode = -1; if (oldscreenmode) SwitchScreenMode(oldscreenmode); /* restore divided screen */ @@ -3427,6 +3377,8 @@ void ConfigMenu(int Init) ClearBB(transp); CopyBB2FB(); + /* reset to nonblocking mode */ + fcntl(rc, F_SETFL, O_NONBLOCK); tuxtxt_cache.pageupdate = 1; RCCode = -1; if (oldscreenmode) @@ -3641,7 +3593,7 @@ void ColorKey(int target) void PageCatching() { - int byte; + int val, byte; int oldzoommode = zoommode; pagecatching = 1; @@ -3671,6 +3623,10 @@ void PageCatching() return; } + /* set blocking mode */ + val = fcntl(rc, F_GETFL); + fcntl(rc, F_SETFL, val &~ O_NONBLOCK); + /* loop */ do { GetRCCode(); @@ -3709,6 +3665,7 @@ void PageCatching() case RC_HOME: case RC_HELP: case RC_MUTE: + fcntl(rc, F_SETFL, O_NONBLOCK); tuxtxt_cache.pageupdate = 1; pagecatching = 0; RCCode = -1; @@ -3732,6 +3689,9 @@ void PageCatching() tuxtxt_cache.subpage = subp; else tuxtxt_cache.subpage = 0; + + /* reset to nonblocking mode */ + fcntl(rc, F_SETFL, O_NONBLOCK); } /****************************************************************************** @@ -3963,9 +3923,9 @@ void SwitchScreenMode(int newscreenmode) if (screenmode==1) /* split with topmenu */ { - int x = screen_x; - int w = screen_w; - int h = screen_h; + int x = CFrameBuffer::getInstance()->getScreenX(); + int w = CFrameBuffer::getInstance()->getScreenWidth(); + int h = CFrameBuffer::getInstance()->getScreenHeight(); fw = fontwidth_topmenumain; tx = 0; /* split means we start at the left edge */ @@ -3992,20 +3952,18 @@ void SwitchScreenMode(int newscreenmode) } else /* 2: split with full height tv picture */ { - StartX = screen_x; + StartX = CFrameBuffer::getInstance()->getScreenX(); fw = fontwidth_small; tx = TV169FULLSTARTX; ty = TV169FULLSTARTY; tw = TV169FULLWIDTH; th = TV169FULLHEIGHT; - displaywidth = screen_w / 2; + displaywidth = CFrameBuffer::getInstance()->getScreenWidth()/2; } setfontwidth(fw); - CFrameBuffer *f = CFrameBuffer::getInstance(); - videoDecoder->Pig(tx, ty, tw, th, - f->getScreenWidth(true), f->getScreenHeight(true)); + videoDecoder->Pig(tx, ty, tw, th, CFrameBuffer::getInstance()->getScreenWidth(true), CFrameBuffer::getInstance()->getScreenHeight(true)); #if 0 int sm = 0; ioctl(pig, VIDIOC_OVERLAY, &sm); @@ -4027,8 +3985,8 @@ void SwitchScreenMode(int newscreenmode) #endif videoDecoder->Pig(-1, -1, -1, -1); - int x = screen_x; - int w = screen_w; + int x = CFrameBuffer::getInstance()->getScreenX(); + int w = CFrameBuffer::getInstance()->getScreenWidth(); //int h = CFrameBuffer::getInstance()->getScreenHeight(); int tx = 0; /* see comment above on the TTX window dimensions */ @@ -4171,9 +4129,7 @@ void RenderDRCS( //FIX ME void DrawVLine(int x, int y, int l, int color) { - unsigned char *p = getFBp(&y); - MARK_FB(x, y, 0, l); - p += x*4 + y * fix_screeninfo.line_length; + unsigned char *p = lfb + x*4 + y * fix_screeninfo.line_length; for ( ; l > 0 ; l--) { @@ -4185,13 +4141,11 @@ void DrawVLine(int x, int y, int l, int color) void DrawHLine(int x, int y, int l, int color) { int ltmp; - unsigned char *p = getFBp(&y); - MARK_FB(x, y, l, 0); if (l > 0) { for (ltmp=0; ltmp <= l; ltmp++) { - memmove(p + x*4 + ltmp*4 + y * fix_screeninfo.line_length, bgra[color], 4); + memmove(lfb + x*4 + ltmp*4 + y * fix_screeninfo.line_length, bgra[color], 4); } } } @@ -4207,10 +4161,7 @@ void FillRectMosaicSeparated(int x, int y, int w, int h, int fgcolor, int bgcolo void FillTrapez(int x0, int y0, int l0, int xoffset1, int h, int l1, int color) { - unsigned char *p = getFBp(&y0); - MARK_FB(x0, y0, l0, h); - p += x0 * 4 + y0 * fix_screeninfo.line_length; - + unsigned char *p = lfb + x0*4 + y0 * fix_screeninfo.line_length; int xoffset, l; int yoffset; int ltmp; @@ -4232,10 +4183,7 @@ void FillTrapez(int x0, int y0, int l0, int xoffset1, int h, int l1, int color) void FlipHorz(int x, int y, int w, int h) { unsigned char *buf= new unsigned char[w*4]; - unsigned char *p = getFBp(&y); - MARK_FB(x, y, w, h); - p += x * 4 + y * fix_screeninfo.line_length; - + unsigned char *p = lfb + x*4 + y * fix_screeninfo.line_length; int w1,h1; if(buf != NULL){ for (h1 = 0 ; h1 < h ; h1++) @@ -4253,11 +4201,7 @@ void FlipHorz(int x, int y, int w, int h) void FlipVert(int x, int y, int w, int h) { unsigned char *buf= new unsigned char[w*4]; - unsigned char *p1, *p2; - unsigned char *p = getFBp(&y); - MARK_FB(x, y, w, h); - p += x*4 + y * fix_screeninfo.line_length; - + unsigned char *p = lfb + x*4 + y * fix_screeninfo.line_length, *p1, *p2; int h1; if(buf != NULL){ for (h1 = 0 ; h1 < h/2 ; h1++) @@ -4518,11 +4462,7 @@ void RenderChar(int Char, tstPageAttr *Attribute, int zoom, int yoffset) else if (*aShapes[Char - 0x20] == S_ADT) { int x,y,f,c; - y = yoffset; - unsigned char *p = getFBp(&y); - MARK_FB(PosX, PosY, curfontwidth, fontheight); - p += PosX * 4 + PosY * fix_screeninfo.line_length; - + unsigned char* p = lfb + PosX*4 + (PosY+yoffset)* fix_screeninfo.line_length; for (y=0; ytop + TTFShiftY + sbit->height > fontheight) sbit->height = fontheight - ascender + sbit->top - TTFShiftY; /* limit char height to defined/calculated fontheight */ - int y = yoffset; - p = getFBp(&y); - p += PosX * 4 + (PosY + Row) * fix_screeninfo.line_length; /* running pointer into framebuffer */ + p = lfb + PosX*4 + (yoffset + PosY + Row) * fix_screeninfo.line_length; /* running pointer into framebuffer */ for (Row = sbit->height; Row; Row--) /* row counts up, but down may be a little faster :) */ { int pixtodo = (usettf ? sbit->width : curfontwidth); @@ -5179,8 +5115,8 @@ void DoFlashing(int startrow) } PosY += fontheight*factor; } -} +} void RenderPage() { int row, col, byte, startrow = 0;; @@ -5251,7 +5187,7 @@ void RenderPage() fontwidth_topmenumain = (TV43STARTX-sx) / (40-nofirst); fontwidth_topmenusmall = (TVENDX - TOPMENUSTARTX) / TOPMENUCHARS; //fontwidth_small = (TV169FULLSTARTX-sx) / (40-nofirst); - fontwidth_small = (screen_w / 2) / (40 - nofirst); + fontwidth_small = (CFrameBuffer::getInstance()->getScreenWidth()/2) / (40-nofirst); switch(screenmode) { case 0: @@ -5259,7 +5195,7 @@ void RenderPage() displaywidth = ex - sx; break; case 2: setfontwidth(fontwidth_small); - displaywidth = screen_w / 2; + displaywidth = CFrameBuffer::getInstance()->getScreenWidth() / 2; break; } if (transpmode || (boxed && !screenmode)) @@ -5502,7 +5438,7 @@ void CreateLine25() showlink(3, next_100); } - if (tuxtxt_cache.bttok && + if (//tuxtxt_cache.bttok && screenmode == 1) /* TOP-Info present, divided screen -> create TOP overview */ { char line[TOPMENUCHARS]; @@ -5612,9 +5548,6 @@ void CopyBB2FB() { unsigned char *src, *dst, *topsrc; int fillcolor, i, screenwidth, swtmp; -#ifdef HAVE_SPARK_HARDWARE - CFrameBuffer *f = CFrameBuffer::getInstance(); -#endif /* line 25 */ if (!pagecatching && use_gui) @@ -5635,16 +5568,12 @@ void CopyBB2FB() if (ioctl(fb, FBIOPAN_DISPLAY, &var_screeninfo) == -1) perror("TuxTxt "); #else -#ifdef HAVE_SPARK_HARDWARE - f->blit2FB(lbb, var_screeninfo.xres, var_screeninfo.yres, 0, 0, 0, 0, true); -#else - memcpy(lfb, lbb, fix_screeninfo.line_length*var_screeninfo.yres); -#endif + memmove(lfb, lfb+fix_screeninfo.line_length * var_screeninfo.yres, fix_screeninfo.line_length*var_screeninfo.yres); #endif /* adapt background of backbuffer if changed */ - if (StartX > 0 && *lfb != *lbb) { - FillBorder(*lbb); + if (StartX > 0 && *lfb != *(lfb + fix_screeninfo.line_length * var_screeninfo.yres)) { + FillBorder(*(lfb + fix_screeninfo.line_length * var_screeninfo.yoffset)); // ClearBB(*(lfb + var_screeninfo.xres * var_screeninfo.yoffset)); } @@ -5656,11 +5585,8 @@ void CopyBB2FB() return; } - src = topsrc = lbb + StartY * fix_screeninfo.line_length; - dst = lfb + StartY * fix_screeninfo.line_length; + src = dst = topsrc = lfb + StartY*fix_screeninfo.line_length; -#ifdef USE_FBPAN - #error USE_FBPAN code is not working right now. if (var_screeninfo.yoffset) dst += fix_screeninfo.line_length * var_screeninfo.yres; else @@ -5668,7 +5594,6 @@ void CopyBB2FB() src += fix_screeninfo.line_length * var_screeninfo.yres; topsrc += fix_screeninfo.line_length * var_screeninfo.yres; } -#endif /* copy line25 in normal height */ if (!pagecatching ) memmove(dst+(24*fontheight)*fix_screeninfo.line_length, src + (24*fontheight)*fix_screeninfo.line_length, fix_screeninfo.line_length*fontheight); @@ -5684,15 +5609,9 @@ void CopyBB2FB() /* copy topmenu in normal height (since PIG also keeps dimensions) */ if (screenmode == 1) { - screenwidth = ( TV43STARTX ) * 4; -#ifdef HAVE_SPARK_HARDWARE - int cx = var_screeninfo.xres - TV43STARTX; /* x start */ - int cw = TV43STARTX; /* width */ - int cy = StartY; - int ch = 24*fontheight; - f->blit2FB(lbb, cw, ch, cx, cy, cx, cy, true); -#else unsigned char *topdst = dst; + + screenwidth = ( TV43STARTX ) * 4; size_t width = ex * sizeof(fb_pixel_t) - screenwidth; topsrc += screenwidth; @@ -5703,7 +5622,6 @@ void CopyBB2FB() topdst += fix_screeninfo.line_length; topsrc += fix_screeninfo.line_length; } -#endif } else if (screenmode == 2) screenwidth = ( TV169FULLSTARTX ) * 4; @@ -5734,9 +5652,6 @@ void CopyBB2FB() memmove(dst + fix_screeninfo.line_length*(fontheight+i)+swtmp*4, bgra[fillcolor], 4); } } -#ifdef HAVE_SPARK_HARDWARE - f->mark(0, 0, var_screeninfo.xres, var_screeninfo.yres); -#endif } /****************************************************************************** @@ -6426,21 +6341,6 @@ void DecodePage() /****************************************************************************** * GetRCCode * ******************************************************************************/ -int GetRCCode() -{ - neutrino_msg_t msg; - neutrino_msg_data_t data; - g_RCInput->getMsg_ms(&msg, &data, 40); - RCCode = -1; - - if (msg <= CRCInput::RC_MaxRC) { - RCCode = msg; - return 1; - } - return 0; -} - -#if 0 #if 1 int GetRCCode() { @@ -6514,7 +6414,7 @@ printf("[tuxtxt] new key, code %X\n", RCCode); } RCCode = -1; - usleep(1000000/25); + usleep(1000000/100); return 0; } @@ -6579,7 +6479,6 @@ int GetRCCode() return 1; } #endif -#endif /* Local Variables: */ /* indent-tabs-mode:t */ /* tab-width:3 */ diff --git a/lib/libtuxtxt/tuxtxt.h b/lib/libtuxtxt/tuxtxt.h index 1a6974c86..4781fe644 100644 --- a/lib/libtuxtxt/tuxtxt.h +++ b/lib/libtuxtxt/tuxtxt.h @@ -1,3 +1,11 @@ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if !HAVE_COOL_HARDWARE +#include +#else #ifndef __tuxtxt_h__ #define __tuxtxt_h__ @@ -12,8 +20,6 @@ * ported 2006 to Dreambox 7025 / 32Bit framebuffer * * by Seddi * * * - * * - * ported to Tripledragon, SPARK and AZbox 2010-2013 Stefan Seyfried * ******************************************************************************/ #define TUXTXT_CFG_STANDALONE 0 // 1:plugin only 0:use library @@ -44,8 +50,6 @@ #include FT_CACHE_H #include FT_CACHE_SMALL_BITMAPS_H -#include - /* devices */ #if TUXTXT_CFG_STANDALONE @@ -86,19 +90,20 @@ int tv_pip_y; #define fontwidth_small_lcd 8 #define TV43STARTX (ex) -#define TVENDX (screen_x + screen_w) //ex +#define TVENDX (CFrameBuffer::getInstance()->getScreenX() + CFrameBuffer::getInstance()->getScreenWidth()) //ex // #define TVENDY (StartY + 25*fontheight) // #define TV43WIDTH (TVENDX - TV43STARTX) // #define TV43HEIGHT (TV43WIDTH *9/16) // #define TV43STARTY (TVENDY - TV43HEIGHT) //#define TV169FULLSTARTX (sx+ 8*40) //(sx +(ex +1 - sx)/2) -#define TV169FULLSTARTX (screen_x + screen_w / 2) +#define TV169FULLSTARTX (CFrameBuffer::getInstance()->getScreenX() + CFrameBuffer::getInstance()->getScreenWidth()/2) #define TV169FULLSTARTY sy //#define TV169FULLWIDTH (ex - sx)/2 -#define TV169FULLWIDTH (screen_w / 2) +#define TV169FULLWIDTH (CFrameBuffer::getInstance()->getScreenWidth()/2) #define TV169FULLHEIGHT (ey - sy) -#define TOPMENUSTARTX (TV43STARTX+2) + +#define TOPMENUSTARTX TV43STARTX+2 //#define TOPMENUENDX TVENDX #define TOPMENUSTARTY StartY #define TOPMENUENDY TV43STARTY @@ -108,7 +113,7 @@ int tv_pip_y; #define TOPMENUINDENTGRP 1 #define TOPMENUINDENTDEF 2 #define TOPMENUSPC 0 -#define TOPMENUCHARS (TOPMENUINDENTDEF+12+TOPMENUSPC+3) +#define TOPMENUCHARS (TOPMENUINDENTDEF+12+TOPMENUSPC+4) #define FLOFSIZE 4 @@ -146,7 +151,6 @@ int tv_pip_y; #define hold_mosaic 0x1E #define release_mosaic 0x1F -#if 0 /* rc codes */ #define RC_0 0x00 #define RC_1 0x01 @@ -175,48 +179,6 @@ int tv_pip_y; #define RC_DBOX 0x18 #define RC_TEXT 0x19 #define RC_HOME 0x1F -#else -#define RC_0 CRCInput::RC_0 -#define RC_1 CRCInput::RC_1 -#define RC_2 CRCInput::RC_2 -#define RC_3 CRCInput::RC_3 -#define RC_4 CRCInput::RC_4 -#define RC_5 CRCInput::RC_5 -#define RC_6 CRCInput::RC_6 -#define RC_7 CRCInput::RC_7 -#define RC_8 CRCInput::RC_8 -#define RC_9 CRCInput::RC_9 -#define RC_RIGHT CRCInput::RC_right -#define RC_LEFT CRCInput::RC_left -#define RC_UP CRCInput::RC_up -#define RC_DOWN CRCInput::RC_down -#define RC_OK CRCInput::RC_ok -#define RC_MUTE CRCInput::RC_spkr -#define RC_STANDBY CRCInput::RC_standby -#define RC_GREEN CRCInput::RC_green -#define RC_YELLOW CRCInput::RC_yellow -#define RC_RED CRCInput::RC_red -#define RC_BLUE CRCInput::RC_blue -#define RC_PLUS CRCInput::RC_plus -#define RC_MINUS CRCInput::RC_minus -#define RC_HELP CRCInput::RC_help -#define RC_INFO CRCInput::RC_info -#define RC_DBOX CRCInput::RC_setup -#define RC_HOME CRCInput::RC_home -#define RC_TTTV CRCInput::RC_tttv -#define RC_TTZOOM CRCInput::RC_ttzoom -#define RC_TTREVEAL CRCInput::RC_ttreveal -#if HAVE_TRIPLEDRAGON -/* td has more keys so use ttx key for switching split mode... */ -#define RC_SPLIT CRCInput::RC_text -/* rc_text is now unused */ -#define RC_TEXT (CRCInput::RC_MaxRC + 1) -#else -/* ...while other receivers use the vol- key for that, so rc_split is unused */ -#define RC_SPLIT (CRCInput::RC_MaxRC + 1) -#define RC_TEXT CRCInput::RC_text -#endif -#endif typedef enum /* object type */ { @@ -248,7 +210,6 @@ const char *ObjectType[] = /* framebuffer stuff */ static unsigned char *lfb = 0; -static unsigned char *lbb = 0; struct fb_var_screeninfo var_screeninfo; struct fb_fix_screeninfo fix_screeninfo; @@ -592,7 +553,7 @@ char versioninfo[16]; int hotlist[10]; int maxhotlist; -int pig, fb, lcd; +int pig, rc, fb, lcd; int sx, ex, sy, ey; int PosX, PosY, StartX, StartY; int lastpage; @@ -624,7 +585,7 @@ int subtitledelay, delaystarted; FILE *conf; -neutrino_msg_t RCCode; +unsigned short RCCode; struct _pid_table { @@ -749,11 +710,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = "ã Bildschirmformat äé" "ã3 Standard-Modus 16:9 äé" "ã äé" - "ã4 Helligkeit äé" + "ã5 Helligkeit äé" "ãí îäé" - "ã5 Transparenz äé" + "ã6 Transparenz äé" "ãí îäé" - "ã6 nationaler Zeichensatz äé" + "ã7 nationaler Zeichensatz äé" "ãautomatische Erkennung äé" "ãí îäé" "ãí Sprache/Language deutsch îäé" @@ -776,11 +737,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = "ã Screen format äé" "ã3 Standard mode 16:9 äé" "ã äé" - "ã4 Brightness äé" + "ã5 Brightness äé" "ãí îäé" - "ã5 Transparency äé" + "ã6 Transparency äé" "ãí îäé" - "ã6 national characterset äé" + "ã7 national characterset äé" "ã automatic recognition äé" "ãí îäé" "ãí Sprache/language english îäé" @@ -803,11 +764,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = "ã Format de l'#cran äé" "ã3 Mode standard 16:9 äé" "ã äé" - "ã4 Clarte äé" + "ã5 Clarte äé" "ãí îäé" - "ã5 Transparence äé" + "ã6 Transparence äé" "ãí îäé" - "ã6 police nationale äé" + "ã7 police nationale äé" "ãreconn. automatique äé" "ãí îäé" "ãí Sprache/language francaisîäé" @@ -830,11 +791,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = "ã Beeldschermformaat äé" "ã3 Standaardmode 16:9 äé" "ã äé" - "ã4 Helderheid äé" + "ã5 Helderheid äé" "ãí îäé" - "ã5 Transparantie äé" + "ã6 Transparantie äé" "ãí îäé" - "ã6 nationale tekenset äé" + "ã7 nationale tekenset äé" "ãautomatische herkenning äé" "ãí îäé" "ãí Sprache/Language nederl. îäé" @@ -857,11 +818,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = "ã Loqv^ oh|mgr äé" "ã3 Tq|por pq|tupor 16:9 äé" "ã äé" - "ã4 Kalpq|tgta äé" + "ã5 Kalpq|tgta äé" "ãí îäé" - "ã5 Diav\\meia äé" + "ã6 Diav\\meia äé" "ãí îäé" - "ã6 Ehmij^ tuposeiq\\ äé" + "ã7 Ehmij^ tuposeiq\\ äé" "ãaut|latg amacm~qisg äé" "ãí îäé" "ãí Ck~ssa/Language ekkgmij\\ îäé" @@ -884,11 +845,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = "ã Formato schermo äé" "ã3 Modo standard 16:9 äé" "ã äé" - "ã4 Luminosit{ äé" + "ã5 Luminosit{ äé" "ãí îäé" - "ã5 Trasparenza äé" + "ã6 Trasparenza äé" "ãí îäé" - "ã6 nazionalita'caratteri äé" + "ã7 nazionalita'caratteri äé" "ã riconoscimento automatico äé" "ãí îäé" "ãí Lingua/Language Italiana îäé" @@ -911,11 +872,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = "ã Format obrazu äé" "ã3 Tryb standard 16:9 äé" "ã äé" - "ã4 Jasno|^ äé" + "ã5 Jasno|^ äé" "ãí îäé" - "ã5 Prze~roczysto|^ äé" + "ã6 Prze~roczysto|^ äé" "ãí îäé" - "ã6 Znaki charakterystyczne äé" + "ã7 Znaki charakterystyczne äé" "ã automatyczne rozpozn. äé" "ãí îäé" "ãí J`zyk/Language polski îäé" @@ -938,11 +899,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = "ã TV- format äé" "ã3 Standard l{ge 16:9 äé" "ã äé" - "ã4 Ljusstyrka äé" + "ã5 Ljusstyrka äé" "ãí îäé" - "ã5 Genomskinlighet äé" + "ã6 Genomskinlighet äé" "ãí îäé" - "ã6nationell teckenupps{ttningäé" + "ã7nationell teckenupps{ttningäé" "ã automatisk igenk{nning äé" "ãí îäé" "ãí Sprache/language svenska îäé" @@ -965,11 +926,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = "ã N{ytt|tila äé" "ã3 Vakiotila 16:9 äé" "ã äé" - "ã4 Kirkkaus äé" + "ã5 Kirkkaus äé" "ãí îäé" - "ã5 L{pin{kyvyys äé" + "ã6 L{pin{kyvyys äé" "ãí îäé" - "ã6 kansallinen merkist| äé" + "ã7 kansallinen merkist| äé" "ã automaattinen tunnistus äé" "ãí îäé" "ãí Kieli suomi îäé" @@ -992,11 +953,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = "ã formato ecran äé" "ã3 Standard mode 16:9 äé" "ã äé" - "ã4 Brilho äé" + "ã5 Brilho äé" "ãí îäé" - "ã5 Transparencia äé" + "ã6 Transparencia äé" "ãí îäé" - "ã6 Caracteres nacionaist äé" + "ã7 Caracteres nacionaist äé" "ãreconhecimento utomatico äé" "ãí îäé" "ãí Lingua Portuguesa îäé" @@ -1019,11 +980,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = "ã Format kartinki äé" "ã3 Stand. revim 16:9 äé" "ã äé" - "ã4 Qrkostx äé" + "ã5 Qrkostx äé" "ãí îäé" - "ã5 Prozra~nostx äé" + "ã6 Prozra~nostx äé" "ãí îäé" - "ã6 Ispolxzuem&j alfawit äé" + "ã7 Ispolxzuem&j alfawit äé" "ã awtoopredelenie äé" "ãí îäé" "ãí Qz&k: Russkij îäé" @@ -1789,3 +1750,4 @@ void eval_object(int iONr, tstCachedPage *pstCachedPage, #endif +#endif diff --git a/lib/libtuxtxt/tuxtxt_common.h b/lib/libtuxtxt/tuxtxt_common.h index 7173aa641..bb1eb2fdc 100644 --- a/lib/libtuxtxt/tuxtxt_common.h +++ b/lib/libtuxtxt/tuxtxt_common.h @@ -1,6 +1,12 @@ -/* tuxtxt_common.h - * for license info see the other tuxtxt files - */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if !HAVE_COOL_HARDWARE +#include +#else + #include #include #include @@ -17,7 +23,6 @@ tuxtxt_cache_struct tuxtxt_cache; static pthread_mutex_t tuxtxt_cache_lock = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t tuxtxt_cache_biglock = PTHREAD_MUTEX_INITIALIZER; int tuxtxt_get_zipsize(int p,int sp) { tstCachedPage* pg = tuxtxt_cache.astCachetable[p][sp]; @@ -353,7 +358,6 @@ int tuxtxt_GetSubPage(int page, int subpage, int offset) void tuxtxt_clear_cache(void) { - pthread_mutex_lock(&tuxtxt_cache_biglock); pthread_mutex_lock(&tuxtxt_cache_lock); int clear_page, clear_subpage, d26; tuxtxt_cache.maxadippg = -1; @@ -417,7 +421,6 @@ void tuxtxt_clear_cache(void) printf("TuxTxt cache cleared\n"); #endif pthread_mutex_unlock(&tuxtxt_cache_lock); - pthread_mutex_unlock(&tuxtxt_cache_biglock); } /****************************************************************************** * init_demuxer * @@ -545,7 +548,6 @@ void tuxtxt_allocate_cache(int magazine) // Lock here as we have a possible race here with // tuxtxt_clear_cache(). We should not be allocating and // freeing at the same time. - // *** this is probably worked around by tuxtxt_cacehe_biglock now *** --seife pthread_mutex_lock(&tuxtxt_cache_lock); /* check cachetable and allocate memory if needed */ @@ -618,13 +620,6 @@ void *tuxtxt_CacheThread(void * /*arg*/) continue; } - /* this "big hammer lock" is a hack: it avoids a crash if - * tuxtxt_clear_cache() is called while the cache thread is in the - * middle of the following loop, leading to tuxtxt_cache.current_page[] - * etc. being set to -1 and tuxtxt_cache.astCachetable[] etc. being set - * to NULL - * it probably also avoids the possible race in tuxtxt_allocate_cache() */ - pthread_mutex_lock(&tuxtxt_cache_biglock); /* analyze it */ for (line = 0; line < readcnt/0x2e /*4*/; line++) { @@ -1066,7 +1061,6 @@ void *tuxtxt_CacheThread(void * /*arg*/) printf("line %d row %X %X, continue\n", line, vtx_rowbyte[0], vtx_rowbyte[1]); #endif } - pthread_mutex_unlock(&tuxtxt_cache_biglock); } pthread_exit(NULL); @@ -1144,3 +1138,4 @@ int tuxtxt_stop_thread() #endif return 1; } +#endif diff --git a/lib/libtuxtxt/tuxtxt_def.h b/lib/libtuxtxt/tuxtxt_def.h index 255db1f74..7b8e26242 100644 --- a/lib/libtuxtxt/tuxtxt_def.h +++ b/lib/libtuxtxt/tuxtxt_def.h @@ -1,3 +1,12 @@ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if !HAVE_COOL_HARDWARE +#include +#else + /****************************************************************************** * definitions for plugin and lib * ******************************************************************************/ @@ -368,3 +377,4 @@ signed int deh24(unsigned char *ph24) ((h24 & 0x7f0000) >> 5); } #endif /* table or serial */ +#endif diff --git a/lib/libtuxtxt_mp/Makefile.am b/lib/libtuxtxt_mp/Makefile.am new file mode 100644 index 000000000..c207800a3 --- /dev/null +++ b/lib/libtuxtxt_mp/Makefile.am @@ -0,0 +1,23 @@ +AM_CPPFLAGS = \ + -I$(top_builddir) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/lib/libconfigfile \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/zapit/include \ + $(FREETYPE_CFLAGS) + +AM_CPPFLAGS += @HWLIB_CFLAGS@ + +AM_CPPFLAGS += -fno-rtti -fno-exceptions + +noinst_LIBRARIES = libtuxtxt.a + +libtuxtxt_a_SOURCES = libtuxtxt.cpp tuxtxt.cpp + +configdir = $(CONFIGDIR)/tuxtxt +## not necessary - the defaults in the code are exactly like +## what is in the config file +#config_DATA = tuxtxt2.conf +## ... but we need the $(configdir)... hence the empty config_DATA... +config_DATA = diff --git a/lib/libtuxtxt_mp/libtuxtxt.cpp b/lib/libtuxtxt_mp/libtuxtxt.cpp new file mode 100644 index 000000000..40af36282 --- /dev/null +++ b/lib/libtuxtxt_mp/libtuxtxt.cpp @@ -0,0 +1,100 @@ +/****************************************************************************** + * <<< TuxTxt - Teletext Plugin >>> * + * * + * (c) Thomas "LazyT" Loewe 2002-2003 (LazyT@gmx.net) * + * * + * TOP-Text Support 2004 by Roland Meier * + * Info entnommen aus videotext-0.6.19991029, * + * Copyright (c) 1994-96 Martin Buck * + * * + ******************************************************************************/ + +#define TUXTXT_DEBUG 0 + +#include +#include + +#include "tuxtxt_def.h" +#include "tuxtxt_common.h" +int tuxtxt_stop(); +/****************************************************************************** + * Initialize * + ******************************************************************************/ + +static int tuxtxt_initialized=0; + +int tuxtxt_init() +{ + if ( tuxtxt_initialized ) + return 0; + + tuxtxt_initialized=1; + + /* init data */ + tuxtxt_stop(); + tuxtxt_clear_cache(); + tuxtxt_cache.thread_starting = 0; + tuxtxt_cache.vtxtpid = -1; + tuxtxt_cache.thread_id = 0; + tuxtxt_cache.dmx = -1; + /* not sure if this is correct here... */ + tuxtxt_cache.page = 0x100; + return 1;//tuxtxt_init_demuxer(); +} + +/****************************************************************************** + * Interface to caller * + ******************************************************************************/ + +int tuxtxt_stop() +{ + if (!tuxtxt_cache.receiving) return 1; + tuxtxt_cache.receiving = 0; + + return tuxtxt_stop_thread(); +} + +void tuxtxt_start(int tpid, int source) +{ + if (tpid == -1) + { + printf("tuxtxt: invalid PID!\n"); + return; + } + + if (tuxtxt_cache.vtxtpid != tpid) + { + tuxtxt_stop(); + tuxtxt_clear_cache(); + tuxtxt_cache.page = 0x100; + tuxtxt_cache.vtxtpid = tpid; + tuxtxt_start_thread(source); + } + else if (!tuxtxt_cache.thread_starting && !tuxtxt_cache.receiving) + { + tuxtxt_start_thread(source); + } +} + +void tuxtxt_close() +{ +#if TUXTXT_DEBUG + printf ("libtuxtxt: cleaning up\n"); +#endif + tuxtxt_stop(); +#if 0 + if (tuxtxt_cache.dmx != -1) + close(tuxtxt_cache.dmx); +#endif + tuxtxt_cache.dmx = -1; + tuxtxt_clear_cache(); + tuxtxt_initialized=0; +} + +/* Local Variables: */ +/* indent-tabs-mode:t */ +/* tab-width:3 */ +/* c-basic-offset:3 */ +/* comment-column:0 */ +/* fill-column:120 */ +/* End: */ diff --git a/lib/libtuxtxt_mp/teletext.h b/lib/libtuxtxt_mp/teletext.h new file mode 100644 index 000000000..6bc3dc590 --- /dev/null +++ b/lib/libtuxtxt_mp/teletext.h @@ -0,0 +1,14 @@ +#ifndef __teletext_h__ +#define __teletext_h__ + +int tuxtxt_init(); +void tuxtxt_close(); +void tuxtxt_start(int tpid, int source = 0); // Start caching +int tuxtxt_stop(); // Stop caching +int tuxtx_main(int _rc, int pid, int page = 0, int source = 0); +void tuxtx_stop_subtitle(); +int tuxtx_subtitle_running(int *pid, int *page, int *running); +void tuxtx_pause_subtitle(bool pause = 1); +void tuxtx_set_pid(int pid, int page, const char * cc); + +#endif diff --git a/lib/libtuxtxt_mp/tuxtxt.cpp b/lib/libtuxtxt_mp/tuxtxt.cpp new file mode 100644 index 000000000..31b2f1f34 --- /dev/null +++ b/lib/libtuxtxt_mp/tuxtxt.cpp @@ -0,0 +1,6589 @@ +/****************************************************************************** + * <<< TuxTxt - Teletext Plugin >>> * + * * + * (c) Thomas "LazyT" Loewe 2002-2003 (LazyT@gmx.net) * + * * + * continued 2004-2005 by Roland Meier * + * and DBLuelle * + * * + * ported 2006 to Dreambox 7025 / 32Bit framebuffer * + * by Seddi * + * * + * ported 2009 to HD1 by Coolstream LTD * + * * + * TD, SPARK and AZbox port (C) 2010-2013 Stefan Seyfried * + * * + ******************************************************************************/ + +#include "teletext.h" +#include "tuxtxt.h" +#include +#include +#include +#include +#include + +/* same as in rcinput.h... */ +#define KEY_TTTV KEY_FN_1 +#define KEY_TTZOOM KEY_FN_2 +#define KEY_REVEAL KEY_FN_D + +#ifdef HAVE_SPARK_HARDWARE +#define MARK_FB(a, b, c, d) if (p == lfb) CFrameBuffer::getInstance()->mark(a, b, (a) + (c), (b) + (d)) +#else +#define MARK_FB(a, b, c, d) +#endif + +extern cVideo * videoDecoder; + +static pthread_t ttx_sub_thread; +static int reader_running; +static int ttx_paused; +static int ttx_req_pause; +static int sub_pid, sub_page; +static bool use_gui; +static int cfg_national_subset; + +static int screen_x, screen_y, screen_w, screen_h; + +//#define USE_FBPAN // FBIOPAN_DISPLAY seems to be working in current driver + +unsigned char *getFBp(int *y) +{ + if (*y < (int)var_screeninfo.yres) + return lfb; + + *y -= var_screeninfo.yres; + return lbb; +} + +void FillRect(int x, int y, int w, int h, int color) +{ + unsigned char *p = getFBp(&y); + MARK_FB(x, y, w, h); + p += x*4 + y * fix_screeninfo.line_length; +#if !HAVE_TRIPLEDRAGON + unsigned int col = bgra[color][3] << 24 | bgra[color][2] << 16 | bgra[color][1] << 8 | bgra[color][0]; +#else + unsigned int col = *((unsigned int*)bgra[color]); +#endif + if (w > 0) + for (int count = 0; count < h; count++) { + unsigned int * dest0 = (unsigned int *)p; + for (int i = 0; i < w; i++) + *(dest0++) = col; + p += fix_screeninfo.line_length; + } +} + + +void FillBorder(int color) +{ + int ys = (var_screeninfo.yres-var_screeninfo.yoffset); + FillRect(0 , ys ,StartX ,var_screeninfo.yres ,color); + FillRect(StartX, ys ,displaywidth,StartY ,color); + FillRect(StartX, ys+StartY+25*fontheight,displaywidth,var_screeninfo.yres-(StartY+25*fontheight),color); + + if (screenmode == 0 ) + FillRect(StartX+displaywidth, ys,var_screeninfo.xres-(StartX+displaywidth),var_screeninfo.yres ,color); +} + +int getIndexOfPageInHotlist() +{ + int i; + for (i = 0; i <= maxhotlist; i++) + { + if (tuxtxt_cache.page == hotlist[i]) + return i; + } + return -1; +} + +void gethotlist() +{ + FILE *hl; + char line[100]; + + hotlistchanged = 0; + maxhotlist = -1; + sprintf(line, TUXTXTDIR "/hotlist%d.conf", tuxtxt_cache.vtxtpid); +#if TUXTXT_DEBUG + printf("TuxTxt = 0x100 && hotlist[maxhotlist+1] <= 0x899) + { +#if TUXTXT_DEBUG + printf(" %03x", hotlist[maxhotlist+1]); +#endif + maxhotlist++; + continue; + } + } +#if TUXTXT_DEBUG + else + printf(" ?%s?", line); +#endif + } while (maxhotlist < (int) (sizeof(hotlist)/sizeof(hotlist[0])-1)); + fclose(hl); + } +#if TUXTXT_DEBUG + printf(">\n"); +#endif + if (maxhotlist < 0) /* hotlist incorrect or not found */ + { + hotlist[0] = 0x100; /* create one */ + hotlist[1] = 0x303; + maxhotlist = 1; + } +} + +void savehotlist() +{ + FILE *hl; + char line[100]; + int i; + + hotlistchanged = 0; + sprintf(line, TUXTXTDIR "/hotlist%d.conf", tuxtxt_cache.vtxtpid); +#if TUXTXT_DEBUG + printf("TuxTxt \n"); +#endif +} + +#define number2char(c) ((c) + (((c) <= 9) ? '0' : ('A' - 10))) +/* print hex-number into string, s points to last digit, caller has to provide enough space, no termination */ +void hex2str(char *s, unsigned int n) +{ + do { + char c = (n & 0xF); + *s-- = number2char(c); + n >>= 4; + } while (n); +} + + +int toptext_getnext(int startpage, int up, int findgroup) +{ + int current, nextgrp, nextblk; + + int stoppage = (tuxtxt_is_dec(startpage) ? startpage : startpage & 0xF00); // avoid endless loop in hexmode + nextgrp = nextblk = 0; + current = startpage; + + if (startpage == 0) + return 0; + + do { + if (up) + tuxtxt_next_dec(¤t); + else + tuxtxt_prev_dec(¤t); + + if (!tuxtxt_cache.bttok || tuxtxt_cache.basictop[current]) /* only if existent */ + { + if (findgroup) + { + if (tuxtxt_cache.basictop[current] >= 6 && tuxtxt_cache.basictop[current] <= 7) + return current; + if (!nextgrp && (current&0x00F) == 0) + nextgrp = current; + } + if (tuxtxt_cache.basictop[current] >= 2 && tuxtxt_cache.basictop[current] <= 5) /* always find block */ + return current; + + if (!nextblk && (current&0x0FF) == 0) + nextblk = current; + } + } while (current != stoppage); + + if (nextgrp) + return nextgrp; + else if (nextblk) + return nextblk; + else + return startpage; +} + +void RenderClearMenuLineBB(char *p, tstPageAttr *attrcol, tstPageAttr *attr) +{ + int col; + + PosX = TOPMENUSTARTX; + RenderCharBB(' ', attrcol); /* indicator for navigation keys */ +#if 0 + RenderCharBB(' ', attr); /* separator */ +#endif + /* the fontwidth_topmenusmall is not correctly calculated: the navigation + * indicator ' ' is not considered and thus the font is slightly too wide. + * Shift the topmenu to the left instead of using a smaller font, since + * the worst that can happen is that the indicator is partly obscured and + * that looks better than empty space on the right of the topmenu. + */ + PosX = screen_x + screen_w - TOPMENUCHARS * fontwidth_topmenusmall; + for(col = 0; col < TOPMENUCHARS; col++) + { + RenderCharBB(*p++, attr); + } + PosY += fontheight; + memset(p-TOPMENUCHARS, ' ', TOPMENUCHARS); /* init with spaces */ +} + +void ClearBB(int color) +{ + FillRect(0, (var_screeninfo.yres - var_screeninfo.yoffset), var_screeninfo.xres, var_screeninfo.yres, color); +} + +void ClearFB(int /*color*/) +{ + //memset(lfb,0, var_screeninfo.yres*fix_screeninfo.line_length); + CFrameBuffer::getInstance()->paintBackground(); +} +#if 0 +//never used +void ClearB(int color) +{ + FillRect(0, 0, var_screeninfo.xres, var_screeninfo.yres, color); /* framebuffer */ + FillRect(0, var_screeninfo.yres, var_screeninfo.xres, var_screeninfo.yres, color); /* backbuffer */ +} +#endif +int GetCurFontWidth() +{ + int mx = (displaywidth)%(40-nofirst); // # of unused pixels + int abx = (mx == 0 ? displaywidth+1 : (displaywidth)/(mx+1));// distance between 'inserted' pixels + int nx= abx+1-((PosX-sx) % (abx+1)); // # of pixels to next insert + + return fontwidth+(((PosX+fontwidth+1-sx) <= displaywidth && nx <= fontwidth+1) ? 1 : 0); +} + +void SetPosX(int column) +{ + PosX = StartX; + int i; + for (i = 0; i < column-nofirst; i++) + PosX += GetCurFontWidth(); +} + +void setfontwidth(int newwidth) +{ + if (fontwidth != newwidth) + { + int i; + fontwidth = newwidth; + if (usettf) + typettf.width = (FT_UShort) fontwidth * TTFWidthFactor16 / 16; + else + { + if (newwidth < 11) + newwidth = 21; + else if (newwidth < 14) + newwidth = 22; + else + newwidth = 23; + typettf.width = typettf.height = (FT_UShort) newwidth; + } + for (i = 0; i <= 12; i++) + axdrcs[i] = (fontwidth * i + 6) / 12; + } +} + +#if HAVE_TRIPLEDRAGON +#define _A 0 +#define _R 1 +#define _G 2 +#define _B 3 +#else +#define _A 3 +#define _R 2 +#define _G 1 +#define _B 0 +#endif +void setcolors(unsigned short *pcolormap, int offset, int number) +{ + int i,trans_tmp; + int j = offset; /* index in global color table */ + + trans_tmp=25-trans_mode; + + bgra[transp2][_A]=((trans_tmp+7)<<11 | 0x7FF)>>8; + + for (i = 0; i < number; i++) + { + int r = (pcolormap[i] << 12 & 0xF000) >> 8; + int g = (pcolormap[i] << 8 & 0xF000) >> 8; + int b = (pcolormap[i] << 4 & 0xF000) >> 8; + + r = (r * (0x3f+(color_mode<<3))) >> 8; + g = (g * (0x3f+(color_mode<<3))) >> 8; + b = (b * (0x3f+(color_mode<<3))) >> 8; + + bgra[j][_R]=r; + bgra[j][_G]=g; + bgra[j][_B]=b; + + j++; + } +} + +/* hexdump of page contents to stdout for debugging */ +void dump_page() +{ + int r, c; + char *p; + unsigned char pagedata[23*40]; + + if (!tuxtxt_cache.astCachetable[tuxtxt_cache.page][tuxtxt_cache.subpage]) + return; + tuxtxt_decompress_page(tuxtxt_cache.page,tuxtxt_cache.subpage,pagedata); + for (r=1; r < 24; r++) + { + p = (char *) pagedata+40*(r-1); + for (c=0; c < 40; c++) + printf(" %02x", *p++); + printf("\n"); + p = (char *) page_char + 40*r; + for (c=0; c < 40; c++) + printf(" %c", *p++); + printf("\n"); + } +} + +/* get object data */ +/* in: absolute triplet number (0..506, start at packet 3 byte 1) */ +/* in: pointer to cache struct of page data */ +/* out: 18 bit triplet data, <0 if invalid number, not cached, or hamming error */ +int iTripletNumber2Data(int iONr, tstCachedPage *pstCachedPage, unsigned char* pagedata) +{ + if (iONr > 506 || 0 == pstCachedPage) + return -1; + + unsigned char *p; + int packet = (iONr / 13) + 3; + int packetoffset = 3 * (iONr % 13); + + if (packet <= 23) + p = pagedata + 40*(packet-1) + packetoffset + 1; + else if (packet <= 25) + { + if (0 == pstCachedPage->pageinfo.p24) + return -1; + p = pstCachedPage->pageinfo.p24 + 40*(packet-24) + packetoffset + 1; + } + else + { + int descode = packet - 26; + if (0 == pstCachedPage->pageinfo.ext) + return -1; + if (0 == pstCachedPage->pageinfo.ext->p26[descode]) + return -1; + p = pstCachedPage->pageinfo.ext->p26[descode] + packetoffset; /* first byte (=designation code) is not cached */ + } + return deh24(p); +} + +#define RowAddress2Row(row) ((row == 40) ? 24 : (row - 40)) + +/* dump interpreted object data to stdout */ +/* in: 18 bit object data */ +/* out: termination info, >0 if end of object */ +void eval_object(int iONr, tstCachedPage *pstCachedPage, + unsigned char *pAPx, unsigned char *pAPy, + unsigned char *pAPx0, unsigned char *pAPy0, + tObjType ObjType, unsigned char* pagedata) +{ + int iOData; + int iONr1 = iONr + 1; /* don't terminate after first triplet */ + unsigned char drcssubp=0, gdrcssubp=0; + signed char endcol = -1; /* last column to which to extend attribute changes */ + tstPageAttr attrPassive = atrtable[ATR_PassiveDefault]; /* current attribute for passive objects */ + + do + { + iOData = iTripletNumber2Data(iONr, pstCachedPage,pagedata); /* get triplet data, next triplet */ + if (iOData < 0) /* invalid number, not cached, or hamming error: terminate */ + break; +#if TUXTXT_DEBUG + if (dumpl25) + printf(" t%03d ", iONr); +#endif + if (endcol < 0) + { + if (ObjType == OBJ_ACTIVE) + { + endcol = 40; + } + else if (ObjType == OBJ_ADAPTIVE) /* search end of line */ + { + int i; + for (i = iONr; i <= 506; i++) + { + int iTempOData = iTripletNumber2Data(i, pstCachedPage,pagedata); /* get triplet data, next triplet */ + int iAddress = (iTempOData ) & 0x3f; + int iMode = (iTempOData >> 6) & 0x1f; + //int iData = (iTempOData >> 11) & 0x7f; + if (iTempOData < 0 || /* invalid number, not cached, or hamming error: terminate */ + (iAddress >= 40 /* new row: row address and */ + && (iMode == 0x01 || /* Full Row Color or */ + iMode == 0x04 || /* Set Active Position */ + (iMode >= 0x15 && iMode <= 0x17) || /* Object Definition */ + iMode == 0x17))) /* Object Termination */ + break; + if (iAddress < 40 && iMode != 0x06) + endcol = iAddress; + } +#if TUXTXT_DEBUG + if (dumpl25) + printf(" endcol %02d", endcol); +#endif + } + } + iONr++; + } + while (0 == eval_triplet(iOData, pstCachedPage, pAPx, pAPy, pAPx0, pAPy0, &drcssubp, &gdrcssubp, &endcol, &attrPassive, pagedata) + || iONr1 == iONr); /* repeat until termination reached */ +} + +void eval_NumberedObject(int p, int s, int packet, int triplet, int high, + unsigned char *pAPx, unsigned char *pAPy, + unsigned char *pAPx0, unsigned char *pAPy0) +{ + if (!packet || 0 == tuxtxt_cache.astCachetable[p][s]) + return; + unsigned char pagedata[23*40]; + tuxtxt_decompress_page(p, s,pagedata); + + + int idata = deh24(pagedata + 40*(packet-1) + 1 + 3*triplet); + int iONr; + + if (idata < 0) /* hamming error: ignore triplet */ + return; + if (high) + iONr = idata >> 9; /* triplet number of odd object data */ + else + iONr = idata & 0x1ff; /* triplet number of even object data */ + if (iONr <= 506) + { +#if TUXTXT_DEBUG + if (dumpl25) + printf("P%xT%x%c %8s %c#%03d@%03d\n", packet, triplet, "LH"[!!high], /* pointer pos, type, number, data pos */ + ObjectType[triplet % 3], "PCD"[triplet % 3], 8*packet + 2*(triplet-1)/3, iONr); + +#endif + eval_object(iONr, tuxtxt_cache.astCachetable[p][s], pAPx, pAPy, pAPx0, pAPy0, (tObjType)(triplet % 3),pagedata); + } +} + +int eval_triplet(int iOData, tstCachedPage *pstCachedPage, + unsigned char *pAPx, unsigned char *pAPy, + unsigned char *pAPx0, unsigned char *pAPy0, + unsigned char *drcssubp, unsigned char *gdrcssubp, + signed char *endcol, tstPageAttr *attrPassive, unsigned char* pagedata) +{ + int iAddress = (iOData ) & 0x3f; + int iMode = (iOData >> 6) & 0x1f; + int iData = (iOData >> 11) & 0x7f; + + if (iAddress < 40) /* column addresses */ + { + int offset; /* offset to page_char and page_atrb */ + + if (iMode != 0x06) + *pAPx = iAddress; /* new Active Column */ + offset = (*pAPy0 + *pAPy) * 40 + *pAPx0 + *pAPx; /* offset to page_char and page_atrb */ +#if TUXTXT_DEBUG + if (dumpl25) + printf(" M%02xC%02xD%02x %d r:%d ch:%02x", iMode, iAddress, iData, *endcol,*pAPy0 + *pAPy,page_char[offset]); +#endif + + switch (iMode) + { + case 0x00: + if (0 == (iData>>5)) + { + int newcolor = iData & 0x1f; + if (*endcol < 0) /* passive object */ + attrPassive->fg = newcolor; + else if (*endcol == 40) /* active object */ + { + tstPageAttr *p = &page_atrb[offset]; + int oldcolor = (p)->fg; /* current color (set-after) */ + int c = *pAPx0 + *pAPx; /* current column absolute */ + do + { + p->fg = newcolor; + p++; + c++; + } while (c < 40 && p->fg == oldcolor); /* stop at change by level 1 page */ + } + else /* adaptive object */ + { + tstPageAttr *p = &page_atrb[offset]; + int c = *pAPx; /* current column relative to object origin */ + do + { + p->fg = newcolor; + p++; + c++; + } while (c <= *endcol); + } +#if TUXTXT_DEBUG + if (dumpl25) + printf(" ,%02d FGCol T%x#%x", iAddress, (iData>>3)&0x03, iData&0x07); +#endif + } + break; + case 0x01: + if (iData >= 0x20) + { +#if TUXTXT_DEBUG + if (dumpl25) + printf(" ,%02d BlockMosaic G1 #%02x", iAddress, iData); +#endif + page_char[offset] = iData; + if (*endcol < 0) /* passive object */ + { + attrPassive->charset = C_G1C; /* FIXME: separated? */ + page_atrb[offset] = *attrPassive; + } + else if (page_atrb[offset].charset != C_G1S) + page_atrb[offset].charset = C_G1C; /* FIXME: separated? */ + } + break; + case 0x02: + case 0x0b: +#if TUXTXT_DEBUG + if (dumpl25) + printf(" ,%02d G3 #%02x f%db%d", iAddress, iData,attrPassive->fg, attrPassive->bg); +#endif + page_char[offset] = iData; + if (*endcol < 0) /* passive object */ + { + attrPassive->charset = C_G3; + page_atrb[offset] = *attrPassive; + } + else + page_atrb[offset].charset = C_G3; + break; + case 0x03: + if (0 == (iData>>5)) + { + int newcolor = iData & 0x1f; + if (*endcol < 0) /* passive object */ + attrPassive->bg = newcolor; + else if (*endcol == 40) /* active object */ + { + tstPageAttr *p = &page_atrb[offset]; + int oldcolor = (p)->bg; /* current color (set-after) */ + int c = *pAPx0 + *pAPx; /* current column absolute */ + do + { + p->bg = newcolor; + if (newcolor == black) + p->IgnoreAtBlackBgSubst = 1; + p++; + c++; + } while (c < 40 && p->bg == oldcolor); /* stop at change by level 1 page */ + } + else /* adaptive object */ + { + tstPageAttr *p = &page_atrb[offset]; + int c = *pAPx; /* current column relative to object origin */ + do + { + p->bg = newcolor; + if (newcolor == black) + p->IgnoreAtBlackBgSubst = 1; + p++; + c++; + } while (c <= *endcol); + } +#if TUXTXT_DEBUG + if (dumpl25) + printf(" ,%02d BGCol T%x#%x", iAddress, (iData>>3)&0x03, iData&0x07); +#endif + } + break; + case 0x06: +#if TUXTXT_DEBUG + if (dumpl25) + printf(" PDC"); +#endif + /* ignore */ + break; + case 0x07: +#if TUXTXT_DEBUG + if (dumpl25) + printf(" ,%02d Flash M%xP%x", iAddress, iData & 0x03, (iData >> 2) & 0x07); +#endif + if ((iData & 0x60) != 0) break; // reserved data field + if (*endcol < 0) /* passive object */ + { + attrPassive->flashing=iData & 0x1f; + page_atrb[offset] = *attrPassive; + } + else + page_atrb[offset].flashing=iData & 0x1f; + break; + case 0x08: +#if TUXTXT_DEBUG + if (dumpl25) + printf(" ,%02d G0+G2 set #%02x (p105)", iAddress, iData); +#endif + if (*endcol < 0) /* passive object */ + { + attrPassive->setG0G2=iData & 0x3f; + page_atrb[offset] = *attrPassive; + } + else + page_atrb[offset].setG0G2=iData & 0x3f; + break; + case 0x09: +#if TUXTXT_DEBUG + if (dumpl25) + printf(" ,%02d G0 #%02x '%c'", iAddress, iData, iData); +#endif + page_char[offset] = iData; + if (*endcol < 0) /* passive object */ + { + attrPassive->charset = C_G0P; /* FIXME: secondary? */ + attrPassive->setX26 = 1; + page_atrb[offset] = *attrPassive; + } + else + { + page_atrb[offset].charset = C_G0P; /* FIXME: secondary? */ + page_atrb[offset].setX26 = 1; + } + break; +// case 0x0b: (see 0x02) + case 0x0c: + { +#if TUXTXT_DEBUG + if (dumpl25) + printf(" ,%02d Attribute%s%s%s%s%s%s", iAddress, + (iData & 0x40) ? " DoubleWidth" : "", + (iData & 0x20) ? " UnderlineSep" : "", + (iData & 0x10) ? " InvColour" : "", + (iData & 0x04) ? " Conceal" : "", + (iData & 0x02) ? " Boxing" : "", + (iData & 0x01) ? " DoubleHeight" : ""); +#endif + int conc = (iData & 0x04); + int inv = (iData & 0x10); + int dw = (iData & 0x40 ?1:0); + int dh = (iData & 0x01 ?1:0); + int sep = (iData & 0x20); + int bw = (iData & 0x02 ?1:0); + if (*endcol < 0) /* passive object */ + { + if (conc) + { + attrPassive->concealed = 1; + attrPassive->fg = attrPassive->bg; + } + attrPassive->inverted = (inv ? 1- attrPassive->inverted : 0); + attrPassive->doubleh = dh; + attrPassive->doublew = dw; + attrPassive->boxwin = bw; + if (bw) attrPassive->IgnoreAtBlackBgSubst = 0; + if (sep) + { + if (attrPassive->charset == C_G1C) + attrPassive->charset = C_G1S; + else + attrPassive->underline = 1; + } + else + { + if (attrPassive->charset == C_G1S) + attrPassive->charset = C_G1C; + else + attrPassive->underline = 0; + } + } + else + { + + int c = *pAPx0 + (*endcol == 40 ? *pAPx : 0); /* current column */ + int c1 = offset; + tstPageAttr *p = &page_atrb[offset]; + do + { + p->inverted = (inv ? 1- p->inverted : 0); + if (conc) + { + p->concealed = 1; + p->fg = p->bg; + } + if (sep) + { + if (p->charset == C_G1C) + p->charset = C_G1S; + else + p->underline = 1; + } + else + { + if (p->charset == C_G1S) + p->charset = C_G1C; + else + p->underline = 0; + } + p->doublew = dw; + p->doubleh = dh; + p->boxwin = bw; + if (bw) p->IgnoreAtBlackBgSubst = 0; + p++; + c++; + c1++; + } while (c < *endcol); + } + break; + } + case 0x0d: +#if TUXTXT_DEBUG + if (dumpl25) + printf(" ,%02d %cDRCS #%02x", iAddress, (iData & 0x40) ? ' ' : 'G', iData & 0x3f); +#endif + page_char[offset] = iData & 0x3f; + if (*endcol < 0) /* passive object */ + { + attrPassive->charset = C_OFFSET_DRCS + ((iData & 0x40) ? (0x10 + *drcssubp) : *gdrcssubp); + page_atrb[offset] = *attrPassive; + } + else + page_atrb[offset].charset = C_OFFSET_DRCS + ((iData & 0x40) ? (0x10 + *drcssubp) : *gdrcssubp); + break; + case 0x0f: +#if TUXTXT_DEBUG + if (dumpl25) + printf(" ,%02d G2 #%02x", iAddress, iData); +#endif + page_char[offset] = iData; + if (*endcol < 0) /* passive object */ + { + attrPassive->charset = C_G2; + page_atrb[offset] = *attrPassive; + } + else + page_atrb[offset].charset = C_G2; + break; + default: + if (iMode == 0x10 && iData == 0x2a) + iData = '@'; + if (iMode >= 0x10) + { +#if TUXTXT_DEBUG + if (dumpl25) + printf(" ,%02d G0 #%02x %c +diacr. %x", iAddress, iData, iData, iMode & 0x0f); +#endif + page_char[offset] = iData; + if (*endcol < 0) /* passive object */ + { + attrPassive->charset = C_G0P; + attrPassive->diacrit = iMode & 0x0f; + attrPassive->setX26 = 1; + page_atrb[offset] = *attrPassive; + } + else + { + page_atrb[offset].charset = C_G0P; + page_atrb[offset].diacrit = iMode & 0x0f; + page_atrb[offset].setX26 = 1; + } + } + break; /* unsupported or not yet implemented mode: ignore */ + } /* switch (iMode) */ + } + else /* ================= (iAddress >= 40): row addresses ====================== */ + { +#if TUXTXT_DEBUG + if (dumpl25) + printf(" M%02xR%02xD%02x", iMode, iAddress, iData); +#endif + switch (iMode) + { + case 0x00: + if (0 == (iData>>5)) + { +#if TUXTXT_DEBUG + if (dumpl25) + printf(" FScrCol T%x#%x", (iData>>3)&0x03, iData&0x07); +#endif + FullScrColor = iData & 0x1f; + } + break; + case 0x01: + if (*endcol == 40) /* active object */ + { + *pAPy = RowAddress2Row(iAddress); /* new Active Row */ + + int color = iData & 0x1f; + int row = *pAPy0 + *pAPy; + int maxrow; +#if TUXTXT_DEBUG + if (dumpl25) + { + printf(" AP=%d,0", RowAddress2Row(iAddress)); + if (0 == (iData>>5)) + printf(" FRowCol T%x#%x", (iData>>3)&0x03, iData&0x07); + else if (3 == (iData>>5)) + printf(" FRowCol++ T%x#%x", (iData>>3)&0x03, iData&0x07); + } +#endif + if (row <= 24 && 0 == (iData>>5)) + maxrow = row; + else if (3 == (iData>>5)) + maxrow = 24; + else + maxrow = -1; + for (; row <= maxrow; row++) + FullRowColor[row] = color; + *endcol = -1; + } + break; + case 0x04: +#if TUXTXT_DEBUG + if (dumpl25) + printf(" AP=%d,%d", RowAddress2Row(iAddress), iData); +#endif + *pAPy = RowAddress2Row(iAddress); /* new Active Row */ + if (iData < 40) + *pAPx = iData; /* new Active Column */ + *endcol = -1; /* FIXME: check if row changed? */ + break; + case 0x07: +#if TUXTXT_DEBUG + if (dumpl25) + { + if (iAddress == 0x3f) + printf(" AP=0,0"); + if (0 == (iData>>5)) + printf(" Address Display R0 FRowCol T%x#%x", (iData>>3)&0x03, iData&0x07); + else if (3 == (iData>>5)) + printf(" Address Display R0->24 FRowCol T%x#%x", (iData>>3)&0x03, iData&0x07); + } +#endif + if (iAddress == 0x3f) + { + *pAPx = *pAPy = 0; /* new Active Position 0,0 */ + if (*endcol == 40) /* active object */ + { + int color = iData & 0x1f; + int row = *pAPy0; // + *pAPy; + int maxrow; + + if (row <= 24 && 0 == (iData>>5)) + maxrow = row; + else if (3 == (iData>>5)) + maxrow = 24; + else + maxrow = -1; + for (; row <= maxrow; row++) + FullRowColor[row] = color; + } + *endcol = -1; + } + break; + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: +#if TUXTXT_DEBUG + if (dumpl25) + printf(" PDC"); +#endif + /* ignore */ + break; + case 0x10: +#if TUXTXT_DEBUG + if (dumpl25) + printf(" AP=%d,%d temp. Origin Modifier", iAddress - 40, iData); +#endif + tAPy = iAddress - 40; + tAPx = iData; + break; + case 0x11: + case 0x12: + case 0x13: + if (iAddress & 0x10) /* POP or GPOP */ + { + unsigned char APx = 0, APy = 0; + unsigned char APx0 = *pAPx0 + *pAPx + tAPx, APy0 = *pAPy0 + *pAPy + tAPy; + int triplet = 3 * ((iData >> 5) & 0x03) + (iMode & 0x03); + int packet = (iAddress & 0x03) + 1; + int subp = iData & 0x0f; + int high = (iData >> 4) & 0x01; + + + if (APx0 < 40) /* not in side panel */ + { +#if TUXTXT_DEBUG + if (dumpl25) + printf(" Object Invocation %5s %8s S%xP%xT%x%c %c#%03d\n---", + ObjectSource[(iAddress >> 3) & 0x03], ObjectType[iMode & 0x03], + subp, + packet, + triplet, + "LH"[high], /* low/high */ + "PCD"[triplet % 3], + 8*packet + 2*(triplet-1)/3 + 1); +#endif + eval_NumberedObject((iAddress & 0x08) ? gpop : pop, subp, packet, triplet, high, &APx, &APy, &APx0, &APy0); +#if TUXTXT_DEBUG + if (dumpl25) + printf("---"); +#endif + } +#if TUXTXT_DEBUG + else if (dumpl25) + printf("Object Invocation for Side Panel - ignored"); +#endif + } + else if (iAddress & 0x08) /* local: eval invoked object */ + { + unsigned char APx = 0, APy = 0; + unsigned char APx0 = *pAPx0 + *pAPx + tAPx, APy0 = *pAPy0 + *pAPy + tAPy; + int descode = ((iAddress & 0x01) << 3) | (iData >> 4); + int triplet = iData & 0x0f; + + if (APx0 < 40) /* not in side panel */ + { +#if TUXTXT_DEBUG + if (dumpl25) + printf(" local Object Invocation %5s %8s D%xT%x:\n---", + ObjectSource[(iAddress >> 3) & 0x03], ObjectType[iMode & 0x03], descode, triplet); +#endif + eval_object(13 * 23 + 13 * descode + triplet, pstCachedPage, &APx, &APy, &APx0, &APy0, (tObjType)(triplet % 3), pagedata); +#if TUXTXT_DEBUG + if (dumpl25) + printf("---"); +#endif + } +#if TUXTXT_DEBUG + else if (dumpl25) + printf("local Object Invocation for Side Panel - ignored"); +#endif + } + break; + case 0x15: + case 0x16: + case 0x17: + if (0 == (iAddress & 0x08)) /* Object Definition illegal or only level 3.5 */ + break; /* ignore */ +#if TUXTXT_DEBUG + if (dumpl25) + { + printf(" Object Definition %8s", ObjectType[iMode & 0x03]); + { /* *POP */ + int triplet = 3 * ((iData >> 5) & 0x03) + (iMode & 0x03); + int packet = (iAddress & 0x03) + 1; + printf(" S%xP%xT%x%c %c#%03d", + iData & 0x0f, /* subpage */ + packet, + triplet, + "LH"[(iData >> 4) & 0x01], /* low/high */ + "PCD"[triplet % 3], + 8*packet + 2*(triplet-1)/3 + 1); + } + { /* local */ + int descode = ((iAddress & 0x03) << 3) | (iData >> 4); + int triplet = iData & 0x0f; + printf(" D%xT%x", descode, triplet); + } + putchar('\n'); + } +#endif + tAPx = tAPy = 0; + *endcol = -1; + return 0xFF; /* termination by object definition */ + break; + case 0x18: + if (0 == (iData & 0x10)) /* DRCS Mode reserved or only level 3.5 */ + break; /* ignore */ +#if TUXTXT_DEBUG + if (dumpl25) + printf(" %cDRCS S%x", (iData & 0x40) ? ' ' : 'G', iData & 0x0f); /* subpage */ +#endif + if (iData & 0x40) + *drcssubp = iData & 0x0f; + else + *gdrcssubp = iData & 0x0f; + break; + case 0x1f: +#if TUXTXT_DEBUG + if (dumpl25) + printf(" Termination Marker %x\n", iData); /* subpage */ +#endif + tAPx = tAPy = 0; + *endcol = -1; + return 0x80 | iData; /* explicit termination */ + break; + default: + break; /* unsupported or not yet implemented mode: ignore */ + } /* switch (iMode) */ + } /* (iAddress >= 40): row addresses */ +#if TUXTXT_DEBUG + if (dumpl25 && iAddress < 40) + putchar('\n'); +#endif + if (iAddress < 40 || iMode != 0x10) /* leave temp. AP-Offset unchanged only immediately after definition */ + tAPx = tAPy = 0; + + + return 0; /* normal exit, no termination */ +} + +int setnational(unsigned char sec) +{ + switch (sec) + { + case 0x08: + return NAT_PL; //polish + case 0x16: + case 0x36: + return NAT_TR; //turkish + case 0x1d: + return NAT_SR; //serbian, croatian, slovenian + case 0x20: + return NAT_SC; // serbian, croatian + case 0x24: + return NAT_RB; // russian, bulgarian + case 0x25: + return NAT_UA; // ukrainian + case 0x22: + return NAT_ET; // estonian + case 0x23: + return NAT_LV; // latvian, lithuanian + case 0x37: + return NAT_GR; // greek + case 0x55: + return NAT_HB; // hebrew + case 0x47: + case 0x57: + return NAT_AR; // arabic + } + return countryconversiontable[sec & 0x07]; +} + +/* evaluate level 2.5 information */ +void eval_l25() +{ + memset(FullRowColor, 0, sizeof(FullRowColor)); + FullScrColor = black; + + if (!tuxtxt_cache.astCachetable[tuxtxt_cache.page][tuxtxt_cache.subpage]) + return; + +#if TUXTXT_DEBUG + if (dumpl25) + printf("=== %03x/%02x %d/%d===\n", tuxtxt_cache.page, tuxtxt_cache.subpage,tuxtxt_cache.astCachetable[tuxtxt_cache.page][tuxtxt_cache.subpage]->pageinfo.nationalvalid,tuxtxt_cache.astCachetable[tuxtxt_cache.page][tuxtxt_cache.subpage]->pageinfo.national); +#endif + +#if 0 //TUXTXT_DEBUG I don't think we need this any longer because this code is unreachable (HexPages are handled before eval_l25() is called) + if (pageinfo->function == FUNC_MOT) /* magazine organization table */ + { + int i; + unsigned char *p = pagedata; + + printf("(G)POP/(G)DRCS-associations:\n"); + printf(" 0011223344556677889900112233445566778899"); + for (i = 0; i < 200; i++) + { + if (p[i] == 0xff) + break; + if (0 == (i % 40)) + printf("\n%x ", i / 20); + putchar(number2char(p[i])); + } + putchar('\n'); + + p = pagedata + 18*40; + for (i = 0; i < 80; i += 10) + { + short pop = ((p[i] << 8) | (p[i+1] << 4) | p[i+2]) & 0x7ff; + unsigned char type = p[i+5] & 0x03; /* 1st default object */ + unsigned char triplet = 3 * ((p[i+7] >> 1) & 0x03) + type; + unsigned char packet = (p[i+7] & 0x08) >> 3; + unsigned char subp = p[i+6]; + if (pop < 0x100) + pop += 0x800; + printf("POP #%x %03x/%x p27prio:%x", i/10, pop, p[i+3], p[i] & 0x08); + printf(" DefObj S%xP%xT%x%c %c#%03d", tuxtxt_cache.subpage, packet, triplet, "LH"[p[i+7] & 0x01], + "-CDP"[type], 8*packet + 2*(triplet-1)/3 + 1); + type = (p[i+5] >> 2) & 0x03; /* 2nd default object */ + triplet = 3 * ((p[i+9] >> 1) & 0x03) + type; + packet = (p[i+9] & 0x08) >> 3; + subp = p[i+8]; + printf(", S%xP%xT%x%c %c#%03d", tuxtxt_cache.subpage, packet, triplet, "LH"[p[i+9] & 0x01], + "-CDP"[type], 8*packet + 2*(triplet-1)/3 + 1); + if ((p[i+4] & 0x01) == 0) + printf(" Sidep.:%c%c BgSubst.:%x", (p[i+4] & 0x02) ? 'L' : '-', (p[i+4] & 0x04) ? 'R' : '-', p[i+4] >> 3); + putchar('\n'); + if ((pop & 0xff) != 0xff && tuxtxt_cache.astCachetable[pop][0]) /* link valid && linked page cached */ + { + tstPageinfo *pageinfo_link = &(tuxtxt_cache.astCachetable[pop][0]->pageinfo); + if (!i) + pageinfo_link->function = FUNC_GPOP; + else + pageinfo_link->function = FUNC_POP; + } + } + + p = pagedata + 20*40; + for (i = 0; i < 4*8; i += 4) + { + short drcs = ((p[i] << 8) | (p[i+1] << 4) | p[i+2]) & 0x7ff; + if (drcs < 0x100) + drcs += 0x800; + printf("DRCS #%x %03x/%x p27prio:%x\n", i/4, drcs, p[i+3], p[i] & 0x08); + if ((drcs & 0xff) != 0xff && tuxtxt_cache.astCachetable[drcs][0]) /* link valid && linked page cached */ + { + tstPageinfo *pageinfo_link = &(tuxtxt_cache.astCachetable[drcs][0]->pageinfo); + if (!i) + pageinfo_link->function = FUNC_GDRCS; + else + pageinfo_link->function = FUNC_DRCS; + } + } + } /* function == FUNC_MOT */ + +// else if (pageinfo->function == FUNC_GPOP || pageinfo->function == FUNC_POP) /* object definitions */ + else if (!tuxtxt_is_dec(tuxtxt_cache.page) && pageinfo->function != FUNC_GDRCS && pageinfo->function != FUNC_DRCS) /* in case the function is not assigned properly */ + { + unsigned char APx0, APy0, APx, APy; + int packet; + + pop = gpop = tuxtxt_cache.page; + + for (packet = 1; packet <= 4; packet++) + { + unsigned char *ptriplet = pagedata + 40*(packet-1); + int idata = dehamming[*ptriplet]; + int triplet; + + if (idata == 0xff || 0 == (idata & 1)) /* hamming error or no pointer data: ignore packet */ + continue; + for (triplet = 1; triplet <= 12; triplet++) + { + APx0 = APy0 = APx = APy = tAPx = tAPy = 0; + eval_NumberedObject(tuxtxt_cache.page, tuxtxt_cache.subpage, packet, triplet, 0, &APx, &APy, &APx0, &APy0); + APx0 = APy0 = APx = APy = tAPx = tAPy = 0; + eval_NumberedObject(tuxtxt_cache.page, tuxtxt_cache.subpage, packet, triplet, 1, &APx, &APy, &APx0, &APy0); + } /* for triplet */ + } /* for packet */ + } /* function == FUNC_*POP */ +#endif /* TUXTXT_DEBUG */ + + /* normal page */ + if (tuxtxt_is_dec(tuxtxt_cache.page)) + { + unsigned char APx0, APy0, APx, APy; + tstPageinfo *pi = &(tuxtxt_cache.astCachetable[tuxtxt_cache.page][tuxtxt_cache.subpage]->pageinfo); + tstCachedPage *pmot = tuxtxt_cache.astCachetable[(tuxtxt_cache.page & 0xf00) | 0xfe][0]; + unsigned short *colortable = 0; + int p26Received = 0; + int BlackBgSubst = 0; + int ColorTableRemapping = 0; + + + pop = gpop = drcs = gdrcs = 0; + + + if (pi->ext) + { + tstExtData *e = pi->ext; + + if (e->p26[0]) + p26Received = 1; + + if (e->p27) + { + tstp27 *p27 = e->p27; + if (p27[0].l25) + gpop = p27[0].page; + if (p27[1].l25) + pop = p27[1].page; + if (p27[2].l25) + gdrcs = p27[2].page; + if (p27[3].l25) + drcs = p27[3].page; + } + + if (e->p28Received) + { + colortable = e->bgr; + BlackBgSubst = e->BlackBgSubst; + ColorTableRemapping = e->ColorTableRemapping; + memset(FullRowColor, e->DefRowColor, sizeof(FullRowColor)); + FullScrColor = e->DefScreenColor; + national_subset = setnational(e->DefaultCharset); + national_subset_secondary = setnational(e->SecondCharset); +#if TUXTXT_DEBUG + if (dumpl25) + { + int c; /* color */ + printf("p28/0: DefCharset %02x Sec %02x SidePanel %c%c%x DefScrCol %02x DefRowCol %02x BlBgSubst %x Map %x\n CBGR", + e->DefaultCharset, + e->SecondCharset, + e->LSP ? (e->SPL25 ? 'L' : 'l') : '-', /* left panel (small: only in level 3.5) */ + e->RSP ? (e->SPL25 ? 'R' : 'r') : '-', /* right panel (small: only in level 3.5) */ + e->LSPColumns, + e->DefScreenColor, + e->DefRowColor, + e->BlackBgSubst, + e->ColorTableRemapping); + for (c = 0; c < 16; c++) + printf(" %x%03x", c, e->bgr[c]); + putchar('\n'); + } +#endif + } /* e->p28Received */ + } + + if (!colortable && tuxtxt_cache.astP29[tuxtxt_cache.page >> 8]) + { + tstExtData *e = tuxtxt_cache.astP29[tuxtxt_cache.page >> 8]; + colortable = e->bgr; + BlackBgSubst = e->BlackBgSubst; + ColorTableRemapping = e->ColorTableRemapping; + memset(FullRowColor, e->DefRowColor, sizeof(FullRowColor)); + FullScrColor = e->DefScreenColor; + national_subset = setnational(e->DefaultCharset); + national_subset_secondary = setnational(e->SecondCharset); +#if TUXTXT_DEBUG + if (dumpl25) + { + int c; /* color */ + printf("p29/0: DefCharset %02x Sec %02x SidePanel %c%c%x DefScrCol %02x DefRowCol %02x BlBgSubst %x Map %x\n CBGR", + e->DefaultCharset, + e->SecondCharset, + e->LSP ? (e->SPL25 ? 'L' : 'l') : '-', /* left panel (small: only in level 3.5) */ + e->RSP ? (e->SPL25 ? 'R' : 'r') : '-', /* right panel (small: only in level 3.5) */ + e->LSPColumns, + e->DefScreenColor, + e->DefRowColor, + e->BlackBgSubst, + e->ColorTableRemapping); + for (c = 0; c < 16; c++) + printf(" %x%03x", c, e->bgr[c]); + putchar('\n'); + } +#endif + + } + + if (ColorTableRemapping) + { + int i; + for (i = 0; i < 25*40; i++) + { + page_atrb[i].fg += MapTblFG[ColorTableRemapping - 1]; + if (!BlackBgSubst || page_atrb[i].bg != black || page_atrb[i].IgnoreAtBlackBgSubst) + page_atrb[i].bg += MapTblBG[ColorTableRemapping - 1]; + } + } + + /* determine ?pop/?drcs from MOT */ + if (pmot) + { + unsigned char pmot_data[23*40]; + tuxtxt_decompress_page((tuxtxt_cache.page & 0xf00) | 0xfe,0,pmot_data); + + unsigned char *p = pmot_data; /* start of link data */ + int o = 2 * (((tuxtxt_cache.page & 0xf0) >> 4) * 10 + (tuxtxt_cache.page & 0x0f)); /* offset of links for current page */ + int opop = p[o] & 0x07; /* index of POP link */ + int odrcs = p[o+1] & 0x07; /* index of DRCS link */ + unsigned char obj[3*4*4]; // types* objects * (triplet,packet,subp,high) + unsigned char type,ct, tstart = 4*4; + memset(obj,0,sizeof(obj)); + + + if (p[o] & 0x08) /* GPOP data used */ + { + if (!gpop || !(p[18*40] & 0x08)) /* no p27 data or higher prio of MOT link */ + { + gpop = ((p[18*40] << 8) | (p[18*40+1] << 4) | p[18*40+2]) & 0x7ff; + if ((gpop & 0xff) == 0xff) + gpop = 0; + else + { + if (gpop < 0x100) + gpop += 0x800; + if (!p26Received) + { + ct=2; + while (ct) + { + ct--; + type = (p[18*40+5] >> 2*ct) & 0x03; + + if (type == 0) continue; + obj[(type-1)*(tstart)+ct*4 ] = 3 * ((p[18*40+7+ct*2] >> 1) & 0x03) + type; //triplet + obj[(type-1)*(tstart)+ct*4+1] = ((p[18*40+7+ct*2] & 0x08) >> 3) + 1 ; //packet + obj[(type-1)*(tstart)+ct*4+2] = p[18*40+6+ct*2] & 0x0f ; //subp + obj[(type-1)*(tstart)+ct*4+3] = p[18*40+7+ct*2] & 0x01 ; //high + +#if TUXTXT_DEBUG + if (dumpl25) + printf("GPOP DefObj%d S%xP%xT%x%c %c#%03d\n" + ,2-ct + , obj[(type-1)*(tstart)+ct*4+2] + , obj[(type-1)*(tstart)+ct*4+1] + , obj[(type-1)*(tstart)+ct*4] + , "LH"[obj[(type-1)*(tstart)+ct*4+3]] + , "-CDP"[type] + , 8*(obj[(type-1)*(tstart)+ct*4+1]-1) + 2*(obj[(type-1)*(tstart)+ct*4]-1)/3 + 1); +#endif + } + } + } + } + } + if (opop) /* POP data used */ + { + opop = 18*40 + 10*opop; /* offset to POP link */ + if (!pop || !(p[opop] & 0x08)) /* no p27 data or higher prio of MOT link */ + { + pop = ((p[opop] << 8) | (p[opop+1] << 4) | p[opop+2]) & 0x7ff; + if ((pop & 0xff) == 0xff) + pop = 0; + else + { + if (pop < 0x100) + pop += 0x800; + if (!p26Received) + { + ct=2; + while (ct) + { + ct--; + type = (p[opop+5] >> 2*ct) & 0x03; + + if (type == 0) continue; + obj[(type-1)*(tstart)+(ct+2)*4 ] = 3 * ((p[opop+7+ct*2] >> 1) & 0x03) + type; //triplet + obj[(type-1)*(tstart)+(ct+2)*4+1] = ((p[opop+7+ct*2] & 0x08) >> 3) + 1 ; //packet + obj[(type-1)*(tstart)+(ct+2)*4+2] = p[opop+6+ct*2] ; //subp + obj[(type-1)*(tstart)+(ct+2)*4+3] = p[opop+7+ct*2] & 0x01 ; //high +#if TUXTXT_DEBUG + if (dumpl25) + printf("POP DefObj%d S%xP%xT%x%c %c#%03d\n" + , 2-ct + , obj[(type-1)*(tstart)+(ct+2)*4+2] + , obj[(type-1)*(tstart)+(ct+2)*4+1] + , obj[(type-1)*(tstart)+(ct+2)*4] + , "LH"[obj[(type-1)*(tstart)+(ct+2)*4+3]] + , "-CDP"[type], 8*(obj[(type-1)*(tstart)+(ct+2)*4+1]-1) + 2*(obj[(type-1)*(tstart)+(ct+2)*4]-1)/3 + 1); +#endif + } + } + } + } + } + // eval default objects in correct order + for (ct = 0; ct < 12; ct++) + { +#if TUXTXT_DEBUG + if (dumpl25) + printf("eval DefObjs : %d S%xP%xT%x%c %c#%03d\n" + , ct + , obj[ct*4+2] + , obj[ct*4+1] + , obj[ct*4] + , "LH"[obj[ct*4+3]] + , "-CDP"[obj[ct*4 % 3]] + , 8*(obj[ct*4+1]-1) + 2*(obj[ct*4]-1)/3 + 1); +#endif + if (obj[ct*4] != 0) + { + APx0 = APy0 = APx = APy = tAPx = tAPy = 0; + eval_NumberedObject(ct % 4 > 1 ? pop : gpop, obj[ct*4+2], obj[ct*4+1], obj[ct*4], obj[ct*4+3], &APx, &APy, &APx0, &APy0); + } + } + + if (p[o+1] & 0x08) /* GDRCS data used */ + { + if (!gdrcs || !(p[20*40] & 0x08)) /* no p27 data or higher prio of MOT link */ + { + gdrcs = ((p[20*40] << 8) | (p[20*40+1] << 4) | p[20*40+2]) & 0x7ff; + if ((gdrcs & 0xff) == 0xff) + gdrcs = 0; + else if (gdrcs < 0x100) + gdrcs += 0x800; + } + } + if (odrcs) /* DRCS data used */ + { + odrcs = 20*40 + 4*odrcs; /* offset to DRCS link */ + if (!drcs || !(p[odrcs] & 0x08)) /* no p27 data or higher prio of MOT link */ + { + drcs = ((p[odrcs] << 8) | (p[odrcs+1] << 4) | p[odrcs+2]) & 0x7ff; + if ((drcs & 0xff) == 0xff) + drcs = 0; + else if (drcs < 0x100) + drcs += 0x800; + } + } + if (tuxtxt_cache.astCachetable[gpop][0]) + tuxtxt_cache.astCachetable[gpop][0]->pageinfo.function = FUNC_GPOP; + if (tuxtxt_cache.astCachetable[pop][0]) + tuxtxt_cache.astCachetable[pop][0]->pageinfo.function = FUNC_POP; + if (tuxtxt_cache.astCachetable[gdrcs][0]) + tuxtxt_cache.astCachetable[gdrcs][0]->pageinfo.function = FUNC_GDRCS; + if (tuxtxt_cache.astCachetable[drcs][0]) + tuxtxt_cache.astCachetable[drcs][0]->pageinfo.function = FUNC_DRCS; + } /* if mot */ + +#if TUXTXT_DEBUG + if (dumpl25) + printf("gpop %03x pop %03x gdrcs %03x drcs %03x p28/0: Func %x Natvalid %x Nat %x Box %x\n", + gpop, pop, gdrcs, drcs, + pi->function, pi->nationalvalid, pi->national, pi->boxed); +#endif + + /* evaluate local extension data from p26 */ + if (p26Received) + { +#if TUXTXT_DEBUG + if (dumpl25) + printf("p26/x:\n"); +#endif + APx0 = APy0 = APx = APy = tAPx = tAPy = 0; + eval_object(13 * (23-2 + 2), tuxtxt_cache.astCachetable[tuxtxt_cache.page][tuxtxt_cache.subpage], &APx, &APy, &APx0, &APy0, OBJ_ACTIVE, &page_char[40]); /* 1st triplet p26/0 */ + tuxtxt_clear_p26(pi->ext); + } + + { + int r, c; + int o = 0; + + + for (r = 0; r < 25; r++) + for (c = 0; c < 39; c++) + { + if (BlackBgSubst && page_atrb[o].bg == black && !(page_atrb[o].IgnoreAtBlackBgSubst)) + { + if (FullRowColor[r] == 0x08) + page_atrb[o].bg = FullScrColor; + else + page_atrb[o].bg = FullRowColor[r]; + } + o++; + } + } + + if (!hintmode) + { + int i; + for (i = 0; i < 25*40; i++) + { + if (page_atrb[i].concealed) page_atrb[i].fg = page_atrb[i].bg; + } + } + + if (boxed || transpmode) { + FillBorder(transp); + } else if(use_gui) { + FillBorder(FullScrColor); + } + if (colortable) /* as late as possible to shorten the time the old page is displayed with the new colors */ + setcolors(colortable, 16, 16); /* set colors for CLUTs 2+3 */ + } /* is_dec(page) */ +} + +/****************************************************************************** + * main loop * + ******************************************************************************/ +static void cleanup_fb_pan() +{ +#ifdef USE_FBPAN + if (var_screeninfo.yoffset) + { + var_screeninfo.yoffset = 0; + if (ioctl(fb, FBIOPAN_DISPLAY, &var_screeninfo) == -1) + perror("TuxTxt "); + } +#endif +} + +static void* reader_thread(void * /*arg*/) +{ + printf("TuxTxt subtitle thread started\n"); + reader_running = 1; + //ttx_paused = 0; + while(reader_running) { + if(ttx_paused) + usleep(10); + else + RenderPage(); + if(ttx_req_pause) { + ttx_req_pause = 0; + ttx_paused = 1; + } + } + if(!ttx_paused) + CleanUp(); + cleanup_fb_pan(); + tuxtxt_close(); + printf("TuxTxt subtitle thread stopped\n"); + pthread_exit(NULL); +} + +void tuxtx_pause_subtitle(bool pause) +{ + if(!pause) { + //printf("TuxTxt subtitle unpause, running %d pid %d page %d\n", reader_running, sub_pid, sub_page); + ttx_paused = 0; + if(!reader_running && sub_pid && sub_page) + tuxtx_main(0, sub_pid, sub_page); + } + else { + if(!reader_running) + return; + printf("TuxTxt subtitle asking to pause...\n"); + ttx_req_pause = 1; + while(!ttx_paused) + usleep(10); + printf("TuxTxt subtitle paused\n"); + cleanup_fb_pan(); + } +} + +void tuxtx_stop_subtitle() +{ + printf("TuxTxt stopping subtitle thread ...\n"); + reader_running = 0; + if(ttx_sub_thread) + pthread_join(ttx_sub_thread, NULL); + ttx_sub_thread = 0; + sub_pid = sub_page = 0; + ttx_paused = 0; +} + +void tuxtx_set_pid(int pid, int page, const char * cc) +{ + if(reader_running) + tuxtx_stop_subtitle(); + + sub_pid = pid; + sub_page = page; + + cfg_national_subset = GetNationalSubset(cc); +#if 0 + printf("TuxTxt subtitle set pid %d page %d lang %s (%d)\n", sub_pid, sub_page, cc, cfg_national_subset); + ttx_paused = 1; + if(sub_pid && sub_page) + tuxtx_main(0, sub_pid, sub_page); +#endif +} + +int tuxtx_subtitle_running(int *pid, int *page, int *running) +{ + int ret = 0; + + if(running) + *running = reader_running; + + if(reader_running && (tuxtxt_cache.vtxtpid == *pid) && (tuxtxt_cache.page == *page)) + { + ret = 1; + } + *pid = sub_pid; + *page = sub_page; + + return ret; +} + +int tuxtx_main(int /*_rc*/, int pid, int page, int source) +{ + char cvs_revision[] = "$Revision: 1.95 $"; + + use_gui = 1; + boxed = 0; +//printf("to init tuxtxt\n");fflush(stdout); +#if !TUXTXT_CFG_STANDALONE + int initialized = tuxtxt_init(); + if (initialized) + tuxtxt_cache.page = 0x100; + if(page) { + sub_page = tuxtxt_cache.page = page; + sub_pid = pid; + use_gui = 0; + boxed = 1; + } +#endif + + /* show versioninfo */ + sscanf(cvs_revision, "%*s %s", versioninfo); + printf("TuxTxt %s\n", versioninfo); + printf("for 32bpp framebuffer\n"); + + fb = -1; +#ifdef USE_FBPAN + if ((fb=open("/dev/fb/0", O_RDWR)) == -1) + { + perror("TuxTxt "); + return 0; + } +#endif + + CFrameBuffer *fbp = CFrameBuffer::getInstance(); + lfb = (unsigned char *)fbp->getFrameBufferPointer(); + lbb = (unsigned char *)fbp->getBackBufferPointer(); + + tuxtxt_cache.vtxtpid = pid; + + if(tuxtxt_cache.vtxtpid == 0) + printf("[tuxtxt] No PID given, so scanning for PIDs ...\n\n"); + else + printf("[tuxtxt] using PID %x page %d\n", tuxtxt_cache.vtxtpid, tuxtxt_cache.page); + +#if 0 /* just get it from the framebuffer class */ + /* get fixed screeninfo */ + if (ioctl(fb, FBIOGET_FSCREENINFO, &fix_screeninfo) == -1) + { + perror("TuxTxt "); + return 0; + } + + /* get variable screeninfo */ + if (ioctl(fb, FBIOGET_VSCREENINFO, &var_screeninfo) == -1) + { + perror("TuxTxt "); + return 0; + } +#else + struct fb_var_screeninfo *var; + var = fbp->getScreenInfo(); + memcpy(&var_screeninfo, var, sizeof(struct fb_var_screeninfo)); + fix_screeninfo.line_length = var_screeninfo.xres * sizeof(fb_pixel_t); +#endif + /* set variable screeninfo for double buffering */ + var_screeninfo.yoffset = 0; +#if 0 + sx = x + 10; + sy = y + 10; + ex = x + w - 10; + ey = y + h - 10; +#endif + screen_x = fbp->getScreenX(); + screen_y = fbp->getScreenY(); + screen_w = fbp->getScreenWidth(); + screen_h = fbp->getScreenHeight(); + + int x = screen_x; + int y = screen_y; + int w = screen_w; + int h = screen_h; + + int tx = 0; + if (!screen_mode1) + tx = (w - (w * 3/4)) / 2; + sx = x + tx; + ex = x + w - tx; + sy = y; + ey = y + h; + + printf("[tuxtxt] screen is %dx%d at %dx%d border %d\n", ex-sx, ey-sy, sx, sy, tx); + /* initialisations */ + transpmode = 0; + + if (Init(source) == 0) + return 0; + + if(!use_gui) { + pthread_create(&ttx_sub_thread, 0, reader_thread, (void *) NULL); + return 1; + } + //transpmode = 1; + /* main loop */ + do { + if (GetRCCode() == 1) + { + if (transpmode == 2) /* TV mode */ + { + switch (RCCode) + { +//#if TUXTXT_DEBUG /* FIXME */ + case RC_OK: + if (showhex) + { + dump_page(); /* hexdump of page contents to stdout for debugging */ + } + continue; /* otherwise ignore key */ +//#endif /* TUXTXT_DEBUG */ + case RC_UP: + case RC_DOWN: + case RC_0: + case RC_1: + case RC_2: + case RC_3: + case RC_4: + case RC_5: + case RC_6: + case RC_7: + case RC_8: + case RC_9: + case RC_GREEN: + case RC_YELLOW: + case RC_BLUE: + case RC_PLUS: + case RC_MINUS: + case RC_DBOX: + case RC_STANDBY: + transpmode = 1; /* switch to normal mode */ + SwitchTranspMode(); + break; /* and evaluate key */ + + case RC_TTTV: + case RC_MUTE: /* regular toggle to transparent */ + case RC_TEXT: + break; + + case RC_HELP: /* switch to scart input and back */ + { + continue; /* otherwise ignore exit key */ + } + default: + continue; /* ignore all other keys */ + } + } + + switch (RCCode) + { + case RC_UP: + GetNextPageOne(!swapupdown); + break; + case RC_DOWN: + GetNextPageOne(swapupdown); + break; + case RC_RIGHT: + if (boxed) + { + subtitledelay++; + // display subtitledelay + PosY = StartY; + char ns[10]; + SetPosX(1); + sprintf(ns,"+%d ",subtitledelay); + RenderCharFB(ns[0],&atrtable[ATR_WB]); + RenderCharFB(ns[1],&atrtable[ATR_WB]); + RenderCharFB(ns[2],&atrtable[ATR_WB]); + RenderCharFB(ns[4],&atrtable[ATR_WB]); + } + else + GetNextSubPage(1); + break; + case RC_LEFT: + if (boxed) + { + subtitledelay--; + if (subtitledelay < 0) subtitledelay = 0; + // display subtitledelay + PosY = StartY; + char ns[10]; + SetPosX(1); + sprintf(ns,"+%d ",subtitledelay); + RenderCharFB(ns[0],&atrtable[ATR_WB]); + RenderCharFB(ns[1],&atrtable[ATR_WB]); + RenderCharFB(ns[2],&atrtable[ATR_WB]); + RenderCharFB(ns[4],&atrtable[ATR_WB]); + } + else + GetNextSubPage(-1); + break; + case RC_OK: + if (tuxtxt_cache.subpagetable[tuxtxt_cache.page] == 0xFF) + continue; + PageCatching(); + break; + + case RC_0: + case RC_1: + case RC_2: + case RC_3: + case RC_4: + case RC_5: + case RC_6: + case RC_7: + case RC_8: + case RC_9: + PageInput(CRCInput::getNumericValue(RCCode)); + break; + case RC_RED: ColorKey(prev_100); break; + case RC_GREEN: ColorKey(prev_10); break; + case RC_YELLOW: ColorKey(next_10); break; + case RC_BLUE: ColorKey(next_100); break; + case RC_TTZOOM: + case RC_PLUS: SwitchZoomMode(); break; + case RC_SPLIT: + case RC_MINUS: SwitchScreenMode(-1);prevscreenmode = screenmode; break; + case RC_TTTV: + case RC_MUTE: SwitchTranspMode(); break; + case RC_TEXT: + if(transpmode == 1) + RCCode = RC_HOME; + SwitchTranspMode(); + break; + case RC_TTREVEAL: + case RC_INFO: + case RC_HELP: SwitchHintMode(); break; + case RC_DBOX: ConfigMenu(0); break; + case RC_HOME: + break; + } + } + + /* update page or timestring and lcd */ + RenderPage(); + } while ((RCCode != RC_HOME) && (RCCode != RC_STANDBY)); + /* if transparent mode was selected, remember the original mode */ + screenmode = prevscreenmode; + + /* exit */ + CleanUp(); + + if (fb >= 0) + close(fb); + +#if 1 + if ( initialized ) + tuxtxt_close(); +#endif + + printf("Tuxtxt: plugin ended\n"); + return 1; +} + +/****************************************************************************** + * MyFaceRequester + ******************************************************************************/ + +FT_Error MyFaceRequester(FTC_FaceID face_id, FT_Library plibrary, FT_Pointer /*request_data*/, FT_Face *aface) +{ + FT_Error result; + + result = FT_New_Face(plibrary, (char *) face_id, 0, aface); + +#if TUXTXT_DEBUG + if (!result) + printf("TuxTxt \n", (char*)face_id); + else + printf("TuxTxt \n", (char*)face_id); +#endif + + return result; +} + +/****************************************************************************** + * Init * + ******************************************************************************/ +extern std::string ttx_font_file; +static bool ft_init_done = false; +static int oldfontheight = 0; +int Init(int source) +{ + int error, i; + static std::string font_file; + + /* init data */ + + //page_atrb[32] = transp<<4 | transp; + inputcounter = 2; + +#if TUXTXT_CFG_STANDALONE + unsigned char magazine; + for (magazine = 1; magazine < 9; magazine++) + { + tuxtxt_cache.current_page [magazine] = -1; + tuxtxt_cache.current_subpage [magazine] = -1; + } + /* init data */ + memset(&tuxtxt_cache.astCachetable, 0, sizeof(tuxtxt_cache.astCachetable)); + memset(&tuxtxt_cache.subpagetable, 0xFF, sizeof(tuxtxt_cache.subpagetable)); + memset(&tuxtxt_cache.astP29, 0, sizeof(tuxtxt_cache.astP29)); + + memset(&tuxtxt_cache.basictop, 0, sizeof(tuxtxt_cache.basictop)); + memset(&tuxtxt_cache.adip, 0, sizeof(tuxtxt_cache.adip)); + memset(&tuxtxt_cache.flofpages, 0 , sizeof(tuxtxt_cache.flofpages)); + tuxtxt_cache.maxadippg = -1; + tuxtxt_cache.bttok = 0; + maxhotlist = -1; + + //page_atrb[32] = transp<<4 | transp; + inputcounter = 2; + tuxtxt_cache.cached_pages = 0; + + tuxtxt_cache.page_receiving = -1; + tuxtxt_cache.page = 0x100; +#endif + lastpage = tuxtxt_cache.page; + prev_100 = 0x100; + prev_10 = 0x100; + next_100 = 0x100; + next_10 = 0x100; + tuxtxt_cache.subpage = tuxtxt_cache.subpagetable[tuxtxt_cache.page]; + if (tuxtxt_cache.subpage == 0xff) + tuxtxt_cache.subpage = 0; + + tuxtxt_cache.pageupdate = 0; + + tuxtxt_cache.zap_subpage_manual = 0; + + subtitledelay = 0; + delaystarted = 0; + + /* init lcd */ + UpdateLCD(); + + /* create TUXTXTDIR if necessary */ + if (!access(TUXTXTDIR, F_OK) == 0) + mkdir(TUXTXTDIR, 0755); + + /* config defaults */ + screenmode = 0; + screen_mode1 = 1; + color_mode = 10; + trans_mode = 1; + menulanguage = 1; /* english */ + /*national_subset = 0;*//* default */ + auto_national = 1; + swapupdown = 0; + showhex = 0; + showflof = 1; + show39 = 1; + showl25 = 1; + dumpl25 = 0; + usettf = 1; + TTFWidthFactor16 = 22; + TTFHeightFactor16 = 14; + TTFShiftX = 0; + TTFShiftY = -2; + + pageinfo = NULL; + + /* load config */ + if ((conf = fopen(TUXTXTCONF, "rt")) == 0) + { + perror("TuxTxt "); + } + else + { + while(1) + { + char line[100]; + int ival; + + if (!fgets(line, sizeof(line), conf)) + break; + + if (1 == sscanf(line, "ScreenMode16x9Normal %i", &ival)) + screen_mode1 = ival & 1; + else if (1 == sscanf(line, "Brightness %i", &ival)) + color_mode = ival; + else if (1 == sscanf(line, "AutoNational %i", &ival)) + auto_national = ival & 1; + else if (1 == sscanf(line, "NationalSubset %i", &ival)) + { + if (ival >= 0 && ival <= (int) MAX_NATIONAL_SUBSET) + national_subset = ival; + } + else if (1 == sscanf(line, "MenuLanguage %i", &ival)) + { + if (ival >= 0 && ival <= MAXMENULANGUAGE) + menulanguage = ival; + } + else if (1 == sscanf(line, "SwapUpDown %i", &ival)) + swapupdown = ival & 1; + else if (1 == sscanf(line, "ShowHexPages %i", &ival)) + showhex = ival & 1; + else if (1 == sscanf(line, "Transparency %i", &ival)) + trans_mode = ival; + else if (1 == sscanf(line, "TTFWidthFactor16 %i", &ival)) + TTFWidthFactor16 = ival; + else if (1 == sscanf(line, "TTFHeightFactor16 %i", &ival)) + TTFHeightFactor16 = ival; + else if (1 == sscanf(line, "TTFShiftX %i", &ival)) + TTFShiftX = ival; + else if (1 == sscanf(line, "TTFShiftY %i", &ival)) + TTFShiftY = ival; + else if (1 == sscanf(line, "Screenmode %i", &ival)) + screenmode = ival; + else if (1 == sscanf(line, "ShowFLOF %i", &ival)) + showflof = ival & 1; + else if (1 == sscanf(line, "Show39 %i", &ival)) + show39 = ival & 1; + else if (1 == sscanf(line, "ShowLevel2p5 %i", &ival)) + showl25 = ival & 1; + else if (1 == sscanf(line, "DumpLevel2p5 %i", &ival)) + dumpl25 = ival & 1; + else if (1 == sscanf(line, "UseTTF %i", &ival)) + usettf = ival & 1; +#if 0 + else if (1 == sscanf(line, "StartX %i", &ival)) + sx = ival; + else if (1 == sscanf(line, "EndX %i", &ival)) + ex = ival; + else if (1 == sscanf(line, "StartY %i", &ival)) + sy = ival; + else if (1 == sscanf(line, "EndY %i", &ival)) + ey = ival; +#endif + } + fclose(conf); + } + saveconfig = 0; + savedscreenmode = screenmode; + national_subset_secondary = NAT_DEFAULT; + + fontwidth = 0; /* initialize at first setting */ + tv_pip_y = 0; + + /* calculate font dimensions */ + displaywidth = (ex-sx); + fontheight = (ey-sy) / 25; //21; + fontwidth_normal = (ex-sx) / 40; + setfontwidth(fontwidth_normal); + fontwidth_topmenumain = (TV43STARTX-sx) / 40; + fontwidth_topmenusmall = (TVENDX - TOPMENUSTARTX) / TOPMENUCHARS; + //fontwidth_small = (TV169FULLSTARTX-sx) / 40; + fontwidth_small = (screen_w / 2) / 40; + ymosaic[0] = 0; /* y-offsets for 2*3 mosaic */ + ymosaic[1] = (fontheight + 1) / 3; + ymosaic[2] = (fontheight * 2 + 1) / 3; + ymosaic[3] = fontheight; + { + int i1; + for (i1 = 0; i1 <= 10; i1++) + aydrcs[i1] = (fontheight * i1 + 5) / 10; + } + + /* center screen */ + StartX = sx; //+ (((ex-sx) - 40*fontwidth) / 2); + StartY = sy + (((ey-sy) - 25*fontheight) / 2); + +#if 0 + if (usettf) + { + typettf.face_id = (FTC_FaceID) TUXTXTTTFVAR; + typettf.height = (FT_UShort) fontheight * TTFHeightFactor16 / 16; + } + else + { + typettf.face_id = (FTC_FaceID) TUXTXTOTBVAR; + typettf.width = (FT_UShort) 23; + typettf.height = (FT_UShort) 23; + } + + typettf.flags = FT_LOAD_MONOCHROME; + + if ((error = FTC_Manager_LookupFace(manager, typettf.face_id, &face))) + { + typettf.face_id = (void *) (usettf ? (FTC_FaceID) TUXTXTTTF : TUXTXTOTB); + if ((error = FTC_Manager_LookupFace(manager, typettf.face_id, &face))) + { + printf("TuxTxt \n", error); + FTC_Manager_Done(manager); + FT_Done_FreeType(library); + return 0; + } + } +#endif + if(!ft_init_done || font_file != ttx_font_file || fontheight != oldfontheight) { + printf("TuxTxt: init fontlibrary\n"); + if(ft_init_done) { + FTC_Manager_Done(manager); + FT_Done_FreeType(library); + ft_init_done = false; + } + /* init fontlibrary */ + if ((error = FT_Init_FreeType(&library))) + { + printf("TuxTxt ", error); + return 0; + } + + if ((error = FTC_Manager_New(library, 7, 2, 1024*1024, &MyFaceRequester, NULL, &manager))) + { + FT_Done_FreeType(library); + printf("TuxTxt \n", error); + return 0; + } + + if ((error = FTC_SBitCache_New(manager, &cache))) + { + FTC_Manager_Done(manager); + FT_Done_FreeType(library); + printf("TuxTxt \n", error); + return 0; + } + + if (usettf) { + printf("TuxTxt: using font %s\n", ttx_font_file.c_str()); + typettf.face_id = (FTC_FaceID) ttx_font_file.c_str(); + typettf.height = (FT_UShort) fontheight * TTFHeightFactor16 / 16; + } else { + typettf.face_id = (FTC_FaceID) TUXTXTOTB; + typettf.width = (FT_UShort) 23; + typettf.height = (FT_UShort) 23; + } + + typettf.flags = FT_LOAD_MONOCHROME; + + if ((error = FTC_Manager_LookupFace(manager, typettf.face_id, &face))) + { + printf("TuxTxt \n", error); + FTC_Manager_Done(manager); + FT_Done_FreeType(library); + return 0; + } + font_file = ttx_font_file; + ft_init_done = true; + oldfontheight = fontheight; + + ascender = (usettf ? fontheight * face->ascender / face->units_per_EM : 16); + } +#if TUXTXT_DEBUG + printf("TuxTxt \n", + fontheight, fontwidth, fontwidth_small, fontwidth_topmenumain, fontwidth_topmenusmall, + ymosaic[0], ymosaic[1], ymosaic[2], StartX, StartY, ascender); +#endif + +#if TUXTXT_DEBUG + printf("TuxTxt \n", + var_screeninfo.xres, var_screeninfo.yres, + var_screeninfo.xres_virtual, var_screeninfo.yres_virtual, + var_screeninfo.yoffset); +#endif + + /* set new colormap */ + setcolors((unsigned short *)defaultcolors, 0, SIZECOLTABLE); + + ClearBB(transp); /* initialize backbuffer */ + for (i = 0; i < 40 * 25; i++) + { + page_char[i] = ' '; + page_atrb[i].fg = transp; + page_atrb[i].bg = transp; + page_atrb[i].charset = C_G0P; + page_atrb[i].doubleh = 0; + page_atrb[i].doublew = 0; + page_atrb[i].IgnoreAtBlackBgSubst = 0; + } + /* if no vtxtpid for current service, search PIDs */ + if (tuxtxt_cache.vtxtpid == 0) + { + /* get all vtxt-pids */ + getpidsdone = -1; /* don't kill thread */ + if (GetTeletextPIDs() == 0) + { +#if 0 + FTC_Manager_Done(manager); + FT_Done_FreeType(library); +#endif + return 0; + } + + if (auto_national) + national_subset = pid_table[0].national_subset; + if (pids_found > 1) + ConfigMenu(1); + else + { + tuxtxt_cache.vtxtpid = pid_table[0].vtxt_pid; + current_service = 0; + RenderMessage(ShowServiceName); + } + } + else + { + SDT_ready = 0; + getpidsdone = 0; + //getpidsdone = GetTeletextPIDs(false); + if(auto_national && cfg_national_subset) + national_subset = cfg_national_subset; + printf("Tuxtxt: national_subset %d (cfg %d)\n", national_subset, cfg_national_subset); + // tuxtxt_cache.pageupdate = 1; /* force display of message page not found (but not twice) */ + + } +#if TUXTXT_CFG_STANDALONE + tuxtxt_init_demuxer(); + tuxtxt_start_thread(); +#else + tuxtxt_start(tuxtxt_cache.vtxtpid, source); +#endif + gethotlist(); + + if(use_gui) + SwitchScreenMode(screenmode); + else + SwitchScreenMode(0); + + prevscreenmode = screenmode; + + printf("TuxTxt: init ok\n"); + + /* init successfull */ + return 1; +} + +/****************************************************************************** + * Cleanup * + ******************************************************************************/ + +void CleanUp() +{ + int curscreenmode = screenmode; + + /* hide and close pig */ + if (screenmode) + SwitchScreenMode(0); /* turn off divided screen */ + //close(pig); + +#if TUXTXT_CFG_STANDALONE + tuxtxt_stop_thread(); + tuxtxt_clear_cache(); + if (tuxtxt_cache.dmx != -1) + close(tuxtxt_cache.dmx); + tuxtxt_cache.dmx = -1; +#else + //tuxtxt_stop(); +#endif + +#ifdef USE_FBPAN + cleanup_fb_pan(); +#endif + //memset(lfb,0, var_screeninfo.yres*fix_screeninfo.line_length); + //CFrameBuffer::getInstance()->paintBackground(); + ClearFB(transp); + +#if 0 + /* close freetype */ + FTC_Manager_Done(manager); + FT_Done_FreeType(library); +#endif + if (hotlistchanged) + savehotlist(); + + /* save config */ + if (saveconfig || curscreenmode != savedscreenmode) + { + if ((conf = fopen(TUXTXTCONF, "wt")) == 0) + { + perror("TuxTxt "); + } + else + { + printf("TuxTxt \n"); + fprintf(conf, "ScreenMode16x9Normal %d\n", screen_mode1); + fprintf(conf, "Brightness %d\n", color_mode); + fprintf(conf, "MenuLanguage %d\n", menulanguage); + fprintf(conf, "AutoNational %d\n", auto_national); + fprintf(conf, "NationalSubset %d\n", national_subset); + fprintf(conf, "SwapUpDown %d\n", swapupdown); + fprintf(conf, "ShowHexPages %d\n", showhex); + fprintf(conf, "Transparency 0x%X\n", trans_mode); + fprintf(conf, "TTFWidthFactor16 %d\n", TTFWidthFactor16); + fprintf(conf, "TTFHeightFactor16 %d\n", TTFHeightFactor16); + fprintf(conf, "TTFShiftX %d\n", TTFShiftX); + fprintf(conf, "TTFShiftY %d\n", TTFShiftY); + fprintf(conf, "Screenmode %d\n", curscreenmode); + fprintf(conf, "ShowFLOF %d\n", showflof); + fprintf(conf, "Show39 %d\n", show39); + fprintf(conf, "ShowLevel2p5 %d\n", showl25); + fprintf(conf, "DumpLevel2p5 %d\n", dumpl25); + fprintf(conf, "UseTTF %d\n", usettf); +#if 0 + fprintf(conf, "StartX %d\n", sx); + fprintf(conf, "EndX %d\n", ex); + fprintf(conf, "StartY %d\n", sy); + fprintf(conf, "EndY %d\n", ey); +#endif + fclose(conf); + } + } +} +/****************************************************************************** + * GetTeletextPIDs * + ******************************************************************************/ +int GetTeletextPIDs() +{ + int pat_scan, pmt_scan, sdt_scan, desc_scan, pid_test, byte, diff, first_sdt_sec; + + unsigned char bufPAT[1024]; + unsigned char bufSDT[1024]; + unsigned char bufPMT[1024]; + + /* show infobar */ + RenderMessage(ShowInfoBar); + + unsigned char filter[DMX_FILTER_SIZE]; + unsigned char mask[DMX_FILTER_SIZE]; + int res; + + cDemux * dmx = new cDemux(1); + dmx->Open(DMX_PSI_CHANNEL); + + memset(filter, 0x00, DMX_FILTER_SIZE); + memset(mask, 0x00, DMX_FILTER_SIZE); + + //filter[0] = 0x00; + //mask[0] = 0xFF; + mask[0] = 0xFF; + mask[4] = 0xFF; + + dmx->sectionFilter(0, filter, mask, 1); + res = dmx->Read(bufPAT, sizeof(bufPAT)); + dmx->Stop(); + if(res <= 0) { + printf("TuxTxt failed"); + delete dmx; + return 0; + } + + /* scan each PMT for vtxt-pid */ + pids_found = 0; + + for (pat_scan = 0x0A; pat_scan < 0x0A + (((bufPAT[0x01]<<8 | bufPAT[0x02]) & 0x0FFF) - 9); pat_scan += 4) + { +#if TUXTXT_DEBUG + printf("PAT liefert:%04x, %04x \n",((bufPAT[pat_scan - 2]<<8) | (bufPAT[pat_scan - 1])),(bufPAT[pat_scan]<<8 | bufPAT[pat_scan+1]) & 0x1FFF); +#endif + if (((bufPAT[pat_scan - 2]<<8) | (bufPAT[pat_scan - 1])) == 0) + continue; + + int pid = (bufPAT[pat_scan]<<8 | bufPAT[pat_scan+1]) & 0x1FFF; + filter[0] = 0x02; + mask[0] = 0xFF; + + dmx->sectionFilter(pid, filter, mask, 1); + res = dmx->Read(bufPMT, sizeof(bufPMT)); + dmx->Stop(); + if(res <= 0) { + perror("TuxTxt "); + continue; + } + + for (pmt_scan = 0x0C + ((bufPMT[0x0A]<<8 | bufPMT[0x0B]) & 0x0FFF); + pmt_scan < (((bufPMT[0x01]<<8 | bufPMT[0x02]) & 0x0FFF) - 7); + pmt_scan += 5 + bufPMT[pmt_scan + 4]) + { + if (bufPMT[pmt_scan] == 6) + { + for (desc_scan = pmt_scan + 5; + desc_scan < pmt_scan + ((bufPMT[pmt_scan + 3]<<8 | bufPMT[pmt_scan + 4]) & 0x0FFF) + 5; + desc_scan += 2 + bufPMT[desc_scan + 1]) + { + if (bufPMT[desc_scan] == 0x56) + { + char country_code[4]; + + for (pid_test = 0; pid_test < pids_found; pid_test++) + if (pid_table[pid_test].vtxt_pid == ((bufPMT[pmt_scan + 1]<<8 | bufPMT[pmt_scan + 2]) & 0x1FFF)) + goto skip_pid; + + pid_table[pids_found].vtxt_pid = (bufPMT[pmt_scan + 1]<<8 | bufPMT[pmt_scan + 2]) & 0x1FFF; + pid_table[pids_found].service_id = bufPMT[0x03]<<8 | bufPMT[0x04]; + if (bufPMT[desc_scan + 1] == 5) + { + country_code[0] = bufPMT[desc_scan + 2] | 0x20; + country_code[1] = bufPMT[desc_scan + 3] | 0x20; + country_code[2] = bufPMT[desc_scan + 4] | 0x20; + country_code[3] = 0; + pid_table[pids_found].national_subset = GetNationalSubset(country_code); + } + else + { + country_code[0] = 0; + pid_table[pids_found].national_subset = NAT_DEFAULT; /* use default charset */ + } + +#if 1 // TUXTXT_DEBUG + printf("TuxTxt \n", + pids_found, + pid_table[pids_found].service_id, + pid_table[pids_found].vtxt_pid, + country_code, + pid_table[pids_found].national_subset, + (pid_table[pids_found].vtxt_pid == tuxtxt_cache.vtxtpid) ? " * " : "" + ); +#endif + + pids_found++; +skip_pid: + ; + } + } + } + } + } + + /* check for teletext */ + if (pids_found == 0) + { + printf("TuxTxt \n"); + + RenderMessage(NoServicesFound); + sleep(3); + delete dmx; + return 0; + } + + /* read SDT to get servicenames */ + SDT_ready = 0; + + filter[0] = 0x42; + mask[0] = 0xFF; + + dmx->sectionFilter(0x0011, filter, mask, 1); + + first_sdt_sec = -1; + while (1) + { + res = dmx->Read(bufSDT, sizeof(bufSDT)); + if(res <= 0) { + perror("TuxTxt "); + delete dmx; + RenderMessage(ShowServiceName); + return 1; + } + + if (first_sdt_sec == bufSDT[6]) + break; + + if (first_sdt_sec == -1) + first_sdt_sec = bufSDT[6]; + + /* scan SDT to get servicenames */ + for (sdt_scan = 0x0B; sdt_scan < ((bufSDT[1]<<8 | bufSDT[2]) & 0x0FFF) - 7; sdt_scan += 5 + ((bufSDT[sdt_scan + 3]<<8 | bufSDT[sdt_scan + 4]) & 0x0FFF)) + { + for (pid_test = 0; pid_test < pids_found; pid_test++) + { + if ((bufSDT[sdt_scan]<<8 | bufSDT[sdt_scan + 1]) == pid_table[pid_test].service_id && bufSDT[sdt_scan + 5] == 0x48) + { + diff = 0; + pid_table[pid_test].service_name_len = bufSDT[sdt_scan+9 + bufSDT[sdt_scan+8]]; + + //FIXME ?? + for (byte = 0; byte < pid_table[pid_test].service_name_len; byte++) + { + if (bufSDT[sdt_scan+10 + bufSDT[sdt_scan + 8] + byte] == (unsigned char)'Ä') + bufSDT[sdt_scan+10 + bufSDT[sdt_scan + 8] + byte] = 0x5B; + if (bufSDT[sdt_scan+10 + bufSDT[sdt_scan + 8] + byte] == (unsigned char)'ä') + bufSDT[sdt_scan+10 + bufSDT[sdt_scan + 8] + byte] = 0x7B; + if (bufSDT[sdt_scan+10 + bufSDT[sdt_scan + 8] + byte] == (unsigned char)'Ö') + bufSDT[sdt_scan+10 + bufSDT[sdt_scan + 8] + byte] = 0x5C; + if (bufSDT[sdt_scan+10 + bufSDT[sdt_scan + 8] + byte] == (unsigned char)'ö') + bufSDT[sdt_scan+10 + bufSDT[sdt_scan + 8] + byte] = 0x7C; + if (bufSDT[sdt_scan+10 + bufSDT[sdt_scan + 8] + byte] == (unsigned char)'Ü') + bufSDT[sdt_scan+10 + bufSDT[sdt_scan + 8] + byte] = 0x5D; + if (bufSDT[sdt_scan+10 + bufSDT[sdt_scan + 8] + byte] == (unsigned char)'ü') + bufSDT[sdt_scan+10 + bufSDT[sdt_scan + 8] + byte] = 0x7D; + if (bufSDT[sdt_scan+10 + bufSDT[sdt_scan + 8] + byte] == (unsigned char)'ß') + bufSDT[sdt_scan+10 + bufSDT[sdt_scan + 8] + byte] = 0x7E; + if (bufSDT[sdt_scan+10 + bufSDT[sdt_scan + 8] + byte] >= 0x80 && bufSDT[sdt_scan+10 + bufSDT[sdt_scan + 8] + byte] <= 0x9F) + diff--; + else + pid_table[pid_test].service_name[byte + diff] = bufSDT[sdt_scan+10 + bufSDT[sdt_scan + 8] + byte]; + } + + pid_table[pid_test].service_name_len += diff; + } + } + } + } + delete dmx; + SDT_ready = 1; + + /* show current servicename */ + current_service = 0; + + if (tuxtxt_cache.vtxtpid != 0) + { + while (pid_table[current_service].vtxt_pid != tuxtxt_cache.vtxtpid && current_service < pids_found) { + current_service++; + } + + if (auto_national && current_service < pids_found) { + national_subset = pid_table[current_service].national_subset; + printf("Tuxtxt: GetTeletextPIDs set national_subset -> %d\n", national_subset); + } + printf("Tuxtxt: GetTeletextPIDs national_subset %d\n", national_subset); + RenderMessage(ShowServiceName); + } + + getpidsdone = 1; + + RenderCharLCD(pids_found/10, 7, 44); + RenderCharLCD(pids_found%10, 19, 44); + + return 1; +} + +/****************************************************************************** + * GetNationalSubset * + ******************************************************************************/ +int GetNationalSubset(const char *cc) +{ + if (memcmp(cc, "cze", 3) == 0 || memcmp(cc, "ces", 3) == 0 || + memcmp(cc, "slo", 3) == 0 || memcmp(cc, "slk", 3) == 0) + return NAT_CZ; + if (memcmp(cc, "eng", 3) == 0) + return NAT_UK; + if (memcmp(cc, "est", 3) == 0) + return NAT_ET; + if (memcmp(cc, "fre", 3) == 0 || memcmp(cc, "lb", 3) == 0 || memcmp(cc, "ltz", 3) == 0 || memcmp(cc, "fra", 3) == 0) + return NAT_FR; + if (memcmp(cc, "ger", 3) == 0 || memcmp(cc, "deu", 3) == 0) + return NAT_DE; + if (memcmp(cc, "ita", 3) == 0) + return NAT_IT; + if (memcmp(cc, "lav", 3) == 0 || memcmp(cc, "lit", 3) == 0) + return NAT_LV; + if (memcmp(cc, "pol", 3) == 0) + return NAT_PL; + if (memcmp(cc, "spa", 3) == 0 || memcmp(cc, "por", 3) == 0) + return NAT_SP; + if (memcmp(cc, "rum", 3) == 0 || memcmp(cc, "ron", 3) == 0) + return NAT_RO; + if (memcmp(cc, "scc", 3) == 0 || memcmp(cc, "srp", 3) == 0 || + memcmp(cc, "scr", 3) == 0 || memcmp(cc, "hrv", 3) == 0 || + memcmp(cc, "slv", 3) == 0) + return NAT_SR; + if (memcmp(cc, "swe", 3) == 0 || + memcmp(cc, "dan", 3) == 0 || + memcmp(cc, "nor", 3) == 0 || + memcmp(cc, "fin", 3) == 0 || + memcmp(cc, "hun", 3) == 0) + return NAT_SW; + if (memcmp(cc, "tur", 3) == 0) + return NAT_TR; + if (memcmp(cc, "rus", 3) == 0 || memcmp(cc, "bul", 3) == 0) + return NAT_RB; + if (memcmp(cc, "ser", 3) == 0 || memcmp(cc, "cro", 3) == 0) + return NAT_SC; + if (memcmp(cc, "ukr", 3) == 0) + return NAT_UA; + if (memcmp(cc, "gre", 3) == 0) + return NAT_GR; + if (memcmp(cc, "heb", 3) == 0) + return NAT_HB; + if (memcmp(cc, "ara", 3) == 0) + return NAT_AR; + return NAT_DEFAULT; /* use default charset */ +} + +/****************************************************************************** + * ConfigMenu * + ******************************************************************************/ +#if TUXTXT_DEBUG +void charpage() +{ + PosY = StartY; + PosX = StartX; + char cachefill[100]; + int fullsize =0,hexcount = 0, col, p,sp; + int escpage = 0; + tstCachedPage* pg; + ClearFB(black); + + int zipsize = 0; + for (p = 0; p < 0x900; p++) + { + for (sp = 0; sp < 0x80; sp++) + { + pg = tuxtxt_cache.astCachetable[p][sp]; + if (pg) + { + + fullsize+=23*40; + zipsize += tuxtxt_get_zipsize(p,sp); + } + } + } + + + memset(cachefill,' ',40); + sprintf(cachefill,"f:%d z:%d h:%d c:%d %03x",fullsize, zipsize, hexcount, tuxtxt_cache.cached_pages, escpage); + + for (col = 0; col < 40; col++) + { + RenderCharFB(cachefill[col], &atrtable[ATR_WB]); + } + tstPageAttr atr; + memmove(&atr,&atrtable[ATR_WB],sizeof(tstPageAttr)); + int row; + atr.charset = C_G0P; + PosY = StartY+fontheight; + for (row = 0; row < 16; row++) + { + PosY+= fontheight; + SetPosX(1); + for (col=0; col < 6; col++) + { + RenderCharFB(col*16+row+0x20, &atr); + } + } + atr.setX26 = 1; + PosY = StartY+fontheight; + for (row = 0; row < 16; row++) + { + PosY+= fontheight; + SetPosX(10); + for (col=0; col < 6; col++) + { + RenderCharFB(col*16+row+0x20, &atr); + } + } + PosY = StartY+fontheight; + atr.charset = C_G2; + atr.setX26 = 0; + for (row = 0; row < 16; row++) + { + PosY+= fontheight; + SetPosX(20); + for (col=0; col < 6; col++) + { + RenderCharFB(col*16+row+0x20, &atr); + } + } + atr.charset = C_G3; + PosY = StartY+fontheight; + for (row = 0; row < 16; row++) + { + PosY+= fontheight; + SetPosX(30); + for (col=0; col < 6; col++) + { + RenderCharFB(col*16+row+0x20, &atr); + } + } + do + { + GetRCCode(); + } + while (RCCode != RC_OK && RCCode != RC_HOME); +} +#endif +void Menu_HighlightLine(char *menu, int line, int high) +{ + char hilitline[] = "0111111111111111111111111111102"; + int itext = Menu_Width*line; /* index start menuline */ + int byte; + int national_subset_bak = national_subset; + + PosX = Menu_StartX; + PosY = Menu_StartY + line*fontheight; + if (line == MenuLine[M_NAT]) + national_subset = national_subset_bak; + else + national_subset = menusubset[menulanguage]; + + for (byte = 0; byte < Menu_Width; byte++) + RenderCharFB(menu[itext + byte], + high ? + &atrtable[hilitline[byte] - '0' + ATR_MENUHIL0] : + &atrtable[menuatr[itext + byte] - '0' + ATR_MENU0]); + national_subset = national_subset_bak; +} + +void Menu_UpdateHotlist(char *menu, int hotindex, int menuitem) +{ + int i, j, k; + tstPageAttr *attr; + + PosX = Menu_StartX + 6*fontwidth; + PosY = Menu_StartY + (MenuLine[M_HOT]+1)*fontheight; + j = Menu_Width*(MenuLine[M_HOT]+1) + 6; /* start index in menu */ + + for (i = 0; i <= maxhotlist+1; i++) + { + if (i == maxhotlist+1) /* clear last+1 entry in case it was deleted */ + { + attr = &atrtable[ATR_MENU5]; + memset(&menu[j], ' ', 3); + } + else + { + if (i == hotindex) + attr = &atrtable[ATR_MENU1]; + else + attr = &atrtable[ATR_MENU5]; + hex2str(&menu[j+2], hotlist[i]); + } + + for (k = 0; k < 3; k++) + RenderCharFB(menu[j+k], attr); + + if (i == 4) + { + PosX = Menu_StartX + 6*fontwidth; + PosY += fontheight; + j += 2*Menu_Width - 4*4; + } + else + { + j += 4; /* one space distance */ + PosX += fontwidth; + } + } + + hex2str(&menu[Menu_Width*MenuLine[M_HOT] + hotlistpagecolumn[menulanguage]], (hotindex >= 0) ? hotlist[hotindex] : tuxtxt_cache.page); + memmove(&menu[Menu_Width*MenuLine[M_HOT] + hotlisttextcolumn[menulanguage]], &hotlisttext[menulanguage][(hotindex >= 0) ? 5 : 0], 5); + PosX = Menu_StartX + 20*fontwidth; + PosY = Menu_StartY + MenuLine[M_HOT]*fontheight; + + Menu_HighlightLine(menu, MenuLine[M_HOT], (menuitem == M_HOT) ? 1 : 0); +} + +void Menu_Init(char *menu, int current_pid, int menuitem, int hotindex) +{ + int byte, line; + int national_subset_bak = national_subset; + + memmove(menu, configmenu[menulanguage], Menu_Height*Menu_Width); + + if (getpidsdone) + { + memset(&menu[MenuLine[M_PID]*Menu_Width+3], 0x20,24); + if (SDT_ready) + memmove(&menu[MenuLine[M_PID]*Menu_Width+3+(24-pid_table[current_pid].service_name_len)/2], &pid_table[current_pid].service_name, pid_table[current_pid].service_name_len); + else + hex2str(&menu[MenuLine[M_PID]*Menu_Width + 13 + 3], tuxtxt_cache.vtxtpid); + } + if (!getpidsdone || current_pid == 0 || pids_found == 1) + menu[MenuLine[M_PID]*Menu_Width + 1] = ' '; + + if (!getpidsdone || current_pid == pids_found - 1 || pids_found == 1) + menu[MenuLine[M_PID]*Menu_Width + 28] = ' '; + + + /* set 16:9 modi, colors & national subset */ + memmove(&menu[Menu_Width*MenuLine[M_SC1] + Menu_Width - 5], &configonoff[menulanguage][screen_mode1 ? 3 : 0], 3); + + menu[MenuLine[M_COL]*Menu_Width + 1] = (color_mode == 1 ? ' ' : 'í'); + menu[MenuLine[M_COL]*Menu_Width + 28] = (color_mode == 24 ? ' ' : 'î'); + memset(&menu[Menu_Width*MenuLine[M_COL] + 3 ], 0x7f,color_mode); + memset(&menu[Menu_Width*MenuLine[M_COL] + 3+color_mode ], 0x20,24-color_mode); +// memmove(&menu[Menu_Width*MenuLine[M_COL] + Menu_Width - 5], &configonoff[menulanguage][color_mode ? 3 : 0], 3); + menu[MenuLine[M_TRA]*Menu_Width + 1] = (trans_mode == 1 ? ' ' : 'í'); + menu[MenuLine[M_TRA]*Menu_Width + 28] = (trans_mode == 24 ? ' ' : 'î'); + memset(&menu[Menu_Width*MenuLine[M_TRA] + 3 ], 0x7f,trans_mode); + memset(&menu[Menu_Width*MenuLine[M_TRA] + 3+trans_mode ], 0x20,24-trans_mode); + + memmove(&menu[Menu_Width*MenuLine[M_AUN] + Menu_Width - 5], &configonoff[menulanguage][auto_national ? 3 : 0], 3); + /*if (national_subset != NAT_DE)*/ + memmove(&menu[Menu_Width*MenuLine[M_NAT] + 2], &countrystring[national_subset*COUNTRYSTRING_WIDTH], COUNTRYSTRING_WIDTH); + if (national_subset == 0 || auto_national) + menu[MenuLine[M_NAT]*Menu_Width + 1] = ' '; + if (national_subset == MAX_NATIONAL_SUBSET || auto_national) + menu[MenuLine[M_NAT]*Menu_Width + 28] = ' '; + if (showhex) + menu[MenuLine[M_PID]*Menu_Width + 27] = '?'; + /* render menu */ + PosY = Menu_StartY; + for (line = 0; line < Menu_Height; line++) + { + PosX = Menu_StartX; + if (line == MenuLine[M_NAT]) + national_subset = national_subset_bak; + else + national_subset = menusubset[menulanguage]; + + if (line == Menu_Height-2) + memmove(&menu[line*Menu_Width + 21], versioninfo, 4); + + for (byte = 0; byte < Menu_Width; byte++) + RenderCharFB(menu[line*Menu_Width + byte], &atrtable[menuatr[line*Menu_Width + byte] - '0' + ATR_MENU0]); + + PosY += fontheight; + } + national_subset = national_subset_bak; + Menu_HighlightLine(menu, MenuLine[menuitem], 1); + Menu_UpdateHotlist(menu, hotindex, menuitem); +} + +void ConfigMenu(int Init) +{ + int menuitem = M_Start; + int current_pid = 0; + int hotindex; + int oldscreenmode, oldtrans = 0; + int i; + int national_subset_bak = national_subset; + char menu[Menu_Height*Menu_Width]; + + if (auto_national && tuxtxt_cache.astCachetable[tuxtxt_cache.page][tuxtxt_cache.subpage] && + tuxtxt_cache.astCachetable[tuxtxt_cache.page][tuxtxt_cache.subpage]->pageinfo.nationalvalid) { + national_subset = countryconversiontable[tuxtxt_cache.astCachetable[tuxtxt_cache.page][tuxtxt_cache.subpage]->pageinfo.national]; + } + + if (getpidsdone) + { + /* set current vtxt */ + if (tuxtxt_cache.vtxtpid == 0) + tuxtxt_cache.vtxtpid = pid_table[0].vtxt_pid; + else + while(pid_table[current_pid].vtxt_pid != tuxtxt_cache.vtxtpid && current_pid < pids_found) + current_pid++; + } + + /* reset to normal mode */ + if (zoommode) + zoommode = 0; + + if (transpmode) + { + oldtrans = transpmode; + transpmode = 0; + ClearBB(black); + } + + oldscreenmode = screenmode; + if (screenmode) + SwitchScreenMode(0); /* turn off divided screen */ + + hotindex = getIndexOfPageInHotlist(); + + /* clear framebuffer */ + ClearFB(transp); + + //FIXME this is hack. sometimes menu appear over txt page -> FB pan problem ? + int old_pagecatching = pagecatching; + pagecatching = 1; + ClearBB(transp); + CopyBB2FB(); + pagecatching = old_pagecatching; + // hack end + + clearbbcolor = black; + Menu_Init(menu, current_pid, menuitem, hotindex); + + /* loop */ + do { + if (GetRCCode() == 1) + { + int rc_num = -1; + + if (CRCInput::isNumeric(RCCode)) + rc_num = CRCInput::getNumericValue(RCCode) -1; /* valid: 1 to M_MaxDirect */ + if (rc_num >= 0 && rc_num <= M_MaxDirect) /* direct access */ + { + Menu_HighlightLine(menu, MenuLine[menuitem], 0); + menuitem = rc_num; + Menu_HighlightLine(menu, MenuLine[menuitem], 1); + + if (menuitem != M_PID) /* just select */ + RCCode = RC_OK; + } + + switch (RCCode) + { + case RC_UP: + Menu_HighlightLine(menu, MenuLine[menuitem], 0); + if (--menuitem < 0) + menuitem = M_Number-1; + if (auto_national && (menuitem == M_NAT)) + menuitem--; + Menu_HighlightLine(menu, MenuLine[menuitem], 1); + break; + + case RC_DOWN: + Menu_HighlightLine(menu, MenuLine[menuitem], 0); + if (++menuitem > M_Number-1) + menuitem = 0; + if (auto_national && (menuitem == M_NAT)) + menuitem++; + Menu_HighlightLine(menu, MenuLine[menuitem], 1); + break; + + case RC_LEFT: + switch (menuitem) + { + case M_COL: + saveconfig = 1; + color_mode--; + if (color_mode < 1) color_mode = 1; + menu[MenuLine[M_COL]*Menu_Width + 1] = (color_mode == 1 ? ' ' : 'í'); + menu[MenuLine[M_COL]*Menu_Width + 28] = (color_mode == 24 ? ' ' : 'î'); + memset(&menu[Menu_Width*MenuLine[M_COL] + 3 ], 0x7f,color_mode); + memset(&menu[Menu_Width*MenuLine[M_COL] + 3+color_mode ], 0x20,24-color_mode); + Menu_HighlightLine(menu, MenuLine[menuitem], 1); + setcolors((unsigned short *)defaultcolors, 0, SIZECOLTABLE); + Menu_Init(menu, current_pid, menuitem, hotindex); + break; + case M_TRA: + saveconfig = 1; + trans_mode--; + if (trans_mode < 1) trans_mode = 1; + menu[MenuLine[M_TRA]*Menu_Width + 1] = (trans_mode == 1 ? ' ' : 'í'); + menu[MenuLine[M_TRA]*Menu_Width + 28] = (trans_mode == 24 ? ' ' : 'î'); + memset(&menu[Menu_Width*MenuLine[M_TRA] + 3 ], 0x7f,trans_mode); + memset(&menu[Menu_Width*MenuLine[M_TRA] + 3+trans_mode ], 0x20,24-trans_mode); + Menu_HighlightLine(menu, MenuLine[menuitem], 1); + setcolors((unsigned short *)defaultcolors, 0, SIZECOLTABLE); + Menu_Init(menu, current_pid, menuitem, hotindex); + break; + case M_PID: + { + if (!getpidsdone) + { + GetTeletextPIDs(); + ClearFB(transp); + /* set current vtxt */ + if (tuxtxt_cache.vtxtpid == 0) + tuxtxt_cache.vtxtpid = pid_table[0].vtxt_pid; + else + while(pid_table[current_pid].vtxt_pid != tuxtxt_cache.vtxtpid && current_pid < pids_found) + current_pid++; + Menu_Init(menu, current_pid, menuitem, hotindex); + } + if (current_pid > 0) + { + current_pid--; + + memset(&menu[MenuLine[M_PID]*Menu_Width + 3], ' ', 24); + + if (SDT_ready) + { + memmove(&menu[MenuLine[M_PID]*Menu_Width+3+(24-pid_table[current_pid].service_name_len)/2], + &pid_table[current_pid].service_name, + pid_table[current_pid].service_name_len); + } + else + hex2str(&menu[MenuLine[M_PID]*Menu_Width + 13 + 3], tuxtxt_cache.vtxtpid); + + if (pids_found > 1) + { + if (current_pid == 0) + { + menu[MenuLine[M_PID]*Menu_Width + 1] = ' '; + menu[MenuLine[M_PID]*Menu_Width + 28] = 'î'; + } + else + { + menu[MenuLine[M_PID]*Menu_Width + 1] = 'í'; + menu[MenuLine[M_PID]*Menu_Width + 28] = 'î'; + } + } + + Menu_HighlightLine(menu, MenuLine[menuitem], 1); + + if (auto_national) + { + national_subset = pid_table[current_pid].national_subset; + + memmove(&menu[Menu_Width*MenuLine[M_NAT] + 2], &countrystring[national_subset*COUNTRYSTRING_WIDTH], COUNTRYSTRING_WIDTH); + Menu_HighlightLine(menu, MenuLine[M_NAT], 0); + } + } + break; + } + + case M_NAT: + saveconfig = 1; + if (national_subset > 0) + { + national_subset--; + + if (national_subset == 0) + { + menu[MenuLine[M_NAT]*Menu_Width + 1] = ' '; + menu[MenuLine[M_NAT]*Menu_Width + 28] = 'î'; + } + else + { + menu[MenuLine[M_NAT]*Menu_Width + 1] = 'í'; + menu[MenuLine[M_NAT]*Menu_Width + 28] = 'î'; + } + + Menu_Init(menu, current_pid, menuitem, hotindex); + } + break; + + case M_HOT: /* move towards top of hotlist */ + if (hotindex <= 0) /* if not found, start at end */ + hotindex = maxhotlist; + else + hotindex--; + Menu_UpdateHotlist(menu, hotindex, menuitem); + break; + + case M_LNG: + saveconfig = 1; + if (--menulanguage < 0) + menulanguage = MAXMENULANGUAGE; + Menu_Init(menu, current_pid, menuitem, hotindex); + break; + } /* switch menuitem */ + break; /* RC_LEFT */ + + case RC_RIGHT: + switch (menuitem) + { + case M_COL: + saveconfig = 1; + color_mode++; + if (color_mode > 24) color_mode = 24; + menu[MenuLine[M_COL]*Menu_Width + 1] = (color_mode == 1 ? ' ' : 'í'); + menu[MenuLine[M_COL]*Menu_Width + 28] = (color_mode == 24 ? ' ' : 'î'); + memset(&menu[Menu_Width*MenuLine[M_COL] + 3 ], 0x7f,color_mode); + memset(&menu[Menu_Width*MenuLine[M_COL] + 3+color_mode ], 0x20,24-color_mode); + Menu_HighlightLine(menu, MenuLine[menuitem], 1); + setcolors((unsigned short *)defaultcolors, 0, SIZECOLTABLE); + Menu_Init(menu, current_pid, menuitem, hotindex); + break; + case M_TRA: + saveconfig = 1; + trans_mode++; + if (trans_mode > 24) trans_mode = 24; + menu[MenuLine[M_TRA]*Menu_Width + 1] = (trans_mode == 1 ? ' ' : 'í'); + menu[MenuLine[M_TRA]*Menu_Width + 28] = (trans_mode == 24 ? ' ' : 'î'); + memset(&menu[Menu_Width*MenuLine[M_TRA] + 3 ], 0x7f,trans_mode); + memset(&menu[Menu_Width*MenuLine[M_TRA] + 3+trans_mode ], 0x20,24-trans_mode); + Menu_HighlightLine(menu, MenuLine[menuitem], 1); + setcolors((unsigned short *)defaultcolors, 0, SIZECOLTABLE); + Menu_Init(menu, current_pid, menuitem, hotindex); + break; + case M_PID: + if (!getpidsdone) + { + GetTeletextPIDs(); + ClearFB(transp); + /* set current vtxt */ + if (tuxtxt_cache.vtxtpid == 0) + tuxtxt_cache.vtxtpid = pid_table[0].vtxt_pid; + else + while(pid_table[current_pid].vtxt_pid != tuxtxt_cache.vtxtpid && current_pid < pids_found) + current_pid++; + Menu_Init(menu, current_pid, menuitem, hotindex); + } + if (current_pid < pids_found - 1) + { + current_pid++; + + memset(&menu[MenuLine[M_PID]*Menu_Width + 3], ' ', 24); + + if (SDT_ready) + memmove(&menu[MenuLine[M_PID]*Menu_Width + 3 + + (24-pid_table[current_pid].service_name_len)/2], + &pid_table[current_pid].service_name, + pid_table[current_pid].service_name_len); + else + hex2str(&menu[MenuLine[M_PID]*Menu_Width + 13 + 3], pid_table[current_pid].vtxt_pid); + + if (pids_found > 1) + { + if (current_pid == pids_found - 1) + { + menu[MenuLine[M_PID]*Menu_Width + 1] = 'í'; + menu[MenuLine[M_PID]*Menu_Width + 28] = ' '; + } + else + { + menu[MenuLine[M_PID]*Menu_Width + 1] = 'í'; + menu[MenuLine[M_PID]*Menu_Width + 28] = 'î'; + } + } + + Menu_HighlightLine(menu, MenuLine[menuitem], 1); + + if (auto_national) + { + if (getpidsdone) + national_subset = pid_table[current_pid].national_subset; + memmove(&menu[Menu_Width*MenuLine[M_NAT] + 2], &countrystring[national_subset*COUNTRYSTRING_WIDTH], COUNTRYSTRING_WIDTH); + Menu_HighlightLine(menu, MenuLine[M_NAT], 0); + } + } + break; + + case M_NAT: + saveconfig = 1; + if (national_subset < (int) MAX_NATIONAL_SUBSET) + { + national_subset++; + + if (national_subset == (int) MAX_NATIONAL_SUBSET) + { + menu[MenuLine[M_NAT]*Menu_Width + 1] = 'í'; + menu[MenuLine[M_NAT]*Menu_Width + 28] = ' '; + } + else + { + menu[MenuLine[M_NAT]*Menu_Width + 1] = 'í'; + menu[MenuLine[M_NAT]*Menu_Width + 28] = 'î'; + } + + Menu_Init(menu, current_pid, menuitem, hotindex); + } + break; + + case M_HOT: /* select hotindex */ + if ((int)hotindex >= maxhotlist) /* if not found, start at 0 */ + hotindex = 0; + else + hotindex++; + Menu_UpdateHotlist(menu, hotindex, menuitem); + break; + + case M_LNG: + saveconfig = 1; + if (++menulanguage > MAXMENULANGUAGE) + menulanguage = 0; + Menu_Init(menu, current_pid, menuitem, hotindex); + break; + } + break; /* RC_RIGHT */ + + case RC_PLUS: + switch (menuitem) + { + case M_HOT: /* move towards end of hotlist */ + { + if (hotindex<0) /* not found: add page at end */ + { + if (maxhotlist < (int) (sizeof(hotlist)/sizeof(hotlist[0])-1)) /* only if still room left */ + { + hotindex = ++maxhotlist; + hotlist[hotindex] = tuxtxt_cache.page; + hotlistchanged = 1; + Menu_UpdateHotlist(menu, hotindex, menuitem); + } + } + else /* found */ + { + if (hotindex < maxhotlist) /* not already at end */ + { + int temp = hotlist[hotindex]; + hotlist[hotindex] = hotlist[hotindex+1]; + hotlist[hotindex+1] = temp; + hotindex++; + hotlistchanged = 1; + Menu_UpdateHotlist(menu, hotindex, menuitem); + } + } + } + break; + } + break; /* RC_PLUS */ + + case RC_MINUS: + switch (menuitem) + { + case M_HOT: /* move towards top of hotlist */ + { + if (hotindex<0) /* not found: add page at top */ + { + if (maxhotlist < (int) (sizeof(hotlist)/sizeof(hotlist[0])-1)) /* only if still room left */ + { + for (hotindex = maxhotlist; hotindex >= 0; hotindex--) /* move rest of list */ + { + hotlist[hotindex+1] = hotlist[hotindex]; + } + maxhotlist++; + hotindex = 0; + hotlist[hotindex] = tuxtxt_cache.page; + hotlistchanged = 1; + Menu_UpdateHotlist(menu, hotindex, menuitem); + } + } + else /* found */ + { + if (hotindex > 0) /* not already at front */ + { + int temp = hotlist[hotindex]; + hotlist[hotindex] = hotlist[hotindex-1]; + hotlist[hotindex-1] = temp; + hotindex--; + hotlistchanged = 1; + Menu_UpdateHotlist(menu, hotindex, menuitem); + } + } + } + break; + } + break; /* RC_MINUS */ + + case RC_HELP: + switch (menuitem) + { + case M_HOT: /* current page is added to / removed from hotlist */ + { + if (hotindex<0) /* not found: add page */ + { + if (maxhotlist < (int) (sizeof(hotlist)/sizeof(hotlist[0])-1)) /* only if still room left */ + { + hotlist[++maxhotlist] = tuxtxt_cache.page; + hotindex = maxhotlist; + hotlistchanged = 1; + Menu_UpdateHotlist(menu, hotindex, menuitem); + } + } + else /* found: remove */ + { + if (maxhotlist > 0) /* don't empty completely */ + { + int i1; + + for (i1=hotindex; i1 maxhotlist) + hotindex = maxhotlist; + hotlistchanged = 1; + Menu_UpdateHotlist(menu, hotindex, menuitem); + } + } + } + break; + case M_PID: + showhex ^= 1; + menu[MenuLine[M_PID]*Menu_Width + 27] = (showhex ? '?' : ' '); + Menu_HighlightLine(menu, MenuLine[menuitem], 1); + break; +#if TUXTXT_DEBUG + case M_LNG: + charpage(); + ClearFB(transp); + Menu_Init(menu, current_pid, menuitem, hotindex); + break; +#endif + } + break; /* RC_MUTE */ + + case RC_OK: + switch (menuitem) + { + case M_PID: + if (!getpidsdone) + { + GetTeletextPIDs(); + ClearFB(transp); + /* set current vtxt */ + if (tuxtxt_cache.vtxtpid == 0) + tuxtxt_cache.vtxtpid = pid_table[0].vtxt_pid; + else + while(pid_table[current_pid].vtxt_pid != tuxtxt_cache.vtxtpid && current_pid < pids_found) + current_pid++; + Menu_Init(menu, current_pid, menuitem, hotindex); + } + else if (pids_found > 1) + { + if (hotlistchanged) + savehotlist(); + + if (Init || tuxtxt_cache.vtxtpid != pid_table[current_pid].vtxt_pid) + { +#if TUXTXT_CFG_STANDALONE + tuxtxt_stop_thread(); + tuxtxt_clear_cache(); +#else + tuxtxt_stop(); + if (Init) + tuxtxt_cache.vtxtpid = 0; // force clear cache +#endif + /* reset data */ + //page_atrb[32] = transp<<4 | transp; + inputcounter = 2; + + tuxtxt_cache.page = 0x100; + lastpage = 0x100; + prev_100 = 0x100; + prev_10 = 0x100; + next_100 = 0x100; + next_10 = 0x100; + tuxtxt_cache.subpage = 0; + + tuxtxt_cache.pageupdate = 0; + tuxtxt_cache.zap_subpage_manual = 0; + hintmode = 0; + memset(page_char,' ',40 * 25); + + for (i = 0; i < 40*25; i++) + { + page_atrb[i].fg = transp; + page_atrb[i].bg = transp; + } + ClearFB(transp); + + + /* start demuxer with new vtxtpid */ + if (auto_national) + national_subset = pid_table[current_pid].national_subset; + +#if TUXTXT_CFG_STANDALONE + tuxtxt_cache.vtxtpid = pid_table[current_pid].vtxt_pid; + tuxtxt_start_thread(); +#else + tuxtxt_start(pid_table[current_pid].vtxt_pid); +#endif + } +// tuxtxt_cache.pageupdate = 1; + + ClearBB(black); + gethotlist(); + + /* show new teletext */ + current_service = current_pid; +// RenderMessage(ShowServiceName); + + RCCode = -1; + if (oldscreenmode) + SwitchScreenMode(oldscreenmode); /* restore divided screen */ + transpmode = oldtrans; + return; + } + break; + + case M_SC1: + saveconfig = 1; + screen_mode1++; + screen_mode1 &= 1; + + memmove(&menu[Menu_Width*MenuLine[M_SC1] + Menu_Width - 5], &configonoff[menulanguage][screen_mode1 ? 3 : 0], 3); + Menu_HighlightLine(menu, MenuLine[menuitem], 1); + + break; + + case M_AUN: + saveconfig = 1; + auto_national++; + auto_national &= 1; + if (auto_national) + { + if (getpidsdone) + national_subset = pid_table[current_pid].national_subset; + else + { + if (tuxtxt_cache.astCachetable[tuxtxt_cache.page][tuxtxt_cache.subpage] && + tuxtxt_cache.astCachetable[tuxtxt_cache.page][tuxtxt_cache.subpage]->pageinfo.nationalvalid) + national_subset = countryconversiontable[tuxtxt_cache.astCachetable[tuxtxt_cache.page][tuxtxt_cache.subpage]->pageinfo.national]; + else + national_subset = national_subset_bak; + } + + } + Menu_Init(menu, current_pid, menuitem, hotindex); + break; + case M_HOT: /* show selected page */ + { + if (hotindex >= 0) /* not found: ignore */ + { + lastpage = tuxtxt_cache.page; + tuxtxt_cache.page = hotlist[hotindex]; + tuxtxt_cache.subpage = tuxtxt_cache.subpagetable[tuxtxt_cache.page]; + inputcounter = 2; + tuxtxt_cache.pageupdate = 1; + RCCode = RC_HOME; /* leave menu */ + } + } + break; + } /* RC_OK */ + break; + } + } + UpdateLCD(); /* update number of cached pages */ + } while ((RCCode != RC_HOME) && (RCCode != RC_DBOX) && (RCCode != RC_MUTE)); + + ClearBB(transp); + CopyBB2FB(); + tuxtxt_cache.pageupdate = 1; + RCCode = -1; + if (oldscreenmode) + SwitchScreenMode(oldscreenmode); /* restore divided screen */ + transpmode = oldtrans; +} + +/****************************************************************************** + * PageInput * + ******************************************************************************/ + +void PageInput(int Number) +{ + /* clear temp_page */ + if (inputcounter == 2) + temp_page = 0; + + /* check for 0 & 9 on first position */ + if (Number == 0 && inputcounter == 2) + { + /* set page */ + temp_page = lastpage; /* 0 toggles to last page as in program switching */ + inputcounter = -1; + } + else if (Number == 9 && inputcounter == 2) + { + /* set page */ + temp_page = getIndexOfPageInHotlist(); /* 9 toggles through hotlist */ + + if (temp_page<0 || temp_page==maxhotlist) /* from any (other) page go to first page in hotlist */ + temp_page = (maxhotlist >= 0) ? hotlist[0] : 0x100; + else + temp_page = hotlist[temp_page+1]; + + inputcounter = -1; + } + + /* show pageinput */ + if (zoommode == 2) + { + zoommode = 1; + CopyBB2FB(); + } + + PosY = StartY; + + switch (inputcounter) + { + case 2: + SetPosX(1); + RenderCharFB(Number | '0', &atrtable[ATR_WB]); + RenderCharFB('-', &atrtable[ATR_WB]); + RenderCharFB('-', &atrtable[ATR_WB]); + break; + + case 1: + SetPosX(2); + RenderCharFB(Number | '0', &atrtable[ATR_WB]); + break; + + case 0: + SetPosX(3); + RenderCharFB(Number | '0', &atrtable[ATR_WB]); + break; + } + + /* generate pagenumber */ + temp_page |= Number << inputcounter*4; + + inputcounter--; + + if (inputcounter < 0) + { + /* disable subpage zapping */ + tuxtxt_cache.zap_subpage_manual = 0; + + /* reset input */ + inputcounter = 2; + + /* set new page */ + lastpage = tuxtxt_cache.page; + + tuxtxt_cache.page = temp_page; + hintmode = 0; + + /* check cache */ + int subp = tuxtxt_cache.subpagetable[tuxtxt_cache.page]; + if (subp != 0xFF) + { + tuxtxt_cache.subpage = subp; + tuxtxt_cache.pageupdate = 1; +#if 1 //TUXTXT_DEBUG + printf("TuxTxt \n", tuxtxt_cache.page, tuxtxt_cache.subpage); +#endif + } + else + { + tuxtxt_cache.subpage = 0; +// RenderMessage(PageNotFound); +#if TUXTXT_DEBUG + printf("TuxTxt \n", tuxtxt_cache.page); +#endif + } + } +} + +/****************************************************************************** + * GetNextPageOne * + ******************************************************************************/ + +void GetNextPageOne(int up) +{ + /* disable subpage zapping */ + tuxtxt_cache.zap_subpage_manual = 0; + + /* abort pageinput */ + inputcounter = 2; + + /* find next cached page */ + lastpage = tuxtxt_cache.page; + + int subp; + do { + if (up) + tuxtxt_next_dec(&tuxtxt_cache.page); + else + tuxtxt_prev_dec(&tuxtxt_cache.page); + subp = tuxtxt_cache.subpagetable[tuxtxt_cache.page]; + } while (subp == 0xFF && tuxtxt_cache.page != lastpage); + + /* update page */ + if (tuxtxt_cache.page != lastpage) + { + if (zoommode == 2) + zoommode = 1; + + tuxtxt_cache.subpage = subp; + hintmode = 0; + tuxtxt_cache.pageupdate = 1; +#if TUXTXT_DEBUG + printf("TuxTxt \n", tuxtxt_cache.page, tuxtxt_cache.subpage); +#endif + } +} + +/****************************************************************************** + * GetNextSubPage * + ******************************************************************************/ +void GetNextSubPage(int offset) +{ + int loop; + + /* abort pageinput */ + inputcounter = 2; + + for (loop = tuxtxt_cache.subpage + offset; loop != tuxtxt_cache.subpage; loop += offset) + { + if (loop < 0) + loop = 0x79; + else if (loop > 0x79) + loop = 0; + if (loop == tuxtxt_cache.subpage) + break; + + if (tuxtxt_cache.astCachetable[tuxtxt_cache.page][loop]) + { + /* enable manual subpage zapping */ + tuxtxt_cache.zap_subpage_manual = 1; + + /* update page */ + if (zoommode == 2) /* if zoomed to lower half */ + zoommode = 1; /* activate upper half */ + + tuxtxt_cache.subpage = loop; + hintmode = 0; + tuxtxt_cache.pageupdate = 1; +#if TUXTXT_DEBUG + printf("TuxTxt \n", tuxtxt_cache.page, tuxtxt_cache.subpage); +#endif + return; + } + } + +#if TUXTXT_DEBUG + printf("TuxTxt \n"); +#endif +} +/****************************************************************************** + * ColorKey * + ******************************************************************************/ + +void ColorKey(int target) +{ + if (!target) + return; + if (zoommode == 2) + zoommode = 1; + lastpage = tuxtxt_cache.page; + tuxtxt_cache.page = target; + tuxtxt_cache.subpage = tuxtxt_cache.subpagetable[tuxtxt_cache.page]; + inputcounter = 2; + hintmode = 0; + tuxtxt_cache.pageupdate = 1; +#if TUXTXT_DEBUG + printf("TuxTxt \n", tuxtxt_cache.page); +#endif +} + +/****************************************************************************** + * PageCatching * + ******************************************************************************/ + +void PageCatching() +{ + int byte; + int oldzoommode = zoommode; + + pagecatching = 1; + + /* abort pageinput */ + inputcounter = 2; + + /* show info line */ + zoommode = 0; + PosX = StartX; + PosY = StartY + 24*fontheight; + for (byte = 0; byte < 40-nofirst; byte++) + RenderCharFB(catchmenutext[menulanguage][byte], &atrtable[catchmenutext[menulanguage][byte+40] - '0' + ATR_CATCHMENU0]); + zoommode = oldzoommode; + + /* check for pagenumber(s) */ + catch_row = 1; + catch_col = 0; + catched_page = 0; + pc_old_row = pc_old_col = 0; /* no inverted page number to restore yet */ + CatchNextPage(0, 1); + + if (!catched_page) + { + pagecatching = 0; + tuxtxt_cache.pageupdate = 1; + return; + } + + /* loop */ + do { + GetRCCode(); + + switch (RCCode) + { + case RC_LEFT: + CatchNextPage(0, -1); + break; + case RC_RIGHT: + CatchNextPage(0, 1); + break; + case RC_UP: + CatchNextPage(-1, -1); + break; + case RC_DOWN: + CatchNextPage(1, 1); + break; + case RC_0: + case RC_1: + case RC_2: + case RC_3: + case RC_4: + case RC_5: + case RC_6: + case RC_7: + case RC_8: + case RC_9: + case RC_RED: + case RC_GREEN: + case RC_YELLOW: + case RC_BLUE: + case RC_PLUS: + case RC_MINUS: + case RC_DBOX: + case RC_HOME: + case RC_HELP: + case RC_MUTE: + tuxtxt_cache.pageupdate = 1; + pagecatching = 0; + RCCode = -1; + return; + } + UpdateLCD(); + } while (RCCode != RC_OK); + + /* set new page */ + if (zoommode == 2) + zoommode = 1; + + lastpage = tuxtxt_cache.page; + tuxtxt_cache.page = catched_page; + hintmode = 0; + tuxtxt_cache.pageupdate = 1; + pagecatching = 0; + + int subp = tuxtxt_cache.subpagetable[tuxtxt_cache.page]; + if (subp != 0xFF) + tuxtxt_cache.subpage = subp; + else + tuxtxt_cache.subpage = 0; +} + +/****************************************************************************** + * CatchNextPage * + ******************************************************************************/ + +void CatchNextPage(int firstlineinc, int inc) +{ + int tmp_page, allowwrap = 1; /* allow first wrap around */ + + /* catch next page */ + for(;;) + { + unsigned char *p = &(page_char[catch_row*40 + catch_col]); + tstPageAttr a = page_atrb[catch_row*40 + catch_col]; + + if (!(a.charset == C_G1C || a.charset == C_G1S) && /* no mosaic */ + (a.fg != a.bg) && /* not hidden */ + (*p >= '1' && *p <= '8' && /* valid page number */ + *(p+1) >= '0' && *(p+1) <= '9' && + *(p+2) >= '0' && *(p+2) <= '9') && + (catch_row == 0 || (*(p-1) < '0' || *(p-1) > '9')) && /* non-numeric char before and behind */ + (catch_row == 37 || (*(p+3) < '0' || *(p+3) > '9'))) + { + tmp_page = ((*p - '0')<<8) | ((*(p+1) - '0')<<4) | (*(p+2) - '0'); + +#if 0 + if (tmp_page != catched_page) /* confusing to skip identical page numbers - I want to reach what I aim to */ +#endif + { + catched_page = tmp_page; + RenderCatchedPage(); + catch_col += inc; /* FIXME: limit */ +#if TUXTXT_DEBUG + printf("TuxTxt 0) + { + catch_row++; + catch_col = 0; + firstlineinc = 0; + } + else if (firstlineinc < 0) + { + catch_row--; + catch_col = 37; + firstlineinc = 0; + } + else + catch_col += inc; + + if (catch_col > 37) + { + catch_row++; + catch_col = 0; + } + else if (catch_col < 0) + { + catch_row--; + catch_col = 37; + } + + if (catch_row > 23) + { + if (allowwrap) + { + allowwrap = 0; + catch_row = 1; + catch_col = 0; + } + else + { +#if TUXTXT_DEBUG + printf("TuxTxt \n"); +#endif + return; + } + } + else if (catch_row < 1) + { + if (allowwrap) + { + allowwrap = 0; + catch_row = 23; + catch_col =37; + } + else + { +#if TUXTXT_DEBUG + printf("TuxTxt \n"); +#endif + return; + } + } + } +} + + +/****************************************************************************** + * RenderCatchedPage * + ******************************************************************************/ + +void RenderCatchedPage() +{ + int zoom = 0; + + /* handle zoom */ + if (zoommode) + zoom = 1<<10; + + if (pc_old_row || pc_old_col) /* not at first call */ + { + /* restore pagenumber */ + SetPosX(pc_old_col); + + if (zoommode == 2) + PosY = StartY + (pc_old_row-12)*fontheight*((zoom>>10)+1); + else + PosY = StartY + pc_old_row*fontheight*((zoom>>10)+1); + + RenderCharFB(page_char[pc_old_row*40 + pc_old_col ], &page_atrb[pc_old_row*40 + pc_old_col ]); + RenderCharFB(page_char[pc_old_row*40 + pc_old_col + 1], &page_atrb[pc_old_row*40 + pc_old_col + 1]); + RenderCharFB(page_char[pc_old_row*40 + pc_old_col + 2], &page_atrb[pc_old_row*40 + pc_old_col + 2]); + } + + pc_old_row = catch_row; + pc_old_col = catch_col; + + /* mark pagenumber */ + if (zoommode == 1 && catch_row > 11) + { + zoommode = 2; + CopyBB2FB(); + } + else if (zoommode == 2 && catch_row < 12) + { + zoommode = 1; + CopyBB2FB(); + } + SetPosX(catch_col); + + + if (zoommode == 2) + PosY = StartY + (catch_row-12)*fontheight*((zoom>>10)+1); + else + PosY = StartY + catch_row*fontheight*((zoom>>10)+1); + + tstPageAttr a0 = page_atrb[catch_row*40 + catch_col ]; + tstPageAttr a1 = page_atrb[catch_row*40 + catch_col + 1]; + tstPageAttr a2 = page_atrb[catch_row*40 + catch_col + 2]; + int t; + + /* exchange colors */ + t = a0.fg; a0.fg = a0.bg; a0.bg = t; + t = a1.fg; a1.fg = a1.bg; a1.bg = t; + t = a2.fg; a2.fg = a2.bg; a2.bg = t; + + RenderCharFB(page_char[catch_row*40 + catch_col ], &a0); + RenderCharFB(page_char[catch_row*40 + catch_col + 1], &a1); + RenderCharFB(page_char[catch_row*40 + catch_col + 2], &a2); +} + +/****************************************************************************** + * SwitchZoomMode * + ******************************************************************************/ + +void SwitchZoomMode() +{ + if (tuxtxt_cache.subpagetable[tuxtxt_cache.page] != 0xFF) + { + /* toggle mode */ + zoommode++; + + if (zoommode == 3) + zoommode = 0; + +#if TUXTXT_DEBUG + printf("TuxTxt \n", zoommode); +#endif + /* update page */ + tuxtxt_cache.pageupdate = 1; /* FIXME */ + } +} + +/****************************************************************************** + * SwitchScreenMode * + ******************************************************************************/ + +void SwitchScreenMode(int newscreenmode) +{ + + //struct v4l2_format format; + + /* reset transparency mode */ + if (transpmode) + transpmode = 0; + + if (newscreenmode < 0) /* toggle mode */ + screenmode++; + else /* set directly */ + screenmode = newscreenmode; + + if ((screenmode > 2) || (screenmode < 0)) + screenmode = 0; + +#if TUXTXT_DEBUG + printf("TuxTxt \n", screenmode); +#endif + + /* update page */ + tuxtxt_cache.pageupdate = 1; + + /* clear back buffer */ + clearbbcolor = screenmode?transp:static_cast(FullScrColor); + + if(use_gui) + ClearBB(clearbbcolor); + + /* set mode */ + if (screenmode) /* split */ + { + ClearFB(clearbbcolor); + + int fw, tx, ty, tw, th; + + if (screenmode==1) /* split with topmenu */ + { + int x = screen_x; + int w = screen_w; + int h = screen_h; + fw = fontwidth_topmenumain; + + tx = 0; /* split means we start at the left edge */ + sx = x; + /* width of the TTX display: + the TTX display shall appear with 4:3 aspect ratio + => width = h * 4/3 + => but the display might not have square pixels + ==> correction factor w/h / (16/9) for a 16:9 display + ===> width = h * 4/3 * w/h * 9/16; + = h * w / h * 4*9/3/16 + = w * 3 / 4 + */ + ex = x + w * 3/4; + + displaywidth = (ex - sx); + + StartX = sx; //+ (((ex-sx) - (40*fw+2+tw)) / 2); /* center screen */ + tx = ex + 2; + tw = x + w - tx; + th = tw * h/w; /* hardcoded 16:9 PIP */ + ty = StartY + 25 * fontheight - th; + tv_pip_y = ty; + } + else /* 2: split with full height tv picture */ + { + StartX = screen_x; + fw = fontwidth_small; + tx = TV169FULLSTARTX; + ty = TV169FULLSTARTY; + tw = TV169FULLWIDTH; + th = TV169FULLHEIGHT; + displaywidth = screen_w / 2; + } + + setfontwidth(fw); + + CFrameBuffer *f = CFrameBuffer::getInstance(); + videoDecoder->Pig(tx, ty, tw, th, + f->getScreenWidth(true), f->getScreenHeight(true)); +#if 0 + int sm = 0; + ioctl(pig, VIDIOC_OVERLAY, &sm); + sm = 1; + ioctl(pig, VIDIOC_G_FMT, &format); + format.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; + format.fmt.win.w.left = tx; + format.fmt.win.w.top = ty; + format.fmt.win.w.width = tw; + format.fmt.win.w.height = th; + ioctl(pig, VIDIOC_S_FMT, &format); + ioctl(pig, VIDIOC_OVERLAY, &sm); +#endif + } + else /* not split */ + { +#if 0 + ioctl(pig, VIDIOC_OVERLAY, &screenmode); +#endif + videoDecoder->Pig(-1, -1, -1, -1); + + int x = screen_x; + int w = screen_w; + //int h = CFrameBuffer::getInstance()->getScreenHeight(); + int tx = 0; + /* see comment above on the TTX window dimensions */ + if (!screen_mode1) + tx = (w - (w * 3/4)) / 2; + sx = x + tx; + ex = x + w - tx; + + /* if screen_mode1 changed, then recalculate fontwidth */ + fontwidth_normal = (ex-sx) / 40; + setfontwidth(fontwidth_normal); + displaywidth= (ex-sx); + StartX = sx; //+ (ex-sx - 40*fontwidth) / 2; /* center screen */ + } +} + +/****************************************************************************** + * SwitchTranspMode * + ******************************************************************************/ + +void SwitchTranspMode() +{ + if (screenmode) + { + prevscreenmode = screenmode; + SwitchScreenMode(0); /* turn off divided screen */ + } + /* toggle mode */ +#if 0 // transparent first + if (transpmode == 2) + transpmode = 0; + else + transpmode++; /* backward to immediately switch to TV-screen */ +#endif + /* transpmode: 0 normal, 1 transparent, 2 off */ + transpmode ++; + if(transpmode > 2) + transpmode = 0; + +#if TUXTXT_DEBUG + printf("TuxTxt \n", transpmode); +#endif + + /* set mode */ + if (!transpmode) /* normal text-only */ + { + ClearBB(FullScrColor); + tuxtxt_cache.pageupdate = 1; + } + else if (transpmode == 1) /* semi-transparent BG with FG text */ + { + ClearBB(transp); + tuxtxt_cache.pageupdate = 1; + } + else /* TV mode */ + { + ClearFB(transp); + clearbbcolor = FullScrColor; + } +} + +/****************************************************************************** + * SwitchHintMode * + ******************************************************************************/ + +void SwitchHintMode() +{ + /* toggle mode */ + hintmode ^= 1; +#if TUXTXT_DEBUG + printf("TuxTxt \n", hintmode); +#endif + + if (!hintmode) /* toggle evaluation of level 2.5 information by explicitly switching off hintmode */ + { + showl25 ^= 1; +#if TUXTXT_DEBUG + printf("TuxTxt \n", showl25); +#endif + } + /* update page */ + tuxtxt_cache.pageupdate = 1; +} + +void RenderDRCS( //FIX ME + unsigned char *s, /* pointer to char data, parity undecoded */ + unsigned char *d, /* pointer to frame buffer of top left pixel */ + unsigned char *ax, /* array[0..12] of x-offsets, array[0..10] of y-offsets for each pixel */ + unsigned char fgcolor, unsigned char bgcolor) +{ + int bit, x, y, ltmp; + unsigned char *ay = ax + 13; /* array[0..10] of y-offsets for each pixel */ + + for (y = 0; y < 10; y++) /* 10*2 bytes a 6 pixels per char definition */ + { + unsigned char c1 = deparity[*s++]; + unsigned char c2 = deparity[*s++]; + int h = ay[y+1] - ay[y]; + + if (!h) + continue; + if (((c1 == ' ') && (*(s-2) != ' ')) || ((c2 == ' ') && (*(s-1) != ' '))) /* parity error: stop decoding FIXME */ + return; + for (bit = 0x20, x = 0; + bit; + bit >>= 1, x++) /* bit mask (MSB left), column counter */ + { + int i, f1, f2; + + f1 = (c1 & bit) ? fgcolor : bgcolor; + f2 = (c2 & bit) ? fgcolor : bgcolor; + + for (i = 0; i < h; i++) + { + if (ax[x+1] > ax[x]) + { +// memset(d + ax[x], f1, ax[x+1] - ax[x]); + for (ltmp=0 ; ltmp <= (ax[x+1]-ax[x]); ltmp++) + { + memmove(d + ax[x]*4 +ltmp*4,bgra[f1],4); + } + } + if (ax[x+7] > ax[x+6]) + { +// memset(d + ax[x+6], f2, ax[x+7] - ax[x+6]); /* 2nd byte 6 pixels to the right */ + for (ltmp=0 ; ltmp <= (ax[x+7]-ax[x+6]); ltmp++) + { + memmove(d + ax[x+6]*4 +ltmp*4,bgra[f2],4); + } + + } + d += fix_screeninfo.line_length; + } + d -= h * fix_screeninfo.line_length; + } + d += h * fix_screeninfo.line_length; + } +} + + +void DrawVLine(int x, int y, int l, int color) +{ + unsigned char *p = getFBp(&y); + MARK_FB(x, y, 0, l); + p += x*4 + y * fix_screeninfo.line_length; + + for ( ; l > 0 ; l--) + { + memmove(p,bgra[color],4); + p += fix_screeninfo.line_length; + } +} + +void DrawHLine(int x, int y, int l, int color) +{ + int ltmp; + unsigned char *p = getFBp(&y); + MARK_FB(x, y, l, 0); + if (l > 0) + { + for (ltmp=0; ltmp <= l; ltmp++) + { + memmove(p + x*4 + ltmp*4 + y * fix_screeninfo.line_length, bgra[color], 4); + } + } +} + +void FillRectMosaicSeparated(int x, int y, int w, int h, int fgcolor, int bgcolor, int set) +{ + FillRect(x, y, w, h, bgcolor); + if (set) + { + FillRect(x+1, y+1, w-2, h-2, fgcolor); + } +} + +void FillTrapez(int x0, int y0, int l0, int xoffset1, int h, int l1, int color) +{ + unsigned char *p = getFBp(&y0); + MARK_FB(x0, y0, l0, h); + p += x0 * 4 + y0 * fix_screeninfo.line_length; + + int xoffset, l; + int yoffset; + int ltmp; + + for (yoffset = 0; yoffset < h; yoffset++) + { + l = l0 + ((l1-l0) * yoffset + h/2) / h; + xoffset = (xoffset1 * yoffset + h/2) / h; + if (l > 0) + { + for (ltmp=0; ltmp <= l; ltmp++) + { + memmove(p + xoffset*4 +ltmp*4, bgra[color], 4); + } + } + p += fix_screeninfo.line_length; + } +} +void FlipHorz(int x, int y, int w, int h) +{ + unsigned char *buf= new unsigned char[w*4]; + unsigned char *p = getFBp(&y); + MARK_FB(x, y, w, h); + p += x * 4 + y * fix_screeninfo.line_length; + + int w1,h1; + if(buf != NULL){ + for (h1 = 0 ; h1 < h ; h1++) + { + memmove(buf,p,w*4); + for (w1 = 0 ; w1 < w ; w1++) + { + memmove(p+w1*4,buf+((w-w1)*4)-4,4); + } + p += fix_screeninfo.line_length; + } + delete [] buf; + } +} +void FlipVert(int x, int y, int w, int h) +{ + unsigned char *buf= new unsigned char[w*4]; + unsigned char *p1, *p2; + unsigned char *p = getFBp(&y); + MARK_FB(x, y, w, h); + p += x*4 + y * fix_screeninfo.line_length; + + int h1; + if(buf != NULL){ + for (h1 = 0 ; h1 < h/2 ; h1++) + { + p1 = (p+(h1*fix_screeninfo.line_length)); + p2 = (p+(h-(h1+1))*fix_screeninfo.line_length); + memmove(buf,p1,w*4); + memmove(p1,p2,w*4); + memmove(p2,buf,w*4); + } + delete [] buf; + } +} + +int ShapeCoord(int param, int curfontwidth, int curfontheight) +{ + switch (param) + { + case S_W13: + return curfontwidth/3; + case S_W12: + return curfontwidth/2; + case S_W23: + return curfontwidth*2/3; + case S_W11: + return curfontwidth; + case S_WM3: + return curfontwidth-3; + case S_H13: + return curfontheight/3; + case S_H12: + return curfontheight/2; + case S_H23: + return curfontheight*2/3; + case S_H11: + return curfontheight; + default: + return param; + } +} + +void DrawShape(int x, int y, int shapenumber, int curfontwidth, int curfontheight, int fgcolor, int bgcolor, int clear) +{ + if (shapenumber < 0x20 || shapenumber > 0x7e || (shapenumber == 0x7e && clear)) + return; + + unsigned char *p = aShapes[shapenumber - 0x20]; + + if (*p == S_INV) + { + int t = fgcolor; + fgcolor = bgcolor; + bgcolor = t; + p++; + } + + if (clear) + FillRect(x, y, curfontwidth, fontheight, bgcolor); + while (*p != S_END) + switch (*p++) + { + case S_FHL: + { + int offset = ShapeCoord(*p++, curfontwidth, curfontheight); + DrawHLine(x, y + offset, curfontwidth, fgcolor); + break; + } + case S_FVL: + { + int offset = ShapeCoord(*p++, curfontwidth, curfontheight); + DrawVLine(x + offset, y, fontheight, fgcolor); + break; + } + case S_FLH: + FlipHorz(x,y,curfontwidth, fontheight); + break; + case S_FLV: + FlipVert(x,y,curfontwidth, fontheight); + break; + case S_BOX: + { + int xo = ShapeCoord(*p++, curfontwidth, curfontheight); + int yo = ShapeCoord(*p++, curfontwidth, curfontheight); + int w = ShapeCoord(*p++, curfontwidth, curfontheight); + int h = ShapeCoord(*p++, curfontwidth, curfontheight); + FillRect(x + xo, y + yo, w, h, fgcolor); + break; + } + case S_TRA: + { + int x0 = ShapeCoord(*p++, curfontwidth, curfontheight); + int y0 = ShapeCoord(*p++, curfontwidth, curfontheight); + int l0 = ShapeCoord(*p++, curfontwidth, curfontheight); + int x1 = ShapeCoord(*p++, curfontwidth, curfontheight); + int y1 = ShapeCoord(*p++, curfontwidth, curfontheight); + int l1 = ShapeCoord(*p++, curfontwidth, curfontheight); + FillTrapez(x + x0, y + y0, l0, x1-x0, y1-y0, l1, fgcolor); + break; + } + case S_BTR: + { + int x0 = ShapeCoord(*p++, curfontwidth, curfontheight); + int y0 = ShapeCoord(*p++, curfontwidth, curfontheight); + int l0 = ShapeCoord(*p++, curfontwidth, curfontheight); + int x1 = ShapeCoord(*p++, curfontwidth, curfontheight); + int y1 = ShapeCoord(*p++, curfontwidth, curfontheight); + int l1 = ShapeCoord(*p++, curfontwidth, curfontheight); + FillTrapez(x + x0, y + y0, l0, x1-x0, y1-y0, l1, bgcolor); + break; + } + case S_LNK: + { + DrawShape(x, y, ShapeCoord(*p, curfontwidth, curfontheight), curfontwidth, curfontheight, fgcolor, bgcolor, 0); + //p = aShapes[ShapeCoord(*p, curfontwidth, curfontheight) - 0x20]; + break; + } + default: + break; + } +} + + +/****************************************************************************** + * RenderChar * + ******************************************************************************/ + +void RenderChar(int Char, tstPageAttr *Attribute, int zoom, int yoffset) +{ + int Row, Pitch, Bit; + int error, glyph; + int bgcolor, fgcolor; + int factor, xfactor; + int national_subset_local = national_subset; + unsigned char *sbitbuffer; + + int curfontwidth = GetCurFontWidth(); + + if (Attribute->setX26) + { + national_subset_local = 0; // no national subset + } + + // G0+G2 set designation + if (Attribute->setG0G2 != 0x3f) + { + switch (Attribute->setG0G2) + { + case 0x20 : + national_subset_local = NAT_SC; + break; + case 0x24 : + national_subset_local = NAT_RB; + break; + case 0x25 : + national_subset_local = NAT_UA; + break; + case 0x37: + national_subset_local = NAT_GR; + break; + case 0x55: + national_subset_local = NAT_HB; + break; + case 0x47: + case 0x57: + national_subset_local = NAT_AR; + break; + default: + national_subset_local = countryconversiontable[Attribute->setG0G2 & 0x07]; + break; + } + } + + if (Attribute->charset == C_G0S) // use secondary charset + national_subset_local = national_subset_secondary; + if (zoom && Attribute->doubleh) + factor = 4; + else if (zoom || Attribute->doubleh) + factor = 2; + else + factor = 1; + + if (Attribute->doublew) + { + int t = curfontwidth; + PosX += t; + curfontwidth += GetCurFontWidth(); + PosX -= t; + xfactor = 2; + } + else + xfactor = 1; + + if (Char == 0xFF) /* skip doubleheight chars in lower line */ + { + PosX += curfontwidth; + return; + } + + /* get colors */ + if (Attribute->inverted) + { + int t = Attribute->fg; + Attribute->fg = Attribute->bg; + Attribute->bg = t; + } + fgcolor = Attribute->fg; + if (transpmode == 1 && PosY < StartY + 24*fontheight) + { + if (fgcolor == transp) /* outside boxed elements (subtitles, news) completely transparent */ + bgcolor = transp; + else + bgcolor = transp2; + } + else + bgcolor = Attribute->bg; + + /* handle mosaic */ + if ((Attribute->charset == C_G1C || Attribute->charset == C_G1S) && + ((Char&0xA0) == 0x20)) + { + int w1 = (curfontwidth / 2 ) *xfactor; + int w2 = (curfontwidth - w1) *xfactor; + int y; + + Char = (Char & 0x1f) | ((Char & 0x40) >> 1); + if (Attribute->charset == C_G1S) /* separated mosaic */ + for (y = 0; y < 3; y++) + { + FillRectMosaicSeparated(PosX, PosY + yoffset + ymosaic[y]*factor, w1, (ymosaic[y+1] - ymosaic[y])*factor, fgcolor, bgcolor, Char & 0x01); + FillRectMosaicSeparated(PosX + w1, PosY + yoffset + ymosaic[y]*factor, w2, (ymosaic[y+1] - ymosaic[y])*factor, fgcolor, bgcolor, Char & 0x02); + Char >>= 2; + } + else + for (y = 0; y < 3; y++) + { + FillRect(PosX, PosY + yoffset + ymosaic[y]*factor, w1, (ymosaic[y+1] - ymosaic[y])*factor, (Char & 0x01) ? fgcolor : bgcolor); + FillRect(PosX + w1, PosY + yoffset + ymosaic[y]*factor, w2, (ymosaic[y+1] - ymosaic[y])*factor, (Char & 0x02) ? fgcolor : bgcolor); + Char >>= 2; + } + + PosX += curfontwidth; + return; + } + + if (Attribute->charset == C_G3) + { + if (Char < 0x20 || Char > 0x7d) + { + Char = 0x20; + } + else + { + if (*aShapes[Char - 0x20] == S_CHR) + { + unsigned char *p = aShapes[Char - 0x20]; + Char = (*(p+1) <<8) + (*(p+2)); + } + else if (*aShapes[Char - 0x20] == S_ADT) + { + int x,y,f,c; + y = yoffset; + unsigned char *p = getFBp(&y); + MARK_FB(PosX, PosY, curfontwidth, fontheight); + p += PosX * 4 + PosY * fix_screeninfo.line_length; + + for (y=0; ycharset >= C_OFFSET_DRCS) + { + + tstCachedPage *pcache = tuxtxt_cache.astCachetable[(Attribute->charset & 0x10) ? drcs : gdrcs][Attribute->charset & 0x0f]; + if (pcache) + { + unsigned char drcs_data[23*40]; + tuxtxt_decompress_page((Attribute->charset & 0x10) ? drcs : gdrcs,Attribute->charset & 0x0f,drcs_data); + unsigned char *p; + if (Char < 23*2) + p = drcs_data + 20*Char; + else if (pcache->pageinfo.p24) + p = pcache->pageinfo.p24 + 20*(Char - 23*2); + else + { + FillRect(PosX, PosY + yoffset, curfontwidth, factor*fontheight, bgcolor); + PosX += curfontwidth; + return; + } + axdrcs[12] = curfontwidth; /* adjust last x-offset according to position, FIXME: double width */ + int y = yoffset; + unsigned char *q = getFBp(&y); + RenderDRCS(p, + q + PosX * 4 + PosY * fix_screeninfo.line_length, + axdrcs, fgcolor, bgcolor); + } + else + FillRect(PosX, PosY + yoffset, curfontwidth, factor*fontheight, bgcolor); + PosX += curfontwidth; + return; + } +#if 0//old + else if (Attribute->charset == C_G2 && Char >= 0x20 && Char <= 0x7F) + { + if (national_subset_local == NAT_GR) + Char = G2table[2][Char-0x20]; + else if (national_subset_local == NAT_RU) + Char = G2table[1][Char-0x20]; + else + Char = G2table[0][Char-0x20]; + + if (Char == 0x7F) + { + FillRect(PosX, PosY + yoffset, curfontwidth, factor*ascender, fgcolor); + FillRect(PosX, PosY + yoffset + factor*ascender, curfontwidth, factor*(fontheight-ascender), bgcolor); + PosX += curfontwidth; + return; + } + } + else if (national_subset_local == NAT_GR && Char >= 0x40 && Char <= 0x7E) /* remap complete areas for greek */ + Char += 0x390 - 0x40; + else if (national_subset_local == NAT_GR && Char == 0x3c) + Char = '«'; + else if (national_subset_local == NAT_GR && Char == 0x3e) + Char = '»'; + else if (national_subset_local == NAT_GR && Char >= 0x23 && Char <= 0x24) + Char = nationaltable23[NAT_DE][Char-0x23]; /* #$ as in german option */ + else if (national_subset_local == NAT_RU && Char >= 0x40 && Char <= 0x7E) /* remap complete areas for cyrillic */ + Char = G0tablecyrillic[Char-0x20]; +#endif + else if (Attribute->charset == C_G2 && Char >= 0x20 && Char <= 0x7F) + { + if ((national_subset_local == NAT_SC) || (national_subset_local == NAT_RB) || (national_subset_local == NAT_UA)) + Char = G2table[1][Char-0x20]; + else if (national_subset_local == NAT_GR) + Char = G2table[2][Char-0x20]; + else if (national_subset_local == NAT_AR) + Char = G2table[3][Char-0x20]; + else + Char = G2table[0][Char-0x20]; + } + else if (national_subset_local == NAT_SC && Char >= 0x20 && Char <= 0x7F) /* remap complete areas for serbian/croatian */ + Char = G0table[0][Char-0x20]; + else if (national_subset_local == NAT_RB && Char >= 0x20 && Char <= 0x7F) /* remap complete areas for russian/bulgarian */ + Char = G0table[1][Char-0x20]; + else if (national_subset_local == NAT_UA && Char >= 0x20 && Char <= 0x7F) /* remap complete areas for ukrainian */ + Char = G0table[2][Char-0x20]; + else if (national_subset_local == NAT_GR && Char >= 0x20 && Char <= 0x7F) /* remap complete areas for greek */ + Char = G0table[3][Char-0x20]; + else if (national_subset_local == NAT_HB && Char >= 0x20 && Char <= 0x7F) /* remap complete areas for hebrew */ + Char = G0table[4][Char-0x20]; + else if (national_subset_local == NAT_AR && Char >= 0x20 && Char <= 0x7F) /* remap complete areas for arabic */ + Char = G0table[5][Char-0x20]; + + else + { + /* load char */ + switch (Char) + { + case 0x00: + case 0x20: + FillRect(PosX, PosY + yoffset, curfontwidth, factor*fontheight, bgcolor); + PosX += curfontwidth; + return; + case 0x23: + case 0x24: + Char = nationaltable23[national_subset_local][Char-0x23]; + break; + case 0x40: + Char = nationaltable40[national_subset_local]; + break; + case 0x5B: + case 0x5C: + case 0x5D: + case 0x5E: + case 0x5F: + case 0x60: + Char = nationaltable5b[national_subset_local][Char-0x5B]; + break; + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + Char = nationaltable7b[national_subset_local][Char-0x7B]; + break; + case 0x7F: + FillRect(PosX, PosY + yoffset, curfontwidth, factor*ascender, fgcolor); + FillRect(PosX, PosY + yoffset + factor*ascender, curfontwidth, factor*(fontheight-ascender), bgcolor); + PosX += curfontwidth; + return; + case 0xE0: /* |- */ + DrawHLine(PosX, PosY + yoffset, curfontwidth, fgcolor); + DrawVLine(PosX, PosY + yoffset +1, fontheight -1, fgcolor); + FillRect(PosX +1, PosY + yoffset +1, curfontwidth-1, fontheight-1, bgcolor); + PosX += curfontwidth; + return; + case 0xE1: /* - */ + DrawHLine(PosX, PosY + yoffset, curfontwidth, fgcolor); + FillRect(PosX, PosY + yoffset +1, curfontwidth, fontheight-1, bgcolor); + PosX += curfontwidth; + return; + case 0xE2: /* -| */ + DrawHLine(PosX, PosY + yoffset, curfontwidth, fgcolor); + DrawVLine(PosX + curfontwidth -1, PosY + yoffset +1, fontheight -1, fgcolor); + FillRect(PosX, PosY + yoffset +1, curfontwidth-1, fontheight-1, bgcolor); + PosX += curfontwidth; + return; + case 0xE3: /* | */ + DrawVLine(PosX, PosY + yoffset, fontheight, fgcolor); + FillRect(PosX +1, PosY + yoffset, curfontwidth -1, fontheight, bgcolor); + PosX += curfontwidth; + return; + case 0xE4: /* | */ + DrawVLine(PosX + curfontwidth -1, PosY + yoffset, fontheight, fgcolor); + FillRect(PosX, PosY + yoffset, curfontwidth -1, fontheight, bgcolor); + PosX += curfontwidth; + return; + case 0xE5: /* |_ */ + DrawHLine(PosX, PosY + yoffset + fontheight -1, curfontwidth, fgcolor); + DrawVLine(PosX, PosY + yoffset, fontheight -1, fgcolor); + FillRect(PosX +1, PosY + yoffset, curfontwidth-1, fontheight-1, bgcolor); + PosX += curfontwidth; + return; + case 0xE6: /* _ */ + DrawHLine(PosX, PosY + yoffset + fontheight -1, curfontwidth, fgcolor); + FillRect(PosX, PosY + yoffset, curfontwidth, fontheight-1, bgcolor); + PosX += curfontwidth; + return; + case 0xE7: /* _| */ + DrawHLine(PosX, PosY + yoffset + fontheight -1, curfontwidth, fgcolor); + DrawVLine(PosX + curfontwidth -1, PosY + yoffset, fontheight -1, fgcolor); + FillRect(PosX, PosY + yoffset, curfontwidth-1, fontheight-1, bgcolor); + PosX += curfontwidth; + return; + case 0xE8: /* Ii */ + FillRect(PosX +1, PosY + yoffset, curfontwidth -1, fontheight, bgcolor); + for (Row=0; Row < curfontwidth/2; Row++) + DrawVLine(PosX + Row, PosY + yoffset + Row, fontheight - Row, fgcolor); + PosX += curfontwidth; + return; + case 0xE9: /* II */ + FillRect(PosX, PosY + yoffset, curfontwidth/2, fontheight, fgcolor); + FillRect(PosX + curfontwidth/2, PosY + yoffset, (curfontwidth+1)/2, fontheight, bgcolor); + PosX += curfontwidth; + return; + case 0xEA: /* ° */ + FillRect(PosX, PosY + yoffset, curfontwidth, fontheight, bgcolor); + FillRect(PosX, PosY + yoffset, curfontwidth/2, curfontwidth/2, fgcolor); + PosX += curfontwidth; + return; + case 0xEB: /* ¬ */ + FillRect(PosX, PosY + yoffset +1, curfontwidth, fontheight -1, bgcolor); + for (Row=0; Row < curfontwidth/2; Row++) + DrawHLine(PosX + Row, PosY + yoffset + Row, curfontwidth - Row, fgcolor); + PosX += curfontwidth; + return; + case 0xEC: /* -- */ + FillRect(PosX, PosY + yoffset, curfontwidth, curfontwidth/2, fgcolor); + FillRect(PosX, PosY + yoffset + curfontwidth/2, curfontwidth, fontheight - curfontwidth/2, bgcolor); + PosX += curfontwidth; + return; + case 0xED: + case 0xEE: + case 0xEF: + case 0xF0: + case 0xF1: + case 0xF2: + case 0xF3: + case 0xF4: + case 0xF5: + case 0xF6: + Char = arrowtable[Char - 0xED]; + break; + default: + break; + } + } + if (Char <= 0x20) + { +#if 0//TUXTXT_DEBUG + printf("TuxTxt found control char: %x \"%c\" \n", Char, Char); +#endif + FillRect(PosX, PosY + yoffset, curfontwidth, factor*fontheight, bgcolor); + PosX += curfontwidth; + return; + } + + + if (!(glyph = FT_Get_Char_Index(face, Char))) + { +#if 1// TUXTXT_DEBUG + printf("TuxTxt c%x a%x g%x w%d h%d x%d y%d\n", + error, Char, (int) Attribute, glyph, curfontwidth, fontheight, PosX, PosY); +#endif + FillRect(PosX, PosY + yoffset, curfontwidth, fontheight, bgcolor); + PosX += curfontwidth; + return; + } + + /* render char */ + sbitbuffer = sbit->buffer; + char localbuffer[1000]; // should be enough to store one character-bitmap... + // add diacritical marks + if (Attribute->diacrit) + { + FTC_SBit sbit_diacrit; +#if 0 + if (national_subset_local == NAT_GR) + Char = G2table[2][0x20+ Attribute->diacrit]; + else if (national_subset_local == NAT_RU) + Char = G2table[1][0x20+ Attribute->diacrit]; + else + Char = G2table[0][0x20+ Attribute->diacrit]; +#endif + if ((national_subset_local == NAT_SC) || (national_subset_local == NAT_RB) || (national_subset_local == NAT_UA)) + Char = G2table[1][0x20+ Attribute->diacrit]; + else if (national_subset_local == NAT_GR) + Char = G2table[2][0x20+ Attribute->diacrit]; +#if 0 + else if (national_subset_local == NAT_HB) + Char = G2table[3][0x20+ Attribute->diacrit]; +#endif + else if (national_subset_local == NAT_AR) + Char = G2table[3][0x20+ Attribute->diacrit]; + else + Char = G2table[0][0x20+ Attribute->diacrit]; + + if ((glyph = FT_Get_Char_Index(face, Char))) + { + if ((error = FTC_SBitCache_Lookup(cache, &typettf, glyph, &sbit_diacrit, NULL)) == 0) + + { + sbitbuffer = (unsigned char*) localbuffer; + memmove(sbitbuffer,sbit->buffer,sbit->pitch*sbit->height); + + for (Row = 0; Row < sbit->height; Row++) + { + for (Pitch = 0; Pitch < sbit->pitch; Pitch++) + { + if (sbit_diacrit->pitch > Pitch && sbit_diacrit->height > Row) + if((sbit_diacrit->pitch*sbit_diacrit->height) > (Row*sbit->pitch+Pitch)) + sbitbuffer[Row*sbit->pitch+Pitch] |= sbit_diacrit->buffer[Row*sbit->pitch+Pitch]; + } + } + } + } + } + + unsigned char *p; + int f; /* running counter for zoom factor */ + + Row = factor * (ascender - sbit->top + TTFShiftY); + FillRect(PosX, PosY + yoffset, curfontwidth, Row, bgcolor); /* fill upper margin */ + + if (ascender - sbit->top + TTFShiftY + sbit->height > fontheight) + sbit->height = fontheight - ascender + sbit->top - TTFShiftY; /* limit char height to defined/calculated fontheight */ + + int y = yoffset; + p = getFBp(&y); + p += PosX * 4 + (PosY + Row) * fix_screeninfo.line_length; /* running pointer into framebuffer */ + + for (Row = sbit->height; Row; Row--) /* row counts up, but down may be a little faster :) */ + { + int pixtodo = (usettf ? sbit->width : curfontwidth); + char *pstart = (char*) p; + + for (Bit = xfactor * (sbit->left + TTFShiftX); Bit > 0; Bit--) /* fill left margin */ + { + for (f = factor-1; f >= 0; f--) + memmove((p + f*fix_screeninfo.line_length),bgra[bgcolor],4);/*bgcolor*/ + p+=4; + if (!usettf) + pixtodo--; + } + + for (Pitch = sbit->pitch; Pitch; Pitch--) + { + for (Bit = 0x80; Bit; Bit >>= 1) + { + int color; + + if (--pixtodo < 0) + break; + + if (*sbitbuffer & Bit) /* bit set -> foreground */ + color = fgcolor; + else /* bit not set -> background */ + color = bgcolor; + + for (f = factor-1; f >= 0; f--) + memmove((p + f*fix_screeninfo.line_length),bgra[color],4); + p+=4; + + if (xfactor > 1) /* double width */ + { + for (f = factor-1; f >= 0; f--) + memmove((p + f*fix_screeninfo.line_length),bgra[color],4); + p+=4; + + if (!usettf) + pixtodo--; + } + } + sbitbuffer++; + } + for (Bit = (usettf ? (curfontwidth - xfactor*(sbit->width + sbit->left + TTFShiftX)) : pixtodo); + Bit > 0; Bit--) /* fill rest of char width */ + { + for (f = factor-1; f >= 0; f--) + memmove((p + f*fix_screeninfo.line_length),bgra[bgcolor],4); + p+=4; + } + + p = (unsigned char*) pstart + factor*fix_screeninfo.line_length; + } + + Row = ascender - sbit->top + sbit->height + TTFShiftY; + FillRect(PosX, PosY + yoffset + Row*factor, curfontwidth, (fontheight - Row) * factor, bgcolor); /* fill lower margin */ + if (Attribute->underline) + FillRect(PosX, PosY + yoffset + (fontheight-2)* factor, curfontwidth,2*factor, fgcolor); /* underline char */ + + PosX += curfontwidth; +} + +/****************************************************************************** + * RenderCharFB * + ******************************************************************************/ + +void RenderCharFB(int Char, tstPageAttr *Attribute) +{ + RenderChar(Char, Attribute, zoommode, var_screeninfo.yoffset); +} + +/****************************************************************************** + * RenderCharBB * + ******************************************************************************/ + +void RenderCharBB(int Char, tstPageAttr *Attribute) +{ + RenderChar(Char, Attribute, 0, var_screeninfo.yres-var_screeninfo.yoffset); +} + +/****************************************************************************** + * RenderCharLCD * + ******************************************************************************/ + +void RenderCharLCD(int /*Digit*/, int /*XPos*/, int /*YPos*/) +{ +#if 0 + int x, y; + + /* render digit to lcd backbuffer */ + for (y = 0; y < 15; y++) + { + for (x = 0; x < 10; x++) + { + if (lcd_digits[Digit*15*10 + x + y*10]) + lcd_backbuffer[XPos + x + ((YPos+y)/8)*120] |= 1 << ((YPos+y)%8); + else + lcd_backbuffer[XPos + x + ((YPos+y)/8)*120] &= ~(1 << ((YPos+y)%8)); + } + } +#endif +} + +#if 0 +void RenderCharLCDsmall(int Char, int XPos, int YPos) +{ + int old_width = fontwidth; + int old_height = fontheight; + setfontwidth(fontwidth_small_lcd); + typettf.font.pix_height = fontheight = fontwidth_small_lcd; + RenderChar(Char, 0, 0, -(YPos<<8 | XPos)); + setfontwidth(old_width); + typettf.font.pix_height = fontheight = old_height; +} +#endif + +/****************************************************************************** + * RenderMessage * + ******************************************************************************/ + +void RenderMessage(int Message) +{ + int byte; + int fbcolor, imenuatr; + int pagecolumn; + const char *msg; + int national_subset_back = national_subset; + national_subset = menusubset[menulanguage]; + +/* 00000000001111111111222222222233333333334 */ +/* 01234567890123456789012345678901234567890 */ + char message_1[] = "àááááááá www.tuxtxt.com x.xx áááááááâè"; + char message_2[] = "ã äé"; +/* char message_3[] = "ã suche nach Teletext-Anbietern äé"; */ + char message_4[] = "ã äé"; + char message_5[] = "åæææææææææææææææææææææææææææææææææææçé"; + char message_6[] = "ëììììììììììììììììììììììììììììììììììììê"; + +/* char message_7[] = "ã kein Teletext auf dem Transponder äé"; */ +/* char message_8[] = "ã warte auf Empfang von Seite 100 äé"; */ +/* char message_9[] = "ã Seite 100 existiert nicht! äé"; */ + + memmove(&message_1[24], versioninfo, 4); + /* reset zoom */ + zoommode = 0; + + /* set colors */ + fbcolor = transp; + imenuatr = ATR_MSG0; + + /* clear framebuffer */ + ClearFB(fbcolor); + + /* hide header */ + page_atrb[32].fg = transp; + page_atrb[32].bg = transp; + + + /* set pagenumber */ + if (Message == ShowServiceName) + { + pagecolumn = message8pagecolumn[menulanguage]; + msg = message_8[menulanguage]; + memmove(&message_4, msg, sizeof(message_4)); + hex2str(message_4+pagecolumn, tuxtxt_cache.page); + + if (SDT_ready) + memmove(&message_2[2 + (35 - pid_table[current_service].service_name_len)/2], + &pid_table[current_service].service_name, pid_table[current_service].service_name_len); + else if (Message == ShowServiceName) + hex2str(&message_2[17+3], tuxtxt_cache.vtxtpid); + + msg = &message_3_blank[0]; + } + else if (Message == NoServicesFound) + msg = &message_7[menulanguage][0]; + else + msg = &message_3[menulanguage][0]; + + /* render infobar */ + PosX = StartX + fontwidth+5; + PosY = StartY + fontheight*16; + for (byte = 0; byte < 37; byte++) + RenderCharFB(message_1[byte], &atrtable[imenuatr + ((byte >= 9 && byte <= 27) ? 1 : 0)]); + RenderCharFB(message_1[37], &atrtable[imenuatr + 2]); + + PosX = StartX + fontwidth+5; + PosY = StartY + fontheight*17; + RenderCharFB(message_2[0], &atrtable[imenuatr + 0]); + for (byte = 1; byte < 36; byte++) + RenderCharFB(message_2[byte], &atrtable[imenuatr + 3]); + RenderCharFB(message_2[36], &atrtable[imenuatr + 0]); + RenderCharFB(message_2[37], &atrtable[imenuatr + 2]); + + PosX = StartX + fontwidth+5; + PosY = StartY + fontheight*18; + RenderCharFB(msg[0], &atrtable[imenuatr + 0]); + for (byte = 1; byte < 36; byte++) + RenderCharFB(msg[byte], &atrtable[imenuatr + 3]); + RenderCharFB(msg[36], &atrtable[imenuatr + 0]); + RenderCharFB(msg[37], &atrtable[imenuatr + 2]); + + PosX = StartX + fontwidth+5; + PosY = StartY + fontheight*19; + RenderCharFB(message_4[0], &atrtable[imenuatr + 0]); + for (byte = 1; byte < 36; byte++) + RenderCharFB(message_4[byte], &atrtable[imenuatr + 3]); + RenderCharFB(message_4[36], &atrtable[imenuatr + 0]); + RenderCharFB(message_4[37], &atrtable[imenuatr + 2]); + + PosX = StartX + fontwidth+5; + PosY = StartY + fontheight*20; + for (byte = 0; byte < 37; byte++) + RenderCharFB(message_5[byte], &atrtable[imenuatr + 0]); + RenderCharFB(message_5[37], &atrtable[imenuatr + 2]); + + PosX = StartX + fontwidth+5; + PosY = StartY + fontheight*21; + for (byte = 0; byte < 38; byte++) + RenderCharFB(message_6[byte], &atrtable[imenuatr + 2]); + national_subset = national_subset_back; +} + +/****************************************************************************** + * RenderPage * + ******************************************************************************/ + +void DoFlashing(int startrow) +{ + int row, col; + /* get national subset */ + if (auto_national && + national_subset <= NAT_MAX_FROM_HEADER && /* not for GR/RU as long as line28 is not evaluated */ + pageinfo && pageinfo->nationalvalid) /* individual subset according to page header */ + { + national_subset = countryconversiontable[pageinfo->national]; + } + /* Flashing */ + tstPageAttr flashattr; + char flashchar; + struct timeval tv; + gettimeofday(&tv,NULL); + long flashphase = (tv.tv_usec / 1000) % 1000; + int srow = startrow; + int erow = 24; + int factor=1; + switch (zoommode) + { + case 1: erow = 12; factor=2;break; + case 2: srow = 12; factor=2;break; + } + PosY = StartY + startrow*fontheight*factor; + for (row = srow; row < erow; row++) + { + int index = row * 40; + int dhset = 0; + int incflash = 3; + int decflash = 2; + PosX = StartX; + for (col = nofirst; col < 40; col++) + { + if (page_atrb[index + col].flashing && page_char[index + col] > 0x20 && page_char[index + col]!= 0xff ) + { + SetPosX(col); + flashchar = page_char[index + col]; + int doflash = 0; + memmove(&flashattr,&page_atrb[index + col],sizeof(tstPageAttr)); + switch (flashattr.flashing &0x1c) // Flash Rate + { + case 0x00 : // 1 Hz + if (flashphase>500) doflash = 1; + break; + case 0x04 : // 2 Hz Phase 1 + if (flashphase<250) doflash = 1; + break; + case 0x08 : // 2 Hz Phase 2 + if (flashphase>=250 && flashphase<500) doflash = 1; + break; + case 0x0c : // 2 Hz Phase 3 + if (flashphase>=500 && flashphase<750) doflash = 1; + break; + case 0x10 : // incremental flash + incflash++; + if (incflash>3) incflash = 1; + switch (incflash) + { + case 1: if (flashphase<250) doflash = 1; break; + case 2: if (flashphase>=250 && flashphase<500) doflash = 1;break; + case 3: if (flashphase>=500 && flashphase<750) doflash = 1; + } + break; + case 0x11 : // decremental flash + decflash--; + if (decflash<1) decflash = 3; + switch (decflash) + { + case 1: if (flashphase<250) doflash = 1; break; + case 2: if (flashphase>=250 && flashphase<500) doflash = 1;break; + case 3: if (flashphase>=500 && flashphase<750) doflash = 1; + } + break; + + } + + switch (flashattr.flashing &0x03) // Flash Mode + { + case 0x01 : // normal Flashing + if (doflash) flashattr.fg = flashattr.bg; + break; + case 0x02 : // inverted Flashing + doflash = 1-doflash; + if (doflash) flashattr.fg = flashattr.bg; + break; + case 0x03 : // color Flashing + if (doflash) flashattr.fg = flashattr.fg + (flashattr.fg > 7 ? (-8) : 8); + break; + + } + RenderCharFB(flashchar,&flashattr); + if (flashattr.doublew) col++; + if (flashattr.doubleh) dhset = 1; + } + } + if (dhset) + { + row++; + PosY += fontheight*factor; + } + PosY += fontheight*factor; + } +} + +void RenderPage() +{ + int row, col, byte, startrow = 0;; + int national_subset_bak = national_subset; + + /* update lcd */ + UpdateLCD(); + + if (transpmode != 2 && delaystarted) + { + struct timeval tv; + gettimeofday(&tv,NULL); + if (tv.tv_sec - tv_delay.tv_sec < subtitledelay) + return; + } + + + /* update page or timestring */ + if (transpmode != 2 && tuxtxt_cache.pageupdate && tuxtxt_cache.page_receiving != tuxtxt_cache.page && inputcounter == 2) + { + if (boxed && subtitledelay) + { + if (!delaystarted) + { + gettimeofday(&tv_delay,NULL); + delaystarted = 1; + return; + } + else + delaystarted = 0; + } + + /* reset update flag */ + tuxtxt_cache.pageupdate = 0; + + + /* decode page */ + if (tuxtxt_cache.subpagetable[tuxtxt_cache.page] != 0xFF) + DecodePage(); + else + startrow = 1; + + if (boxed) + { + if (screenmode != 0) + SwitchScreenMode(0); /* turn off divided screen */ + } + else + { + if (screenmode != prevscreenmode && !transpmode) + SwitchScreenMode(prevscreenmode); + } + + /* display first column? */ + nofirst = show39; + for (row = 1; row < 24; row++) + { + byte = page_char[row*40]; + if (byte != ' ' && byte != 0x00 && byte != 0xFF && + page_atrb[row*40].fg != page_atrb[row*40].bg) + { + nofirst = 0; + break; + } + } + fontwidth_normal = (ex-sx) / (40-nofirst); + setfontwidth(fontwidth_normal); + fontwidth_topmenumain = (TV43STARTX-sx) / (40-nofirst); + fontwidth_topmenusmall = (TVENDX - TOPMENUSTARTX) / TOPMENUCHARS; + //fontwidth_small = (TV169FULLSTARTX-sx) / (40-nofirst); + fontwidth_small = (screen_w / 2) / (40 - nofirst); + switch(screenmode) + { + case 0: + case 1: setfontwidth(fontwidth_normal); + displaywidth = ex - sx; + break; + case 2: setfontwidth(fontwidth_small); + displaywidth = screen_w / 2; + break; + } + if (transpmode || (boxed && !screenmode)) + { + FillBorder(transp);//ClearBB(transp); + clearbbcolor = transp; + } + + /* get national subset */ + if (auto_national && + national_subset <= NAT_MAX_FROM_HEADER && /* not for GR/RU as long as line28 is not evaluated */ + pageinfo && pageinfo->nationalvalid) /* individual subset according to page header */ + { +#if TUXTXT_DEBUG + printf("p%03x bak %d nat %d valid %d info nat %d\n", tuxtxt_cache.page,national_subset_bak, national_subset, pageinfo->nationalvalid, pageinfo->national); +#endif + national_subset = countryconversiontable[pageinfo->national]; + } + /* render page */ + PosY = StartY + startrow*fontheight; + for (row = startrow; row < 24; row++) + { + int index = row * 40; + + PosX = StartX; + for (col = nofirst; col < 40; col++) + { + RenderCharBB(page_char[index + col], &page_atrb[index + col]); + + if (page_atrb[index + col].doubleh && page_char[index + col] != 0xff) /* disable lower char in case of doubleh setting in l25 objects */ + page_char[index + col + 40] = 0xff; + if (page_atrb[index + col].doublew) /* skip next column if double width */ + { + col++; + if (page_atrb[index + col-1].doubleh && page_char[index + col] != 0xff) /* disable lower char in case of doubleh setting in l25 objects */ + page_char[index + col + 40] = 0xff; + } + } + PosY += fontheight; + } + DoFlashing(startrow); + national_subset = national_subset_bak; + + /* update framebuffer */ + CopyBB2FB(); + } + else if (use_gui && transpmode != 2) + { + if (zoommode != 2) + { + PosY = StartY; + if (tuxtxt_cache.subpagetable[tuxtxt_cache.page] == 0xff) + { + page_atrb[32].fg = yellow; + page_atrb[32].bg = menu1; + int showpage = tuxtxt_cache.page_receiving; + int showsubpage = tuxtxt_cache.subpagetable[showpage]; + if (showsubpage!=0xff) + { + + tstCachedPage *pCachedPage; + pCachedPage = tuxtxt_cache.astCachetable[showpage][showsubpage]; + if (pCachedPage && tuxtxt_is_dec(showpage)) + { + PosX = StartX; + if (inputcounter == 2) + { + if (tuxtxt_cache.bttok && !tuxtxt_cache.basictop[tuxtxt_cache.page]) /* page non-existent according to TOP (continue search anyway) */ + { + page_atrb[0].fg = white; + page_atrb[0].bg = red; + } + else + { + page_atrb[0].fg = yellow; + page_atrb[0].bg = menu1; + } + hex2str((char*) page_char+3, tuxtxt_cache.page); + for (col = nofirst; col < 7; col++) // selected page + { + RenderCharFB(page_char[col], &page_atrb[0]); + } + RenderCharFB(page_char[col], &page_atrb[32]); + } + else + SetPosX(8); + + memmove(&page_char[8], pCachedPage->p0, 24); /* header line without timestring */ + for (col = 0; col < 24; col++) + { + RenderCharFB(pCachedPage->p0[col], &page_atrb[32]); + } + } + } + } + /* update timestring */ + SetPosX(32); + for (byte = 0; byte < 8; byte++) + { + if (!page_atrb[32+byte].flashing) + RenderCharFB(tuxtxt_cache.timestring[byte], &page_atrb[32]); + else + { + SetPosX(33+byte); + page_char[32+byte] = page_char[32+byte]; + } + + + } + } + DoFlashing(startrow); + national_subset = national_subset_bak; + } + else if (transpmode == 2 && tuxtxt_cache.pageupdate == 2) + { +#if TUXTXT_DEBUG + printf("received Update flag for page %03x\n",tuxtxt_cache.page); +#endif + // display pagenr. when page has been updated while in transparency mode + PosY = StartY; + + char ns[3]; + SetPosX(1); + hex2str(ns+2,tuxtxt_cache.page); + + RenderCharFB(ns[0],&atrtable[ATR_WB]); + RenderCharFB(ns[1],&atrtable[ATR_WB]); + RenderCharFB(ns[2],&atrtable[ATR_WB]); + + tuxtxt_cache.pageupdate=0; + } +} + +/****************************************************************************** + * CreateLine25 * + ******************************************************************************/ + +void showlink(int column, int linkpage) +{ + unsigned char *p, line[] = " >??? "; + int oldfontwidth = fontwidth; + int yoffset; + +#ifdef USE_FBPAN + if (var_screeninfo.yoffset) + yoffset = 0; + else + yoffset = var_screeninfo.yres; +#else + yoffset = var_screeninfo.yres; //NEW +#endif + + int abx = ((displaywidth)%(40-nofirst) == 0 ? displaywidth+1 : (displaywidth)/(((displaywidth)%(40-nofirst)))+1);// distance between 'inserted' pixels + int width = displaywidth /4; + + PosY = StartY + 24*fontheight; + + if (boxed) + { + PosX = StartX + column*width; + FillRect(PosX, PosY+yoffset, displaywidth, fontheight, transp); + return; + } + + if (tuxtxt_cache.adip[linkpage][0]) + { + PosX = StartX + column*width; + int l = strlen((char*) tuxtxt_cache.adip[linkpage]); + + if (l > 9) /* smaller font, if no space for one half space at front and end */ + setfontwidth(oldfontwidth * 10 / (l+1)); + FillRect(PosX, PosY+yoffset, width+(displaywidth%4), fontheight, atrtable[ATR_L250 + column].bg); + PosX += ((width) - (l*fontwidth+l*fontwidth/abx))/2; /* center */ + for (p = tuxtxt_cache.adip[linkpage]; *p; p++) + RenderCharBB(*p, &atrtable[ATR_L250 + column]); + setfontwidth(oldfontwidth); + } + else /* display number */ + { + PosX = StartX + column*width; + //FillRect(PosX, PosY+yoffset, displaywidth+sx-PosX, fontheight, atrtable[ATR_L250 + column].bg); + FillRect(PosX, PosY+yoffset, width, fontheight, atrtable[ATR_L250 + column].bg); + if (linkpage < tuxtxt_cache.page) + { + line[6] = '<'; + hex2str((char*) line + 5, linkpage); + } + else + hex2str((char*) line + 6, linkpage); + for (p = line; p < line+9; p++) + RenderCharBB(*p, &atrtable[ATR_L250 + column]); + } +} + +void CreateLine25() +{ + + if (!tuxtxt_cache.bttok) + /* btt completely received and not yet decoded */ + tuxtxt_decode_btt(); + if (tuxtxt_cache.maxadippg >= 0) + tuxtxt_decode_adip(); + + if (!showhex && showflof && + (tuxtxt_cache.flofpages[tuxtxt_cache.page][0] || tuxtxt_cache.flofpages[tuxtxt_cache.page][1] || tuxtxt_cache.flofpages[tuxtxt_cache.page][2] || tuxtxt_cache.flofpages[tuxtxt_cache.page][3])) // FLOF-Navigation present + { + int i; + + prev_100 = tuxtxt_cache.flofpages[tuxtxt_cache.page][0]; + prev_10 = tuxtxt_cache.flofpages[tuxtxt_cache.page][1]; + next_10 = tuxtxt_cache.flofpages[tuxtxt_cache.page][2]; + next_100 = tuxtxt_cache.flofpages[tuxtxt_cache.page][3]; + + PosY = StartY + 24*fontheight; + PosX = StartX; + for (i=nofirst; i<40; i++) + RenderCharBB(page_char[24*40 + i], &page_atrb[24*40 + i]); + } + else + { + /* normal: blk-1, grp+1, grp+2, blk+1 */ + /* hex: hex+1, blk-1, grp+1, blk+1 */ + if (showhex) + { + /* arguments: startpage, up, findgroup */ + prev_100 = tuxtxt_next_hex(tuxtxt_cache.page); + prev_10 = toptext_getnext(tuxtxt_cache.page, 0, 0); + next_10 = toptext_getnext(tuxtxt_cache.page, 1, 1); + } + else + { + prev_100 = toptext_getnext(tuxtxt_cache.page, 0, 0); + prev_10 = toptext_getnext(tuxtxt_cache.page, 1, 1); + next_10 = toptext_getnext(prev_10, 1, 1); + } + next_100 = toptext_getnext(next_10, 1, 0); + showlink(0, prev_100); + showlink(1, prev_10); + showlink(2, next_10); + showlink(3, next_100); + } + + if (tuxtxt_cache.bttok && + screenmode == 1) /* TOP-Info present, divided screen -> create TOP overview */ + { + char line[TOPMENUCHARS]; + int current; + int prev10done, next10done, next100done, indent; + tstPageAttr *attrcol, *attr; /* color attribute for navigation keys and text */ + + int olddisplaywidth = displaywidth; + displaywidth = 1000*(40-nofirst); // disable pixelinsert; + setfontwidth(fontwidth_topmenusmall); + + PosY = TOPMENUSTARTY; + memset(line, ' ', TOPMENUCHARS); /* init with spaces */ + + memmove(line+TOPMENUINDENTBLK, tuxtxt_cache.adip[prev_100], 12); + hex2str(&line[TOPMENUINDENTDEF+12+TOPMENUSPC+2], prev_100); + RenderClearMenuLineBB(line, &atrtable[ATR_L250], &atrtable[ATR_TOPMENU2]); + +/* 1: blk-1, grp-1, grp+1, blk+1 */ +/* 2: blk-1, grp+1, grp+2, blk+1 */ +#if (LINE25MODE == 1) + current = prev_10 - 1; +#else + current = tuxtxt_cache.page - 1; +#endif + + prev10done = next10done = next100done = 0; + while (PosY <= (tv_pip_y - fontheight)) + { + attr = 0; + attrcol = &atrtable[ATR_WB]; + if (!next100done && (PosY > (tv_pip_y - 2*fontheight))) /* last line */ + { + attrcol = &atrtable[ATR_L253]; + current = next_100; + } + else if (!next10done && (PosY > (tv_pip_y - 3*fontheight))) /* line before */ + { + attrcol = &atrtable[ATR_L252]; + current = next_10; + } + else if (!prev10done && (PosY > (tv_pip_y - 4*fontheight))) /* line before */ + { + attrcol = &atrtable[ATR_L251]; + current = prev_10; + } + else do + { + tuxtxt_next_dec(¤t); + if (current == prev_10) + { + attrcol = &atrtable[ATR_L251]; + prev10done = 1; + break; + } + else if (current == next_10) + { + attrcol = &atrtable[ATR_L252]; + next10done = 1; + break; + } + else if (current == next_100) + { + attrcol = &atrtable[ATR_L253]; + next100done = 1; + break; + } + else if (current == tuxtxt_cache.page) + { + attr = &atrtable[ATR_TOPMENU0]; + break; + } + } while (tuxtxt_cache.adip[current][0] == 0 && (tuxtxt_cache.basictop[current] < 2 || tuxtxt_cache.basictop[current] > 7)); + + if (!tuxtxt_cache.bttok || (tuxtxt_cache.basictop[current] >= 2 && tuxtxt_cache.basictop[current] <= 5)) /* block (also for FLOF) */ + { + indent = TOPMENUINDENTBLK; + if (!attr) + attr = &atrtable[tuxtxt_cache.basictop[current] <=3 ? ATR_TOPMENU1 : ATR_TOPMENU2]; /* green for program block */ + } + else if (tuxtxt_cache.basictop[current] >= 6 && tuxtxt_cache.basictop[current] <= 7) /* group */ + { + indent = TOPMENUINDENTGRP; + if (!attr) + attr = &atrtable[ATR_TOPMENU3]; + } + else + { + indent = TOPMENUINDENTDEF; + if (!attr) + attr = &atrtable[ATR_WB]; + } + memmove(line+indent, tuxtxt_cache.adip[current], 12); + hex2str(&line[TOPMENUINDENTDEF+12+TOPMENUSPC+2], current); + RenderClearMenuLineBB(line, attrcol, attr); + } + displaywidth = olddisplaywidth; + setfontwidth(fontwidth_topmenumain); + } +} + +/****************************************************************************** + * CopyBB2FB * + ******************************************************************************/ + +void CopyBB2FB() +{ + unsigned char *src, *dst, *topsrc; + int fillcolor, i, screenwidth, swtmp; +#ifdef HAVE_SPARK_HARDWARE + CFrameBuffer *f = CFrameBuffer::getInstance(); +#endif + + /* line 25 */ + if (!pagecatching && use_gui) + CreateLine25(); + + /* copy backbuffer to framebuffer */ + if (!zoommode) + { +#ifdef USE_FBPAN + /* if yoffset != 0, we had active page 1, and activate 0 */ + /* else active was page 0, activate page 1 */ + if (var_screeninfo.yoffset) + var_screeninfo.yoffset = 0; + else + var_screeninfo.yoffset = var_screeninfo.yres; + + //FIXME check zoom mode code + if (ioctl(fb, FBIOPAN_DISPLAY, &var_screeninfo) == -1) + perror("TuxTxt "); +#else +#ifdef HAVE_SPARK_HARDWARE + f->blit2FB(lbb, var_screeninfo.xres, var_screeninfo.yres, 0, 0, 0, 0, true); +#else + memcpy(lfb, lbb, fix_screeninfo.line_length*var_screeninfo.yres); +#endif +#endif + + /* adapt background of backbuffer if changed */ + if (StartX > 0 && *lfb != *lbb) { + FillBorder(*lbb); +// ClearBB(*(lfb + var_screeninfo.xres * var_screeninfo.yoffset)); + } + + if (clearbbcolor >= 0) + { +// ClearBB(clearbbcolor); + clearbbcolor = -1; + } + return; + } + + src = topsrc = lbb + StartY * fix_screeninfo.line_length; + dst = lfb + StartY * fix_screeninfo.line_length; + +#ifdef USE_FBPAN + #error USE_FBPAN code is not working right now. + if (var_screeninfo.yoffset) + dst += fix_screeninfo.line_length * var_screeninfo.yres; + else + { + src += fix_screeninfo.line_length * var_screeninfo.yres; + topsrc += fix_screeninfo.line_length * var_screeninfo.yres; + } +#endif + /* copy line25 in normal height */ + if (!pagecatching ) + memmove(dst+(24*fontheight)*fix_screeninfo.line_length, src + (24*fontheight)*fix_screeninfo.line_length, fix_screeninfo.line_length*fontheight); + + if (transpmode) + fillcolor = transp; + else + fillcolor = FullScrColor; + + if (zoommode == 2) + src += 12*fontheight*fix_screeninfo.line_length; + + /* copy topmenu in normal height (since PIG also keeps dimensions) */ + if (screenmode == 1) + { + screenwidth = ( TV43STARTX ) * 4; +#ifdef HAVE_SPARK_HARDWARE + int cx = var_screeninfo.xres - TV43STARTX; /* x start */ + int cw = TV43STARTX; /* width */ + int cy = StartY; + int ch = 24*fontheight; + f->blit2FB(lbb, cw, ch, cx, cy, cx, cy, true); +#else + unsigned char *topdst = dst; + size_t width = ex * sizeof(fb_pixel_t) - screenwidth; + + topsrc += screenwidth; + topdst += screenwidth; + for (i=0; i < 24*fontheight; i++) + { + memmove(topdst, topsrc, width); + topdst += fix_screeninfo.line_length; + topsrc += fix_screeninfo.line_length; + } +#endif + } + else if (screenmode == 2) + screenwidth = ( TV169FULLSTARTX ) * 4; + else + screenwidth = fix_screeninfo.line_length;//var_screeninfo.xres; + + for (i = StartY; i>0;i--) + { + for (swtmp=0; swtmp<=screenwidth; swtmp++) + { + memmove(dst - i*fix_screeninfo.line_length+swtmp*4, bgra[fillcolor], 4); + } + } + + for (i = 12*fontheight; i; i--) + { + memmove(dst, src, screenwidth); + dst += fix_screeninfo.line_length; + memmove(dst, src, screenwidth); + dst += fix_screeninfo.line_length; + src += fix_screeninfo.line_length; + } + + for (i = var_screeninfo.yres - StartY - 25*fontheight; i >= 0;i--) + { + for (swtmp=0; swtmp<= screenwidth;swtmp++) + { + memmove(dst + fix_screeninfo.line_length*(fontheight+i)+swtmp*4, bgra[fillcolor], 4); + } + } +#ifdef HAVE_SPARK_HARDWARE + f->mark(0, 0, var_screeninfo.xres, var_screeninfo.yres); +#endif +} + +/****************************************************************************** + * UpdateLCD * + ******************************************************************************/ + +void UpdateLCD() +{ +#if 0 + static int init_lcd = 1, old_cached_pages = -1, old_page = -1, old_subpage = -1, old_subpage_max = -1, old_hintmode = -1; + int x, y, subpage_max = 0, update_lcd = 0; + + if (lcd == -1) return; // for Dreamboxes without LCD-Display (5xxx) + /* init or update lcd */ + if (init_lcd) + { + init_lcd = 0; + + for (y = 0; y < 64; y++) + { + int lcdbase = (y/8)*120; + int lcdmask = 1 << (y%8); + + for (x = 0; x < 120; ) + { + int rommask; + int rombyte = lcd_layout[x/8 + y*120/8]; + + for (rommask = 0x80; rommask; rommask >>= 1) + { + if (rombyte & rommask) + lcd_backbuffer[x + lcdbase] |= lcdmask; + else + lcd_backbuffer[x + lcdbase] &= ~lcdmask; + x++; + } + } + } + + write(lcd, &lcd_backbuffer, sizeof(lcd_backbuffer)); + + for (y = 16; y < 56; y += 8) /* clear rectangle in backbuffer */ + for (x = 1; x < 118; x++) + lcd_backbuffer[x + (y/8)*120] = 0; + + for (x = 3; x <= 116; x++) + lcd_backbuffer[x + (39/8)*120] |= 1 << (39%8); + + for (y = 42; y <= 60; y++) + lcd_backbuffer[35 + (y/8)*120] |= 1 << (y%8); + + for (y = 42; y <= 60; y++) + lcd_backbuffer[60 + (y/8)*120] |= 1 << (y%8); + + RenderCharLCD(10, 43, 20); + RenderCharLCD(11, 79, 20); + + return; + } + else + { + int p; + + if (inputcounter == 2) + p = tuxtxt_cache.page; + else + p = temp_page + (0xDD >> 4*(1-inputcounter)); /* partial pageinput (filled with spaces) */ + + /* page */ + if (old_page != p) + { + RenderCharLCD(p>>8, 7, 20); + RenderCharLCD((p&0x0F0)>>4, 19, 20); + RenderCharLCD(p&0x00F, 31, 20); + + old_page = p; + update_lcd = 1; + } + + /* current subpage */ + if (old_subpage != tuxtxt_cache.subpage) + { + if (!tuxtxt_cache.subpage) + { + RenderCharLCD(0, 55, 20); + RenderCharLCD(1, 67, 20); + } + else + { + if (tuxtxt_cache.subpage >= 0xFF) + tuxtxt_cache.subpage = 1; + else if (tuxtxt_cache.subpage > 99) + tuxtxt_cache.subpage = 0; + + RenderCharLCD(tuxtxt_cache.subpage>>4, 55, 20); + RenderCharLCD(tuxtxt_cache.subpage&0x0F, 67, 20); + } + + old_subpage = tuxtxt_cache.subpage; + update_lcd = 1; + } + + /* max subpage */ + for (x = 0; x <= 0x79; x++) + { + if (tuxtxt_cache.astCachetable[tuxtxt_cache.page][x]) + subpage_max = x; + } + + if (old_subpage_max != subpage_max) + { + if (!subpage_max) + { + RenderCharLCD(0, 91, 20); + RenderCharLCD(1, 103, 20); + } + else + { + RenderCharLCD(subpage_max>>4, 91, 20); + RenderCharLCD(subpage_max&0x0F, 103, 20); + } + + old_subpage_max = subpage_max; + update_lcd = 1; + } + + /* cachestatus */ + if (old_cached_pages != tuxtxt_cache.cached_pages) + { + #if 0 + int s; + int p = tuxtxt_cache.cached_pages; + for (s=107; s >= 107-4*fontwidth_small_lcd; s -= fontwidth_small_lcd) + { + int c = p % 10; + if (p) + RenderCharLCDsmall('0'+c, s, 44); + else + RenderCharLCDsmall(' ', s, 44); + p /= 10; + } + #else + RenderCharLCD(tuxtxt_cache.cached_pages/1000, 67, 44); + RenderCharLCD(tuxtxt_cache.cached_pages%1000/100, 79, 44); + RenderCharLCD(tuxtxt_cache.cached_pages%100/10, 91, 44); + RenderCharLCD(tuxtxt_cache.cached_pages%10, 103, 44); + #endif + + old_cached_pages = tuxtxt_cache.cached_pages; + update_lcd = 1; + } + + /* mode */ + if (old_hintmode != hintmode) + { + if (hintmode) + RenderCharLCD(12, 43, 44); + else + RenderCharLCD(13, 43, 44); + + old_hintmode = hintmode; + update_lcd = 1; + } + } + + if (update_lcd) + write(lcd, &lcd_backbuffer, sizeof(lcd_backbuffer)); +#endif +} + +/****************************************************************************** + * DecodePage * + ******************************************************************************/ + +void DecodePage() +{ + int row, col; + int hold, dhset; + int foreground, background, doubleheight, doublewidth, charset, mosaictype, IgnoreAtBlackBgSubst, concealed, flashmode, boxwin; + unsigned char held_mosaic, *p; + tstCachedPage *pCachedPage; + + /* copy page to decode buffer */ + if (tuxtxt_cache.subpagetable[tuxtxt_cache.page] == 0xff) /* not cached: do nothing */ + return; + int tmp_subpage = tuxtxt_cache.zap_subpage_manual ? tuxtxt_cache.subpage : tuxtxt_cache.subpagetable[tuxtxt_cache.page]; + pCachedPage = tuxtxt_cache.astCachetable[tuxtxt_cache.page][tmp_subpage]; + if (!pCachedPage) /* not cached: do nothing */ + return; + + tuxtxt_decompress_page(tuxtxt_cache.page,tmp_subpage,&page_char[40]); + + memmove(&page_char[8], pCachedPage->p0, 24); /* header line without timestring */ + + pageinfo = &(pCachedPage->pageinfo); + if (pageinfo->p24) + memmove(&page_char[24*40], pageinfo->p24, 40); /* line 25 for FLOF */ + + /* copy timestring */ + memmove(&page_char[32], &tuxtxt_cache.timestring, 8); + + /* check for newsflash & subtitle */ + if (pageinfo->boxed && tuxtxt_is_dec(tuxtxt_cache.page)) + boxed = 1; + else + boxed = 0; + + + /* modify header */ + if (boxed) + memset(&page_char, ' ', 40); + else + { + memset(page_char, ' ', 8); + hex2str((char*) page_char+3, tuxtxt_cache.page); + if (tuxtxt_cache.subpage) + { + *(page_char+4) ='/'; + *(page_char+5) ='0'; + hex2str((char*) page_char+6, tuxtxt_cache.subpage); + } + + } + + if (!tuxtxt_is_dec(tuxtxt_cache.page)) + { + if (pageinfo->function == FUNC_MOT) /* magazine organization table */ + { +#if TUXTXT_DEBUG + printf("TuxTxt \n", tuxtxt_cache.page, tuxtxt_cache.subpage, pageinfo->function); +#endif + ClearBB(black); + for (col = 0; col < 24*40; col++) + page_atrb[col] = atrtable[ATR_WB]; + for (col = 40; col < 24*40; col++) + page_char[col] = number2char(page_char[col]); + boxed = 0; + return ; /* don't interpret irregular pages */ + } + else if (pageinfo->function == FUNC_GPOP || pageinfo->function == FUNC_POP) /* object definitions */ + { +#if TUXTXT_DEBUG + printf("TuxTxt \n", tuxtxt_cache.page, tuxtxt_cache.subpage, pageinfo->function); +#endif + ClearBB(black); + for (col = 0; col < 24*40; col++) + page_atrb[col] = atrtable[ATR_WB]; + p = page_char + 40; + for (row = 1; row < 12; row++) + { + *p++ = number2char(row); /* first column: number (0-9, A-..) */ + for (col = 1; col < 40; col += 3) + { + int d = deh24(p); + if (d < 0) + { + memmove(p, "???", 3); + p += 3; + } + else + { + *p++ = number2char((d >> 6) & 0x1f); /* mode */ + *p++ = number2char(d & 0x3f); /* address */ + *p++ = number2char((d >> 11) & 0x7f); /* data */ + } + } + } + boxed = 0; + return ; /* don't interpret irregular pages */ + } + else if (pageinfo->function == FUNC_GDRCS || pageinfo->function == FUNC_DRCS) /* character definitions */ + { + #define DRCSROWS 8 + #define DRCSCOLS (48/DRCSROWS) + #define DRCSZOOMX 3 + #define DRCSZOOMY 5 + #define DRCSXSPC (12*DRCSZOOMX + 2) + #define DRCSYSPC (10*DRCSZOOMY + 2) + + unsigned char ax[] = { /* array[0..12] of x-offsets, array[0..10] of y-offsets for each pixel */ + DRCSZOOMX * 0, + DRCSZOOMX * 1, + DRCSZOOMX * 2, + DRCSZOOMX * 3, + DRCSZOOMX * 4, + DRCSZOOMX * 5, + DRCSZOOMX * 6, + DRCSZOOMX * 7, + DRCSZOOMX * 8, + DRCSZOOMX * 9, + DRCSZOOMX * 10, + DRCSZOOMX * 11, + DRCSZOOMX * 12, + DRCSZOOMY * 0, + DRCSZOOMY * 1, + DRCSZOOMY * 2, + DRCSZOOMY * 3, + DRCSZOOMY * 4, + DRCSZOOMY * 5, + DRCSZOOMY * 6, + DRCSZOOMY * 7, + DRCSZOOMY * 8, + DRCSZOOMY * 9, + DRCSZOOMY * 10 + }; +#if TUXTXT_DEBUG + printf("TuxTxt \n", tuxtxt_cache.page, tuxtxt_cache.subpage, pageinfo->function); +#endif + ClearBB(black); + for (col = 0; col < 24*40; col++) + page_atrb[col] = atrtable[ATR_WB]; + + for (row = 0; row < DRCSROWS; row++) + for (col = 0; col < DRCSCOLS; col++) + RenderDRCS( + page_char + 20 * (DRCSCOLS * row + col + 2), + lfb + + (StartY + fontheight + DRCSYSPC * row + var_screeninfo.yres - var_screeninfo.yoffset) * fix_screeninfo.line_length + + (StartX + DRCSXSPC * col)*4, + ax, white, black); + + memset(page_char + 40, 0xff, 24*40); /* don't render any char below row 0 */ + boxed = 0; + return ; /* don't interpret irregular pages */ + } + else + { + int i; + int h, parityerror = 0; + + for (i = 0; i < 8; i++) + page_atrb[i] = atrtable[ATR_WB]; + + /* decode parity/hamming */ + for (i = 40; i < (int) sizeof(page_char); i++) + { + page_atrb[i] = atrtable[ATR_WB]; + p = page_char + i; + h = dehamming[*p]; + if (parityerror && h != 0xFF) /* if no regular page (after any parity error) */ + hex2str((char *) p, h); /* first try dehamming */ + else + { + if (*p == ' ' || deparity[*p] != ' ') /* correct parity */ + *p &= 127; + else + { + parityerror = 1; + if (h != 0xFF) /* first parity error: try dehamming */ + hex2str((char *) p, h); + else + *p = ' '; + } + } + } + if (parityerror) + { + boxed = 0; + return ; /* don't interpret irregular pages */ + } + } + } + + /* decode */ + for (row = 0; + row < ((showflof && pageinfo->p24) ? 25 : 24); + row++) + { + /* start-of-row default conditions */ + foreground = white; + background = black; + doubleheight = 0; + doublewidth = 0; + charset = C_G0P; + mosaictype = 0; + concealed = 0; + flashmode = 0; + hold = 0; + boxwin = 0; + held_mosaic = ' '; + dhset = 0; + IgnoreAtBlackBgSubst = 0; + + if (boxed && memchr(&page_char[row*40], start_box, 40) == 0) + { + foreground = transp; + background = transp; + } + + for (col = 0; col < 40; col++) + { + int index = row*40 + col; + + page_atrb[index].fg = foreground; + page_atrb[index].bg = background; + page_atrb[index].charset = charset; + page_atrb[index].doubleh = doubleheight; + page_atrb[index].doublew = (col < 39 ? doublewidth : 0); + page_atrb[index].IgnoreAtBlackBgSubst = IgnoreAtBlackBgSubst; + page_atrb[index].concealed = concealed; + page_atrb[index].flashing = flashmode; + page_atrb[index].boxwin = boxwin; + page_atrb[index].inverted = 0; // only relevant for Level 2.5 + page_atrb[index].underline = 0; // only relevant for Level 2.5 + page_atrb[index].diacrit = 0; // only relevant for Level 2.5 + page_atrb[index].setX26 = 0; // only relevant for Level 2.5 + page_atrb[index].setG0G2 = 0x3f; // only relevant for Level 2.5 + + if (page_char[index] < ' ') + { + switch (page_char[index]) + { + case alpha_black: + case alpha_red: + case alpha_green: + case alpha_yellow: + case alpha_blue: + case alpha_magenta: + case alpha_cyan: + case alpha_white: + concealed = 0; + foreground = page_char[index] - alpha_black + black; + if (col == 0 && page_char[index] == alpha_white) + page_atrb[index].fg = black; // indicate level 1 color change on column 0; (hack) + charset = C_G0P; + break; + + case flash: + flashmode = 1; + break; + case steady: + flashmode = 0; + page_atrb[index].flashing = 0; + break; + case end_box: + boxwin = 0; + IgnoreAtBlackBgSubst = 0; +/* if (boxed) + { + foreground = transp; + background = transp; + IgnoreAtBlackBgSubst = 0; + } +*/ + break; + + case start_box: + if (!boxwin) + { + boxwin = 1; + //background = 0x08; + } +/* if (boxed) + { + int rowstart = row * 40; + if (col > 0) + memset(&page_char[rowstart], ' ', col); + for (clear = 0; clear < col; clear++) + { + page_atrb[rowstart + clear].fg = page_atrb[rowstart + clear].bg = transp; + page_atrb[rowstart + clear].IgnoreAtBlackBgSubst = 0; + } + } +*/ + break; + + case normal_size: + doubleheight = 0; + doublewidth = 0; + page_atrb[index].doubleh = doubleheight; + page_atrb[index].doublew = doublewidth; + break; + + case double_height: + if (row < 23) + { + doubleheight = 1; + dhset = 1; + } + doublewidth = 0; + + break; + + case double_width: + if (col < 39) + doublewidth = 1; + doubleheight = 0; + break; + + case double_size: + if (row < 23) + { + doubleheight = 1; + dhset = 1; + } + if (col < 39) + doublewidth = 1; + break; + + case mosaic_black: + case mosaic_red: + case mosaic_green: + case mosaic_yellow: + case mosaic_blue: + case mosaic_magenta: + case mosaic_cyan: + case mosaic_white: + concealed = 0; + foreground = page_char[index] - mosaic_black + black; + charset = mosaictype ? C_G1S : C_G1C; + break; + + case conceal: + page_atrb[index].concealed = 1; + concealed = 1; + if (!hintmode) + { + foreground = background; + page_atrb[index].fg = foreground; + } + break; + + case contiguous_mosaic: + mosaictype = 0; + if (charset == C_G1S) + { + charset = C_G1C; + page_atrb[index].charset = charset; + } + break; + + case separated_mosaic: + mosaictype = 1; + if (charset == C_G1C) + { + charset = C_G1S; + page_atrb[index].charset = charset; + } + break; + + case esc: + if (charset == C_G0P) + charset = C_G0S; + else if (charset == C_G0S) + charset = C_G0P; + break; + + case black_background: + background = black; + IgnoreAtBlackBgSubst = 0; + page_atrb[index].bg = background; + page_atrb[index].IgnoreAtBlackBgSubst = IgnoreAtBlackBgSubst; + break; + + case new_background: + background = foreground; + if (background == black) + IgnoreAtBlackBgSubst = 1; + else + IgnoreAtBlackBgSubst = 0; + page_atrb[index].bg = background; + page_atrb[index].IgnoreAtBlackBgSubst = IgnoreAtBlackBgSubst; + break; + + case hold_mosaic: + hold = 1; + break; + + case release_mosaic: + hold = 2; + break; + } + + /* handle spacing attributes */ + if (hold && (page_atrb[index].charset == C_G1C || page_atrb[index].charset == C_G1S)) + page_char[index] = held_mosaic; + else + page_char[index] = ' '; + + if (hold == 2) + hold = 0; + } + else /* char >= ' ' */ + { + /* set new held-mosaic char */ + if ((charset == C_G1C || charset == C_G1S) && + ((page_char[index]&0xA0) == 0x20)) + held_mosaic = page_char[index]; + if (page_atrb[index].doubleh) + page_char[index + 40] = 0xFF; + + } + if (!(charset == C_G1C || charset == C_G1S)) + held_mosaic = ' '; /* forget if outside mosaic */ + + } /* for col */ + + /* skip row if doubleheight */ + if (row < 23 && dhset) + { + for (col = 0; col < 40; col++) + { + int index = row*40 + col; + page_atrb[index+40].bg = page_atrb[index].bg; + page_atrb[index+40].fg = white; + if (!page_atrb[index].doubleh) + page_char[index+40] = ' '; + page_atrb[index+40].flashing = 0; + page_atrb[index+40].charset = C_G0P; + page_atrb[index+40].doubleh = 0; + page_atrb[index+40].doublew = 0; + page_atrb[index+40].IgnoreAtBlackBgSubst = 0; + page_atrb[index+40].concealed = 0; + page_atrb[index+40].flashing = 0; + page_atrb[index+40].boxwin = page_atrb[index].boxwin; + } + row++; + } + } /* for row */ + FullScrColor = black; + + if (showl25) + eval_l25(); + + + /* handle Black Background Color Substitution and transparency (CLUT1#0) */ + { + int r, c; + int o = 0; + char bitmask ; + + + + for (r = 0; r < 25; r++) + { + for (c = 0; c < 40; c++) + { + bitmask = (page_atrb[o].bg == 0x08 ? 0x08 : 0x00) | (FullRowColor[r] == 0x08 ? 0x04 : 0x00) | (page_atrb[o].boxwin <<1) | boxed; + switch (bitmask) + { + case 0x08: + case 0x0b: + if (FullRowColor[r] == 0x08) + page_atrb[o].bg = FullScrColor; + else + page_atrb[o].bg = FullRowColor[r]; + break; + case 0x01: + case 0x05: + case 0x09: + case 0x0a: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + page_atrb[o].bg = transp; + break; + } + bitmask = (page_atrb[o].fg == 0x08 ? 0x08 : 0x00) | (FullRowColor[r] == 0x08 ? 0x04 : 0x00) | (page_atrb[o].boxwin <<1) | boxed; + switch (bitmask) + { + case 0x08: + case 0x0b: + if (FullRowColor[r] == 0x08) + page_atrb[o].fg = FullScrColor; + else + page_atrb[o].fg = FullRowColor[r]; + break; + case 0x01: + case 0x05: + case 0x09: + case 0x0a: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + page_atrb[o].fg = transp; + break; + } + o++; + } + } + } + return ; +} + +/****************************************************************************** + * GetRCCode * + ******************************************************************************/ +int GetRCCode() +{ + neutrino_msg_t msg; + neutrino_msg_data_t data; + g_RCInput->getMsg_ms(&msg, &data, 40); + RCCode = -1; + + if (msg <= CRCInput::RC_MaxRC) { + RCCode = msg; + return 1; + } + return 0; +} + +#if 0 +#if 1 +int GetRCCode() +{ + struct input_event ev; + static __u16 rc_last_key = KEY_RESERVED; + + int val = fcntl(rc, F_GETFL); + if(!(val & O_NONBLOCK)) + printf("[tuxtxt] GetRCCode in blocking mode.\n"); + + /* get code */ + if (read(rc, &ev, sizeof(ev)) == sizeof(ev)) + { + if (ev.value) + { + if (ev.code != rc_last_key || + ev.code == KEY_DOWN || ev.code == KEY_UP || /* allow direction keys */ + ev.code == KEY_LEFT || ev.code == KEY_RIGHT) /* to autorepeat... */ + { + rc_last_key = ev.code; + switch (ev.code) + { + case KEY_UP: RCCode = RC_UP; break; + case KEY_DOWN: RCCode = RC_DOWN; break; + case KEY_LEFT: RCCode = RC_LEFT; break; + case KEY_RIGHT: RCCode = RC_RIGHT; break; + case KEY_OK: RCCode = RC_OK; break; + case KEY_0: RCCode = RC_0; break; + case KEY_1: RCCode = RC_1; break; + case KEY_2: RCCode = RC_2; break; + case KEY_3: RCCode = RC_3; break; + case KEY_4: RCCode = RC_4; break; + case KEY_5: RCCode = RC_5; break; + case KEY_6: RCCode = RC_6; break; + case KEY_7: RCCode = RC_7; break; + case KEY_8: RCCode = RC_8; break; + case KEY_9: RCCode = RC_9; break; + case KEY_RED: RCCode = RC_RED; break; + case KEY_GREEN: RCCode = RC_GREEN; break; + case KEY_YELLOW: RCCode = RC_YELLOW; break; + case KEY_BLUE: RCCode = RC_BLUE; break; + case KEY_VOLUMEUP: RCCode = RC_PLUS; break; + case KEY_VOLUMEDOWN: RCCode = RC_MINUS; break; + case KEY_MUTE: RCCode = RC_MUTE; break; +#if !HAVE_TRIPLEDRAGON + /* on CS, change transparent mode with TEXT key */ + case KEY_TEXT: RCCode = RC_TEXT; break; +#else + /* on TD, cycle split screen mode with TTX key + * - the TD has a special key for transparent mode */ + case KEY_TEXT: RCCode = RC_MINUS; break; +#endif + case KEY_TTTV: RCCode = RC_MUTE; break; + case KEY_TTZOOM: RCCode = RC_PLUS; break; + case KEY_REVEAL: RCCode = RC_HELP; break; + //case KEY_HELP: RCCode = RC_HELP; break; + case KEY_INFO: RCCode = RC_HELP; break; + case KEY_MENU: RCCode = RC_DBOX; break; + case KEY_EXIT: RCCode = RC_HOME; break; + case KEY_POWER: RCCode = RC_STANDBY; break; + } +printf("[tuxtxt] new key, code %X\n", RCCode); + return 1; + } + } + else + { + RCCode = -1; + rc_last_key = KEY_RESERVED; + } + } + + RCCode = -1; + usleep(1000000/25); + + return 0; +} +#else +/* this is obsolete and can soon be removed */ +int GetRCCode() +{ + static unsigned short LastKey = -1; + int count; + if ((count = read(rc, &RCCode, 2)) != 2) + { + RCCode = -1; + usleep(1000000/100); + return 0; + } + + fprintf(stderr, "rccode: %04x\n", RCCode); + if (RCCode == LastKey && + RCCode != 0x18 && RCCode != 0x19 && /* allow direction keys */ + RCCode != 0x1b && RCCode != 0x1c) /* to autorepeat... */ + { + RCCode = -1; + return 1; + } + + LastKey = RCCode; + if ((RCCode & 0xFF00) == 0x0000) + { + switch (RCCode) + { + case 0x18: RCCode = RC_UP; break; + case 0x1c: RCCode = RC_DOWN; break; + case 0x19: RCCode = RC_LEFT; break; + case 0x1b: RCCode = RC_RIGHT; break; + case 0x1a: RCCode = RC_OK; break; + case 0x0e: RCCode = RC_0; break; + case 0x02: RCCode = RC_1; break; + case 0x03: RCCode = RC_2; break; + case 0x04: RCCode = RC_3; break; + case 0x05: RCCode = RC_4; break; + case 0x06: RCCode = RC_5; break; + case 0x07: RCCode = RC_6; break; + case 0x09: RCCode = RC_7; break; + case 0x0a: RCCode = RC_8; break; + case 0x0b: RCCode = RC_9; break; + case 0x1f: RCCode = RC_RED; break; + case 0x20: RCCode = RC_GREEN; break; + case 0x21: RCCode = RC_YELLOW; break; + case 0x22: RCCode = RC_BLUE; break; + case 0x29: RCCode = RC_PLUS; break; // [=X=] key -> double height + case 0x27: RCCode = RC_MINUS; break; // [txt] key -> split mode + case 0x11: RCCode = RC_MUTE; break; + case 0x28: RCCode = RC_MUTE; break; // [ /=] key + case 0x14: RCCode = RC_HELP; break; + case 0x2a: RCCode = RC_HELP; break; // [==?] key + case 0x12: RCCode = RC_DBOX; break; + case 0x15: RCCode = RC_HOME; break; + case 0x01: RCCode = RC_STANDBY; break; + } + return 1; + } + return 1; +} +#endif +#endif +/* Local Variables: */ +/* indent-tabs-mode:t */ +/* tab-width:3 */ +/* c-basic-offset:3 */ +/* comment-column:0 */ +/* fill-column:120 */ +/* End: */ diff --git a/lib/libtuxtxt_mp/tuxtxt.h b/lib/libtuxtxt_mp/tuxtxt.h new file mode 100644 index 000000000..d5c12bbcd --- /dev/null +++ b/lib/libtuxtxt_mp/tuxtxt.h @@ -0,0 +1,1797 @@ + +#if HAVE_COOL_HARDWARE +#include "tuxtxt_cool.h" +#else + +#ifndef __tuxtxt_h__ +#define __tuxtxt_h__ + +/****************************************************************************** + * <<< TuxTxt - Teletext Plugin >>> * + * * + * (c) Thomas "LazyT" Loewe 2002-2003 (LazyT@gmx.net) * + * * + * continued 2004-2005 by Roland Meier * + * and DBLuelle * + * * + * ported 2006 to Dreambox 7025 / 32Bit framebuffer * + * by Seddi * + * * + * * + * ported to Tripledragon, SPARK and AZbox 2010-2013 Stefan Seyfried * + ******************************************************************************/ + +#define TUXTXT_CFG_STANDALONE 0 // 1:plugin only 0:use library +#define TUXTXT_DEBUG 0 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include "tuxtxt_def.h" + +#include +#include FT_FREETYPE_H +#include FT_CACHE_H +#include FT_CACHE_SMALL_BITMAPS_H + +#include + +/* devices */ + +#if TUXTXT_CFG_STANDALONE +#include "tuxtxt_common.h" +#else +/* variables and functions from libtuxtxt */ +extern tuxtxt_cache_struct tuxtxt_cache; +extern void tuxtxt_next_dec(int *i); /* skip to next decimal */ +extern void tuxtxt_prev_dec(int *i); /* counting down */ +extern int tuxtxt_is_dec(int i); +extern int tuxtxt_next_hex(int i); +extern void tuxtxt_decode_btt(); +extern void tuxtxt_decode_adip(); /* additional information table */ +extern void tuxtxt_compress_page(int p, int sp, unsigned char* buffer); +extern void tuxtxt_decompress_page(int p, int sp, unsigned char* buffer); +extern void tuxtxt_clear_p26(tstExtData* extData); +#if TUXTXT_DEBUG +extern int tuxtxt_get_zipsize(int p, int sp); +#endif +#endif + + +#define TUXTXTDIR CONFIGDIR "/tuxtxt" +#define TUXTXTCONF TUXTXTDIR "/tuxtxt2.conf" + +/* fonts */ +#define TUXTXTTTF FONTDIR "/tuxtxt.ttf" +#define TUXTXTOTB FONTDIR "/tuxtxt.otb" +/* alternative fontdir */ +#define TUXTXTTTFVAR "/var/tuxtxt/tuxtxt.ttf" +#define TUXTXTOTBVAR "/var/tuxtxt/tuxtxt.otb" + +int TTFWidthFactor16, TTFHeightFactor16, TTFShiftX, TTFShiftY; /* parameters for adapting to various TTF fonts */ +int fontheight, fontwidth, fontwidth_normal, fontwidth_small, fontwidth_topmenumain, fontwidth_topmenusmall, ascender; +int ymosaic[4]; +int displaywidth; +int tv_pip_y; +#define fontwidth_small_lcd 8 + +#define TV43STARTX (ex) +#define TVENDX (screen_x + screen_w) //ex +// #define TVENDY (StartY + 25*fontheight) +// #define TV43WIDTH (TVENDX - TV43STARTX) +// #define TV43HEIGHT (TV43WIDTH *9/16) +// #define TV43STARTY (TVENDY - TV43HEIGHT) + +//#define TV169FULLSTARTX (sx+ 8*40) //(sx +(ex +1 - sx)/2) +#define TV169FULLSTARTX (screen_x + screen_w / 2) +#define TV169FULLSTARTY sy +//#define TV169FULLWIDTH (ex - sx)/2 +#define TV169FULLWIDTH (screen_w / 2) +#define TV169FULLHEIGHT (ey - sy) +#define TOPMENUSTARTX (TV43STARTX+2) +//#define TOPMENUENDX TVENDX +#define TOPMENUSTARTY StartY +#define TOPMENUENDY TV43STARTY + +//#define TOPMENULINEWIDTH ((TOPMENUENDX-TOPMENU43STARTX+fontwidth_topmenusmall-1)/fontwidth_topmenusmall) +#define TOPMENUINDENTBLK 0 +#define TOPMENUINDENTGRP 1 +#define TOPMENUINDENTDEF 2 +#define TOPMENUSPC 0 +#define TOPMENUCHARS (TOPMENUINDENTDEF+12+TOPMENUSPC+3) + +#define FLOFSIZE 4 + +/* spacing attributes */ +#define alpha_black 0x00 +#define alpha_red 0x01 +#define alpha_green 0x02 +#define alpha_yellow 0x03 +#define alpha_blue 0x04 +#define alpha_magenta 0x05 +#define alpha_cyan 0x06 +#define alpha_white 0x07 +#define flash 0x08 +#define steady 0x09 +#define end_box 0x0A +#define start_box 0x0B +#define normal_size 0x0C +#define double_height 0x0D +#define double_width 0x0E +#define double_size 0x0F +#define mosaic_black 0x10 +#define mosaic_red 0x11 +#define mosaic_green 0x12 +#define mosaic_yellow 0x13 +#define mosaic_blue 0x14 +#define mosaic_magenta 0x15 +#define mosaic_cyan 0x16 +#define mosaic_white 0x17 +#define conceal 0x18 +#define contiguous_mosaic 0x19 +#define separated_mosaic 0x1A +#define esc 0x1B +#define black_background 0x1C +#define new_background 0x1D +#define hold_mosaic 0x1E +#define release_mosaic 0x1F + +#if 0 +/* rc codes */ +#define RC_0 0x00 +#define RC_1 0x01 +#define RC_2 0x02 +#define RC_3 0x03 +#define RC_4 0x04 +#define RC_5 0x05 +#define RC_6 0x06 +#define RC_7 0x07 +#define RC_8 0x08 +#define RC_9 0x09 +#define RC_RIGHT 0x0A +#define RC_LEFT 0x0B +#define RC_UP 0x0C +#define RC_DOWN 0x0D +#define RC_OK 0x0E +#define RC_MUTE 0x0F +#define RC_STANDBY 0x10 +#define RC_GREEN 0x11 +#define RC_YELLOW 0x12 +#define RC_RED 0x13 +#define RC_BLUE 0x14 +#define RC_PLUS 0x15 +#define RC_MINUS 0x16 +#define RC_HELP 0x17 +#define RC_DBOX 0x18 +#define RC_TEXT 0x19 +#define RC_HOME 0x1F +#else +#define RC_0 CRCInput::RC_0 +#define RC_1 CRCInput::RC_1 +#define RC_2 CRCInput::RC_2 +#define RC_3 CRCInput::RC_3 +#define RC_4 CRCInput::RC_4 +#define RC_5 CRCInput::RC_5 +#define RC_6 CRCInput::RC_6 +#define RC_7 CRCInput::RC_7 +#define RC_8 CRCInput::RC_8 +#define RC_9 CRCInput::RC_9 +#define RC_RIGHT CRCInput::RC_right +#define RC_LEFT CRCInput::RC_left +#define RC_UP CRCInput::RC_up +#define RC_DOWN CRCInput::RC_down +#define RC_OK CRCInput::RC_ok +#define RC_MUTE CRCInput::RC_spkr +#define RC_STANDBY CRCInput::RC_standby +#define RC_GREEN CRCInput::RC_green +#define RC_YELLOW CRCInput::RC_yellow +#define RC_RED CRCInput::RC_red +#define RC_BLUE CRCInput::RC_blue +#define RC_PLUS CRCInput::RC_plus +#define RC_MINUS CRCInput::RC_minus +#define RC_HELP CRCInput::RC_help +#define RC_INFO CRCInput::RC_info +#define RC_DBOX CRCInput::RC_setup +#define RC_HOME CRCInput::RC_home +#define RC_TTTV CRCInput::RC_tttv +#define RC_TTZOOM CRCInput::RC_ttzoom +#define RC_TTREVEAL CRCInput::RC_ttreveal +#if HAVE_TRIPLEDRAGON +/* td has more keys so use ttx key for switching split mode... */ +#define RC_SPLIT CRCInput::RC_text +/* rc_text is now unused */ +#define RC_TEXT (CRCInput::RC_MaxRC + 1) +#else +/* ...while other receivers use the vol- key for that, so rc_split is unused */ +#define RC_SPLIT (CRCInput::RC_MaxRC + 1) +#define RC_TEXT CRCInput::RC_text +#endif +#endif + +typedef enum /* object type */ +{ + OBJ_PASSIVE, + OBJ_ACTIVE, + OBJ_ADAPTIVE +} tObjType; + +const char *ObjectSource[] = +{ + "(illegal)", + "Local", + "POP", + "GPOP" +}; +const char *ObjectType[] = +{ + "Passive", + "Active", + "Adaptive", + "Passive" +}; + +/* messages */ +#define ShowInfoBar 0 +//#define PageNotFound 1 +#define ShowServiceName 2 +#define NoServicesFound 3 + +/* framebuffer stuff */ +static unsigned char *lfb = 0; +static unsigned char *lbb = 0; +struct fb_var_screeninfo var_screeninfo; +struct fb_fix_screeninfo fix_screeninfo; + +/* freetype stuff */ +FT_Library library; +FTC_Manager manager; +static FTC_SBitCache cache; +FTC_SBit sbit; + +#define FONTTYPE FTC_ImageTypeRec + +FT_Face face; +FONTTYPE typettf; + +const unsigned short int arrowtable[] = +{ + 8592, 8594, 8593, 8595, 'O', 'K', 8592, 8592 +}; +// G2 Set as defined in ETS 300 706 +const unsigned short int G2table[4][6*16] = +{ + { 0x0020, 0x00A1, 0x00A2, 0x00A3, 0x0024, 0x00A5, 0x0023, 0x00A7, 0x00A4, 0x2018, 0x201C, 0x00AB, 0x2190, 0x2191, 0x2192, 0x2193, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00D7, 0x00B5, 0x00B6, 0x00B7, 0x00F7, 0x2019, 0x201D, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x0020, 0x0300, 0x0301, 0x02C6, 0x0303, 0x02C9, 0x02D8, 0x02D9, 0x00A8, 0x002E, 0x02DA, 0x00B8, 0x005F, 0x02DD, 0x02DB, 0x02C7, + 0x2014, 0x00B9, 0x00AE, 0x00A9, 0x2122, 0x266A, 0x20AC, 0x2030, 0x03B1, 0x0020, 0x0020, 0x0020, 0x215B, 0x215C, 0x215D, 0x215E, + 0x2126, 0x00C6, 0x00D0, 0x00AA, 0x0126, 0x0020, 0x0132, 0x013F, 0x0141, 0x00D8, 0x0152, 0x00BA, 0x00DE, 0x0166, 0x014A, 0x0149, + 0x0138, 0x00E6, 0x0111, 0x00F0, 0x0127, 0x0131, 0x0133, 0x0140, 0x0142, 0x00F8, 0x0153, 0x00DF, 0x00FE, 0x0167, 0x014B, 0x25A0}, + + { 0x0020, 0x00A1, 0x00A2, 0x00A3, 0x0024, 0x00A5, 0x0020, 0x00A7, 0x0020, 0x2018, 0x201C, 0x00AB, 0x2190, 0x2191, 0x2192, 0x2193, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00D7, 0x00B5, 0x00B6, 0x00B7, 0x00F7, 0x2019, 0x201D, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x0020, 0x0300, 0x0301, 0x02C6, 0x02DC, 0x02C9, 0x02D8, 0x02D9, 0x00A8, 0x002E, 0x02DA, 0x00B8, 0x005F, 0x02DD, 0x02DB, 0x02C7, + 0x2014, 0x00B9, 0x00AE, 0x00A9, 0x2122, 0x266A, 0x20AC, 0x2030, 0x03B1, 0x0141, 0x0142, 0x00DF, 0x215B, 0x215C, 0x215D, 0x215E, + 0x0044, 0x0045, 0x0046, 0x0047, 0x0049, 0x004A, 0x004B, 0x004C, 0x004E, 0x0051, 0x0052, 0x0053, 0x0055, 0x0056, 0x0057, 0x005A, + 0x0064, 0x0065, 0x0066, 0x0067, 0x0069, 0x006A, 0x006B, 0x006C, 0x006E, 0x0071, 0x0072, 0x0073, 0x0075, 0x0076, 0x0077, 0x007A}, + + { 0x0020, 0x0061, 0x0062, 0x00A3, 0x0065, 0x0068, 0x0069, 0x00A7, 0x003A, 0x2018, 0x201C, 0x006B, 0x2190, 0x2191, 0x2192, 0x2193, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00D7, 0x006D, 0x006E, 0x0070, 0x00F7, 0x2019, 0x201D, 0x0074, 0x00BC, 0x00BD, 0x00BE, 0x0078, + 0x0020, 0x0300, 0x0301, 0x02C6, 0x02DC, 0x02C9, 0x02D8, 0x02D9, 0x00A8, 0x002E, 0x02DA, 0x00B8, 0x005F, 0x02DD, 0x02DB, 0x02C7, + 0x003F, 0x00B9, 0x00AE, 0x00A9, 0x2122, 0x266A, 0x20AC, 0x2030, 0x03B1, 0x038A, 0x038E, 0x038F, 0x215B, 0x215C, 0x215D, 0x215E, + 0x0043, 0x0044, 0x0046, 0x0047, 0x004A, 0x004C, 0x0051, 0x0052, 0x0053, 0x0055, 0x0056, 0x0057, 0x0059, 0x005A, 0x0386, 0x0389, + 0x0063, 0x0064, 0x0066, 0x0067, 0x006A, 0x006C, 0x0071, 0x0072, 0x0073, 0x0075, 0x0076, 0x0077, 0x0079, 0x007A, 0x0388, 0x25A0}, + + { 0x0020, 0x0639, 0xFEC9, 0xFE83, 0xFE85, 0xFE87, 0xFE8B, 0xFE89, 0xFB7C, 0xFB7D, 0xFB7A, 0xFB58, 0xFB59, 0xFB56, 0xFB6D, 0xFB8E, + 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668, 0x0669, 0xFECE, 0xFECD, 0xFEFC, 0xFEEC, 0xFEEA, 0xFEE9, + 0x00E0, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x00EB, 0x00EA, 0x00F9, 0x00EE, 0xFECA, + 0x00E9, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x00E2, 0x00F4, 0x00FB, 0x00E7, 0x25A0} +}; + +const unsigned short int G0table[6][6*16] = +{ + { ' ', '!', '\"', '#', '$', '%', '&', '\'', '(' , ')' , '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', + 0x0427, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, 0x0425, 0x0418, 0x0408, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, + 0x041F, 0x040C, 0x0420, 0x0421, 0x0422, 0x0423, 0x0412, 0x0403, 0x0409, 0x040A, 0x0417, 0x040B, 0x0416, 0x0402, 0x0428, 0x040F, + 0x0447, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, 0x0445, 0x0438, 0x0458, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, + 0x043F, 0x045C, 0x0440, 0x0441, 0x0442, 0x0443, 0x0432, 0x0453, 0x0459, 0x045A, 0x0437, 0x045B, 0x0436, 0x0452, 0x0448, 0x25A0}, + + { ' ', '!', '\"', '#', '$', '%', 0x044B, '\'', '(' , ')' , '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', + 0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, 0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, + 0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, 0x042C, 0x042A, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042B, + 0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, 0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, + 0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, 0x044C, 0x044A, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x25A0}, + + { ' ', '!', '\"', '#', '$', '%', 0x0457, '\'', '(' , ')' , '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', + 0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, 0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, + 0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, 0x042C, 0x0406, 0x0417, 0x0428, 0x0404, 0x0429, 0x0427, 0x0407, + 0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, 0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, + 0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, 0x044C, 0x0456, 0x0437, 0x0448, 0x0454, 0x0449, 0x0447, 0x25A0}, + + { ' ', '!', '\"', '#', '$', '%', '&', '\'', '(' , ')' , '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', 0x00AB, '=', 0x00BB, '?', + 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, + 0x03A0, 0x03A1, 0x0384, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, + 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, + 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x25A0}, + + { ' ', '!', 0x05F2, 0x00A3, '$', '%', '&', '\'', '(' , ')' , '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', + '@', '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', 0x2190, 0x00BD, 0x2192, 0x2191, '#', + 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, + 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x20AA, 0x2551, 0x00BE, 0x00F7, 0x25A0}, + + { ' ', '!', 0x05F2, 0x00A3, '$', 0x066A, 0xFEF0, 0xFEF2, 0xFD3F, 0xFD3E, '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', 0x061B, '>', '=', '<', 0x061F, + 0xFE94, 0x0621, 0xFE92, 0x0628, 0xFE98, 0x062A, 0xFE8E, 0xFE8D, 0xFE91, 0xFE93, 0xFE97, 0xFE9B, 0xFE9F, 0xFEA3, 0xFEA7, 0xFEA9, + 0x0630, 0xFEAD, 0xFEAF, 0xFEB3, 0xFEB7, 0xFEBB, 0xFEBF, 0xFEC1, 0xFEC5, 0xFECB, 0xFECF, 0xFE9C, 0xFEA0, 0xFEA4, 0xFEA8, 0x0023, + 0x0640, 0xFED3, 0xFED7, 0xFEDB, 0xFEDF, 0xFEE3, 0xFEE7, 0xFEEB, 0xFEED, 0xFEEF, 0xFEF3, 0xFE99, 0xFE9D, 0xFEA1, 0xFEA5, 0xFEF4, + 0xFEF0, 0xFECC, 0xFED0, 0xFED4, 0xFED1, 0xFED8, 0xFED5, 0xFED9, 0xFEE0, 0xFEDD, 0xFEE4, 0xFEE1, 0xFEE8, 0xFEE5, 0xFEFB, 0x25A0} +}; + +const unsigned short int nationaltable23[14][2] = +{ + { '#', 0x00A4 }, /* 0 */ + { '#', 0x016F }, /* 1 CS/SK */ + { 0x00A3, '$' }, /* 2 EN */ + { '#', 0x00F5 }, /* 3 ET */ + { 0x00E9, 0x0457 }, /* 4 FR */ + { '#', '$' }, /* 5 DE */ + { 0x00A3, '$' }, /* 6 IT */ + { '#', '$' }, /* 7 LV/LT */ + { '#', 0x0144 }, /* 8 PL */ + { 0x00E7, '$' }, /* 9 PT/ES */ + { '#', 0x00A4 }, /* A RO */ + { '#', 0x00CB }, /* B SR/HR/SL */ + { '#', 0x00A4 }, /* C SV/FI/HU */ + { 0x20A4, 0x011F }, /* D TR */ +}; +const unsigned short int nationaltable40[14] = +{ + '@', /* 0 */ + 0x010D, /* 1 CS/SK */ + '@', /* 2 EN */ + 0x0161, /* 3 ET */ + 0x00E0, /* 4 FR */ + 0x00A7, /* 5 DE */ + 0x00E9, /* 6 IT */ + 0x0161, /* 7 LV/LT */ + 0x0105, /* 8 PL */ + 0x00A1, /* 9 PT/ES */ + 0x0162, /* A RO */ + 0x010C, /* B SR/HR/SL */ + 0x00C9, /* C SV/FI/HU */ + 0x0130, /* D TR */ +}; +const unsigned short int nationaltable5b[14][6] = +{ + { '[', '\\', ']', '^', '_', '`' }, /* 0 */ + { 0x0165, 0x017E, 0x00FD, 0x00ED, 0x0159, 0x00E9 }, /* 1 CS/SK */ + { 0x2190, 0x00BD, 0x2192, 0x2191, '#', 0x00AD }, /* 2 EN */ + { 0x00C4, 0x00D6, 0x017D, 0x00DC, 0x00D5, 0x0161 }, /* 3 ET */ + { 0x0451, 0x00EA, 0x00F9, 0x00EE, '#', 0x00E8 }, /* 4 FR */ + { 0x00C4, 0x00D6, 0x00DC, '^', '_', 0x00B0 }, /* 5 DE */ + { 0x00B0, 0x00E7, 0x2192, 0x2191, '#', 0x00F9 }, /* 6 IT */ + { 0x0117, 0x0119, 0x017D, 0x010D, 0x016B, 0x0161 }, /* 7 LV/LT */ + { 0x017B, 0x015A, 0x0141, 0x0107, 0x00F3, 0x0119 }, /* 8 PL */ + { 0x00E1, 0x00E9, 0x00ED, 0x00F3, 0x00FA, 0x00BF }, /* 9 PT/ES */ + { 0x00C2, 0x015E, 0x01CD, 0x01CF, 0x0131, 0x0163 }, /* A RO */ + { 0x0106, 0x017D, 0x00D0, 0x0160, 0x0451, 0x010D }, /* B SR/HR/SL */ + { 0x00C4, 0x00D6, 0x00C5, 0x00DC, '_', 0x00E9 }, /* C SV/FI/HU */ + { 0x015E, 0x00D6, 0x00C7, 0x00DC, 0x011E, 0x0131 }, /* D TR */ +}; +const unsigned short int nationaltable7b[14][4] = +{ + { '{', '|', '}', '~' }, /* 0 */ + { 0x00E1, 0x011B, 0x00FA, 0x0161 }, /* 1 CS/SK */ + { 0x00BC, 0x2551, 0x00BE, 0x00F7 }, /* 2 EN */ + { 0x00E4, 0x00F6, 0x017E, 0x00FC }, /* 3 ET */ + { 0x00E2, 0x00F4, 0x00FB, 0x00E7 }, /* 4 FR */ + { 0x00E4, 0x00F6, 0x00FC, 0x00DF }, /* 5 DE */ + { 0x00E0, 0x00F3, 0x00E8, 0x00EC }, /* 6 IT */ + { 0x0105, 0x0173, 0x017E, 0x012F }, /* 7 LV/LT */ + { 0x017C, 0x015B, 0x0142, 0x017A }, /* 8 PL */ + { 0x00FC, 0x00F1, 0x00E8, 0x00E0 }, /* 9 PT/ES */ + { 0x00E2, 0x015F, 0x01CE, 0x00EE }, /* A RO */ + { 0x0107, 0x017E, 0x0111, 0x0161 }, /* B SR/HR/SL */ + { 0x00E4, 0x00F6, 0x00E5, 0x00FC }, /* C SV/FI/HU */ + { 0x015F, 0x00F6, 0x00E7, 0x00FC }, /* D TR */ +}; +#if 0 +// G2 Charset (0 = Latin, 1 = Cyrillic, 2 = Greek) +const unsigned short int G2table[3][6*16] = +{ + { ' ' ,'¡' ,'¢' ,'£' ,'$' ,'¥' ,'#' ,'§' ,'¤' ,'\'','\"','«' ,8592,8594,8595,8593, + '°' ,'±' ,'²' ,'³' ,'x' ,'µ' ,'¶' ,'·' ,'÷' ,'\'','\"','»' ,'¼' ,'½' ,'¾' ,'¿' , + ' ' ,'`' ,'´' ,710 ,732 ,'¯' ,728 ,729 ,733 ,716 ,730 ,719 ,'_' ,698 ,718 ,711 , + '­' ,'¹' ,'®' ,'©' ,8482,9834,8364,8240,945 ,' ' ,' ' ,' ' ,8539,8540,8541,8542, + 937 ,'Æ' ,272 ,'ª' ,294 ,' ' ,306 ,319 ,321 ,'Ø' ,338 ,'º' ,'Þ' ,358 ,330 ,329 , + 1082,'æ' ,273 ,'ð' ,295 ,305 ,307 ,320 ,322 ,'ø' ,339 ,'ß' ,'þ' ,359 ,951 ,0x7F}, + { ' ' ,'¡' ,'¢' ,'£' ,'$' ,'¥' ,' ' ,'§' ,' ' ,'\'','\"','«' ,8592,8594,8595,8593, + '°' ,'±' ,'²' ,'³' ,'x' ,'µ' ,'¶' ,'·' ,'÷' ,'\'','\"','»' ,'¼' ,'½' ,'¾' ,'¿' , + ' ' ,'`' ,'´' ,710 ,732 ,'¯' ,728 ,729 ,733 ,716 ,730 ,719 ,'_' ,698 ,718 ,711 , + '­' ,'¹' ,'®' ,'©' ,8482,9834,8364,8240,945 ,321 ,322 ,'ß' ,8539,8540,8541,8542, + 'D' ,'E' ,'F' ,'G' ,'I' ,'J' ,'K' ,'L' ,'N' ,'Q' ,'R' ,'S' ,'U' ,'V' ,'W' ,'Z' , + 'd' ,'e' ,'f' ,'g' ,'i' ,'j' ,'k' ,'l' ,'n' ,'q' ,'r' ,'s' ,'u' ,'v' ,'w' ,'z' }, + { ' ' ,'a' ,'b' ,'£' ,'e' ,'h' ,'i' ,'§' ,':' ,'\'','\"','k' ,8592,8594,8595,8593, + '°' ,'±' ,'²' ,'³' ,'x' ,'m' ,'n' ,'p' ,'÷' ,'\'','\"','t' ,'¼' ,'½' ,'¾' ,'x' , + ' ' ,'`' ,'´' ,710 ,732 ,'¯' ,728 ,729 ,733 ,716 ,730 ,719 ,'_' ,698 ,718 ,711 , + '?' ,'¹' ,'®' ,'©' ,8482,9834,8364,8240,945 ,906 ,910 ,911 ,8539,8540,8541,8542, + 'C' ,'D' ,'F' ,'G' ,'J' ,'L' ,'Q' ,'R' ,'S' ,'U' ,'V' ,'W' ,'Y' ,'Z' ,902 ,905 , + 'c' ,'d' ,'f' ,'g' ,'j' ,'l' ,'q' ,'r' ,'s' ,'u' ,'v' ,'w' ,'y' ,'z' ,904 ,0x7F} +}; +// cyrillic G0 Charset +// TODO: different maps for serbian/russian/ukrainian +const unsigned short int G0tablecyrillic[6*16] = +{ + ' ' ,'!' ,'\"','#' ,'$' ,'%' ,'&' ,'\'','(' ,')' ,'*' ,'+' ,',' ,'-' ,'.' ,'/' , + '0' ,'1' ,'2' ,'3' ,'4' ,'5' ,'6' ,'7' ,'8' ,'9' ,':' ,';' ,'<' ,'=' ,'>' ,'?' , + 1063,1040,1041,1062,1044,1045,1060,1043,1061,1048,1032,1050,1051,1052,1053,1054, + 1055,1036,1056,1057,1058,1059,1042,1027,1033,1034,1047,1035,1046,1026,1064,1119, + 1095,1072,1073,1094,1076,1077,1092,1075,1093,1080,1112,1082,1083,1084,1085,1086, + 1087,1116,1088,1089,1090,1091,1074,1107,1113,1114,1079,1115,1078,1106,1096,0x7F +}; + +const unsigned short int nationaltable23[14][2] = +{ + { '#', '¤' }, /* 0 */ + { '#', 367 }, /* 1 CS/SK */ + { '£', '$' }, /* 2 EN */ + { '#', 'õ' }, /* 3 ET */ + { 'é', 'ï' }, /* 4 FR */ + { '#', '$' }, /* 5 DE */ + { '£', '$' }, /* 6 IT */ + { '#', '$' }, /* 7 LV/LT */ + { '#', 329 }, /* 8 PL */ + { 'ç', '$' }, /* 9 PT/ES */ + { '#', '¤' }, /* A RO */ + { '#', 'Ë' }, /* B SR/HR/SL */ + { '#', '¤' }, /* C SV/FI/HU */ + { '£', 287 }, /* D TR ? */ +}; +const unsigned short int nationaltable40[14] = +{ + '@', /* 0 */ + 269, /* 1 CS/SK */ + '@', /* 2 EN */ + 352, /* 3 ET */ + 'à', /* 4 FR */ + '§', /* 5 DE */ + 'é', /* 6 IT */ + 352, /* 7 LV/LT */ + 261, /* 8 PL */ + '¡', /* 9 PT/ES */ + 354, /* A RO */ + 268, /* B SR/HR/SL */ + 'É', /* C SV/FI/HU */ + 304, /* D TR */ +}; +const unsigned short int nationaltable5b[14][6] = +{ + { '[','\\', ']', '^', '_', '`' }, /* 0 */ + { 357, 382, 'ý', 'í', 345, 'é' }, /* 1 CS/SK */ + {8592, '½',8594,8593, '#', 822 }, /* 2 EN */ + { 'Ä', 'Ö', 381, 'Ü', 'Õ', 353 }, /* 3 ET */ + { 'ë', 'ê', 'ù', 'î', '#', 'è' }, /* 4 FR */ + { 'Ä', 'Ö', 'Ü', '^', '_', '°' }, /* 5 DE */ + { '°', 'ç',8594,8593, '#', 'ù' }, /* 6 IT */ + { 'é', 553, 381, 269, 363, 353 }, /* 7 LV/LT */ + { 437, 346, 321, 263, 'ó', 281 }, /* 8 PL */ + { 'á', 'é', 'í', 'ó', 'ú', '¿' }, /* 9 PT/ES */ + { 'Â', 350, 461, 'Î', 305, 355 }, /* A RO */ + { 262, 381, 272, 352, 'ë', 269 }, /* B SR/HR/SL */ + { 'Ä', 'Ö', 'Å', 'Ü', '_', 'é' }, /* C SV/FI/HU */ + { 350, 'Ö', 'Ç', 'Ü', 486, 305 }, /* D TR */ +}; +const unsigned short int nationaltable7b[14][4] = +{ + { '{', '|', '}', '~' }, /* 0 */ + { 'á', 283, 'ú', 353 }, /* 1 CS/SK */ + { '¼',8214, '¾', '÷' }, /* 2 EN */ + { 'ä', 'ö', 382, 'ü' }, /* 3 ET */ + { 'â', 'ô', 'û', 'ç' }, /* 4 FR */ + { 'ä', 'ö', 'ü', 'ß' }, /* 5 DE */ + { 'à', 'ò', 'è', 'ì' }, /* 6 IT */ + { 261, 371, 382, 303 }, /* 7 LV/LT */ + { 380, 347, 322, 378 }, /* 8 PL */ + { 'ü', 'ñ', 'è', 'à' }, /* 9 PT/ES */ + { 'â', 351, 462, 'î' }, /* A RO */ + { 263, 382, 273, 353 }, /* B SR/HR/SL */ + { 'ä', 'ö', 'å', 'ü' }, /* C SV/FI/HU */ + { 351, 'ö', 231, 'ü' }, /* D TR */ +}; + +/* national subsets */ +const char countrystring[] = +" (#$@[\\]^_`{|}~) " /* 0 no subset specified */ +" CS/SK (#$@[\\]^_`{|}~) " /* 1 czech, slovak */ +" EN (#$@[\\]^_`{|}~) " /* 2 english */ +" ET (#$@[\\]^_`{|}~) " /* 3 estonian */ +" FR (#$@[\\]^_`{|}~) " /* 4 french */ +" DE (#$@[\\]^_`{|}~) " /* 5 german */ +" IT (#$@[\\]^_`{|}~) " /* 6 italian */ +" LV/LT (#$@[\\]^_`{|}~) " /* 7 latvian, lithuanian */ +" PL (#$@[\\]^_`{|}~) " /* 8 polish */ +" PT/ES (#$@[\\]^_`{|}~) " /* 9 portuguese, spanish */ +" RO (#$@[\\]^_`{|}~) " /* 10 romanian */ +" SR/HR/SL (#$@[\\]^_`{|}~) " /* 11 serbian, croatian, slovenian */ +" SV/FI/HU (#$@[\\]^_`{|}~) " /* 12 swedish, finnish, hungarian */ +" TR (#$@[\\]^_`{|}~) " /* 13 turkish */ +" RU/BUL/SER/CRO/UKR (cyr) " /* 14 cyrillic */ +" EK " /* 15 greek */ +; +#endif +const char countrystring[] = +" Default " /* 0 no subset specified */ +" Czech/Slovak " /* 1 czech, slovak */ +" English " /* 2 english */ +" Estonian " /* 3 estonian */ +" French " /* 4 french */ +" Deutsch " /* 5 german */ +" Italian " /* 6 italian */ +" Latvian/Lithuanian " /* 7 latvian, lithuanian */ +" Polish " /* 8 polish */ +" Portuguese/Spanish " /* 9 portuguese, spanish */ +" Romanian " /* 10 romanian */ +"Serbian/Croatian/Slovenian" /* 11 serbian, croatian, slovenian */ +"Swedish/Finnish/Hungarian " /* 12 swedish, finnish, hungarian */ +" T~rk}e " /* 13 turkish */ +" Srpski/Hrvatski " /* 14 serbian, croatian */ +" Russkij/Bylgarski " /* 15 russian, bulgarian */ +" Ukra&nsxka " /* 16 ukrainian */ +" Ekkgmij\\ " /* 17 greek */ +" zixar " /* 18 hebrew */ +" pHQY " /* 19 arabic */ +; +#define COUNTRYSTRING_WIDTH 26 +#define MAX_NATIONAL_SUBSET (sizeof(countrystring) / COUNTRYSTRING_WIDTH - 1) + +enum +{ + NAT_DEFAULT = 0, + NAT_CZ = 1, + NAT_UK = 2, + NAT_ET = 3, + NAT_FR = 4, + NAT_DE = 5, + NAT_IT = 6, + NAT_LV = 7, + NAT_PL = 8, + NAT_SP = 9, + NAT_RO = 10, + NAT_SR = 11, + NAT_SW = 12, + NAT_TR = 13, + NAT_MAX_FROM_HEADER = 13, + NAT_SC = 14, + NAT_RB = 15, + NAT_UA = 16, + NAT_GR = 17, + NAT_HB = 18, + NAT_AR = 19 +}; +const unsigned char countryconversiontable[] = { NAT_UK, NAT_DE, NAT_SW, NAT_IT, NAT_FR, NAT_SP, NAT_CZ, NAT_RO}; + +/* some data */ +char versioninfo[16]; +int hotlist[10]; +int maxhotlist; + +int pig, fb, lcd; +int sx, ex, sy, ey; +int PosX, PosY, StartX, StartY; +int lastpage; +int inputcounter; +int zoommode, screenmode, transpmode, hintmode, boxed, nofirst, savedscreenmode, showflof, show39, showl25, prevscreenmode; +char dumpl25; +int catch_row, catch_col, catched_page, pagecatching; +int prev_100, prev_10, next_10, next_100; +int screen_mode1, color_mode, trans_mode, national_subset, national_subset_secondary, auto_national, swapupdown, showhex, menulanguage; +int pids_found, current_service, getpidsdone; +int SDT_ready; +int pc_old_row, pc_old_col; /* for page catching */ +int temp_page; /* for page input */ +char saveconfig, hotlistchanged; +signed char clearbbcolor = -1; +int usettf; +short pop, gpop, drcs, gdrcs; +unsigned char tAPx, tAPy; /* temporary offset to Active Position for objects */ +unsigned char axdrcs[12+1+10+1]; +#define aydrcs (axdrcs + 12+1) +unsigned char FullRowColor[25]; +unsigned char FullScrColor; +tstPageinfo *pageinfo = 0;/* pointer to cached info of last decoded page */ +const char * fncmodes[] = {"12", "6"}; +const char * saamodes[] = {"4:3_full_format", "16:9_full_format"}; + +struct timeval tv_delay; +int subtitledelay, delaystarted; +FILE *conf; + + +neutrino_msg_t RCCode; + +struct _pid_table +{ + int vtxt_pid; + int service_id; + int service_name_len; + char service_name[24]; + int national_subset; +}pid_table[128]; + +unsigned char restoreaudio = 0; +/* 0 Nokia, 1 Philips, 2 Sagem */ +/* typ_vcr/dvb: v1 a1 v2 a2 v3 a3 (vcr_only: fblk) */ + +/* language dependent texts */ +#define MAXMENULANGUAGE 10 /* 0 deutsch, 1 englisch, 2 französisch, 3 niederländisch, 4 griechisch, 5 italienisch, 6 polnisch, 7 schwedisch, 8 suomi, 9 portuguesa, 10 russian */ +const int menusubset[] = { NAT_DE , NAT_UK , NAT_FR , NAT_UK , NAT_GR , NAT_IT , NAT_PL , NAT_SW , NAT_SW , NAT_SP, NAT_RB};//FIXME + +#define Menu_StartX (StartX + fontwidth*9/2) +#define Menu_StartY (StartY + (25 - Menu_Height) * fontheight / 2) +#define Menu_Height 23 +#define Menu_Width 31 + +const char MenuLine[] = +{ + 3,8,11,14,16,18,19,20 +}; + +enum +{ + M_HOT=0, + M_PID, + M_SC1, + M_COL, + M_TRA, + M_AUN, + M_NAT, + M_LNG, + M_Number +}; + +#define M_Start M_HOT +#define M_MaxDirect M_AUN + +const char hotlistpagecolumn[] = /* last(!) column of page to show in each language */ +{ + 22, 26, 28, 27, 28, 27, 28, 21, 20, 26, 26 +}; +const char hotlisttextcolumn[] = +{ + 24, 14, 14, 15, 14, 15, 14, 23, 22, 14, 14 +}; +const char hotlisttext[][2*6] = +{ + { "dazu entf." }, + { " add rem. " }, + { "ajoutenlev" }, + { "toev.verw." }, + { "pq|shava_q" }, + { "agg. elim." }, + { "dodajkasuj" }, + { "ny bort " }, + { "lis{{pois " }, + { " adi rem. " }, + { "Dob. Udal." } +}; + +const char configonoff[][2*4] = +{ + { "ausein" }, + { "offon " }, + { "desact" }, + { "uitaan" }, + { "emeape" }, + { "offon " }, + { "wy}w} " }, + { "p} av " }, + { "EI ON " }, + { "offon " }, + { "w&kwkl" } +}; +const char menuatr[Menu_Height*(Menu_Width+1)] = +{ + "0000000000000000000000000000002" + "0111111111111111111111111111102" + "0000000000000000000000000000002" + "3144444444444444444444444444432" + "3556655555555555555555555555532" + "3555555555555555555555555555532" + "3333333333333333333333333333332" + "3144444444444444444444444444432" + "3555555555555555555555555555532" + "3333333333333333333333333333332" + "3444444444444444444444444444432" + "3155555555555555555555555555532" + "3333333333333333333333333333332" + "3144444444444444444444444444432" + "3555555555555555555555555555532" + "3144444444444444444444444444432" + "3555555555555555555555555555532" + "3144444444444444444444444444432" + "3555555555555555555555555555532" + "3555555555555555555555555555532" + "3555555555555555555555555555532" + "3334444444444444444444444443332" + "2222222222222222222222222222222" +}; +const char configmenu[][Menu_Height*(Menu_Width+1)] = +{ + { +/* 0123456789012345678901234567890 */ + "àááááááááááááááááááááááááááááâè" + "ã Konfigurationsmen} äé" + "åææææææææææææææææææææææææææææçé" + "ã1 Favoriten: Seite 111 dazu äé" + "ãíîñò äé" + "ã+-? äé" + "ã äé" + "ã2 Teletext-Auswahl äé" + "ãí suchen îäé" + "ã äé" + "ã Bildschirmformat äé" + "ã3 Standard-Modus 16:9 äé" + "ã äé" + "ã4 Helligkeit äé" + "ãí îäé" + "ã5 Transparenz äé" + "ãí îäé" + "ã6 nationaler Zeichensatz äé" + "ãautomatische Erkennung äé" + "ãí îäé" + "ãí Sprache/Language deutsch îäé" + "åæ www.tuxtxt.net x.xx æçé" + "ëìììììììììììììììììììììììììììììê" + }, +/* 0000000000111111111122222222223 */ +/* 0123456789012345678901234567890 */ + { + "àááááááááááááááááááááááááááááâè" + "ã Configuration menu äé" + "åææææææææææææææææææææææææææææçé" + "ã1 Favorites: add page 111 äé" + "ãíîñò äé" + "ã+-? äé" + "ã äé" + "ã2 Teletext selection äé" + "ãí search îäé" + "ã äé" + "ã Screen format äé" + "ã3 Standard mode 16:9 äé" + "ã äé" + "ã4 Brightness äé" + "ãí îäé" + "ã5 Transparency äé" + "ãí îäé" + "ã6 national characterset äé" + "ã automatic recognition äé" + "ãí îäé" + "ãí Sprache/language english îäé" + "åæ www.tuxtxt.net x.xx æçé" + "ëìììììììììììììììììììììììììììììê" + }, +/* 0000000000111111111122222222223 */ +/* 0123456789012345678901234567890 */ + { + "àááááááááááááááááááááááááááááâè" + "ã Menu de configuration äé" + "åææææææææææææææææææææææææææææçé" + "ã1 Favorites: ajout. page 111äé" + "ãíîñò äé" + "ã+-? äé" + "ã äé" + "ã2 Selection de teletext äé" + "ãí recherche îäé" + "ã äé" + "ã Format de l'#cran äé" + "ã3 Mode standard 16:9 äé" + "ã äé" + "ã4 Clarte äé" + "ãí îäé" + "ã5 Transparence äé" + "ãí îäé" + "ã6 police nationale äé" + "ãreconn. automatique äé" + "ãí îäé" + "ãí Sprache/language francaisîäé" + "åæ www.tuxtxt.net x.xx æçé" + "ëìììììììììììììììììììììììììììììê" + }, +/* 0000000000111111111122222222223 */ +/* 0123456789012345678901234567890 */ + { + "àááááááááááááááááááááááááááááâè" + "ã Configuratiemenu äé" + "åææææææææææææææææææææææææææææçé" + "ã1 Favorieten: toev. pag 111 äé" + "ãíîñò äé" + "ã+-? äé" + "ã äé" + "ã2 Teletekst-selectie äé" + "ãí zoeken îäé" + "ã äé" + "ã Beeldschermformaat äé" + "ã3 Standaardmode 16:9 äé" + "ã äé" + "ã4 Helderheid äé" + "ãí îäé" + "ã5 Transparantie äé" + "ãí îäé" + "ã6 nationale tekenset äé" + "ãautomatische herkenning äé" + "ãí îäé" + "ãí Sprache/Language nederl. îäé" + "åæ www.tuxtxt.net x.xx æçé" + "ëìììììììììììììììììììììììììììììê" + }, +/* 0000000000111111111122222222223 */ +/* 0123456789012345678901234567890 */ + { + "àááááááááááááááááááááááááááááâè" + "ã Lemo} quhl_seym äé" + "åææææææææææææææææææææææææææææçé" + "ã1 Vaboq_: pqo_h. sek. 111äé" + "ãíîñò äé" + "ã+-? äé" + "ã äé" + "ã2 Epikoc^ Teket]nt äé" + "ãí Amaf^tgsg îäé" + "ã äé" + "ã Loqv^ oh|mgr äé" + "ã3 Tq|por pq|tupor 16:9 äé" + "ã äé" + "ã4 Kalpq|tgta äé" + "ãí îäé" + "ã5 Diav\\meia äé" + "ãí îäé" + "ã6 Ehmij^ tuposeiq\\ äé" + "ãaut|latg amacm~qisg äé" + "ãí îäé" + "ãí Ck~ssa/Language ekkgmij\\ îäé" + "åæ www.tuxtxt.net x.xx æçé" + "ëìììììììììììììììììììììììììììììê" + }, +/* 0000000000111111111122222222223 */ +/* 0123456789012345678901234567890 */ + { + "àááááááááááááááááááááááááááááâè" + "ã Menu di configurazione äé" + "åææææææææææææææææææææææææææææçé" + "ã1 Preferiti: agg. pag.111 äé" + "ãíîñò äé" + "ã+-? äé" + "ã äé" + "ã2 Selezione televideo äé" + "ãí ricerca îäé" + "ã äé" + "ã Formato schermo äé" + "ã3 Modo standard 16:9 äé" + "ã äé" + "ã4 Luminosit{ äé" + "ãí îäé" + "ã5 Trasparenza äé" + "ãí îäé" + "ã6 nazionalita'caratteri äé" + "ã riconoscimento automatico äé" + "ãí îäé" + "ãí Lingua/Language Italiana îäé" + "åæ www.tuxtxt.net x.xx æçé" + "ëìììììììììììììììììììììììììììììê" + }, +/* 0000000000111111111122222222223 */ +/* 0123456789012345678901234567890 */ + { + "àááááááááááááááááááááááááááááâè" + "ã Konfiguracja äé" + "åææææææææææææææææææææææææææææçé" + "ã1 Ulubione : kasuj str. 111äé" + "ãíîñò äé" + "ã+-? äé" + "ã äé" + "ã2 Wyb_r telegazety äé" + "ãí szukaj îäé" + "ã äé" + "ã Format obrazu äé" + "ã3 Tryb standard 16:9 äé" + "ã äé" + "ã4 Jasno|^ äé" + "ãí îäé" + "ã5 Prze~roczysto|^ äé" + "ãí îäé" + "ã6 Znaki charakterystyczne äé" + "ã automatyczne rozpozn. äé" + "ãí îäé" + "ãí J`zyk/Language polski îäé" + "åæ www.tuxtxt.net x.xx æçé" + "ëìììììììììììììììììììììììììììììê" + }, +/* 0000000000111111111122222222223 */ +/* 0123456789012345678901234567890 */ + { + "àááááááááááááááááááááááááááááâè" + "ã Konfigurationsmeny äé" + "åææææææææææææææææææææææææææææçé" + "ã1 Favoriter: sida 111 ny äé" + "ãíîñò äé" + "ã+-? äé" + "ã äé" + "ã2 TextTV v{ljaren äé" + "ãí s|k îäé" + "ã äé" + "ã TV- format äé" + "ã3 Standard l{ge 16:9 äé" + "ã äé" + "ã4 Ljusstyrka äé" + "ãí îäé" + "ã5 Genomskinlighet äé" + "ãí îäé" + "ã6nationell teckenupps{ttningäé" + "ã automatisk igenk{nning äé" + "ãí îäé" + "ãí Sprache/language svenska îäé" + "åæ www.tuxtxt.net x.xx æçé" + "ëìììììììììììììììììììììììììììììê" + }, +/* 0000000000111111111122222222223 */ +/* 0123456789012345678901234567890 */ + { + "àááááááááááááááááááááááááááááâè" + "ã Asetusvalikko äé" + "åææææææææææææææææææææææææææææçé" + "ã1 Suosikit: sivu 111 lis{{ äé" + "ãíîñò äé" + "ã+-? äé" + "ã äé" + "ã2 Tekstikanavan valinta äé" + "ãí search îäé" + "ã äé" + "ã N{ytt|tila äé" + "ã3 Vakiotila 16:9 äé" + "ã äé" + "ã4 Kirkkaus äé" + "ãí îäé" + "ã5 L{pin{kyvyys äé" + "ãí îäé" + "ã6 kansallinen merkist| äé" + "ã automaattinen tunnistus äé" + "ãí îäé" + "ãí Kieli suomi îäé" + "åæ www.tuxtxt.net x.xx æçé" + "ëìììììììììììììììììììììììììììììê" + }, +/* 0000000000111111111122222222223 */ +/* 0123456789012345678901234567890 */ + { + "àááááááááááááááááááááááááááááâè" + "ã Menu de Configuracao äé" + "åææææææææææææææææææææææææææææçé" + "ã1 Favoritos: adi pag. 111 äé" + "ãíîñò äé" + "ã+-? äé" + "ã äé" + "ã2 Seleccao Teletext äé" + "ãí Procurar îäé" + "ã äé" + "ã formato ecran äé" + "ã3 Standard mode 16:9 äé" + "ã äé" + "ã4 Brilho äé" + "ãí îäé" + "ã5 Transparencia äé" + "ãí îäé" + "ã6 Caracteres nacionaist äé" + "ãreconhecimento utomatico äé" + "ãí îäé" + "ãí Lingua Portuguesa îäé" + "åæ www.tuxtxt.net x.xx æçé" + "ëìììììììììììììììììììììììììììììê" + }, +/* 0000000000111111111122222222223 */ +/* 0123456789012345678901234567890 */ + { + "àááááááááááááááááááááááááááááâè" + "ã Konfiguraciq äé" + "åææææææææææææææææææææææææææææçé" + "ã1 Faworit&: dob str. 111 äé" + "ãíîñò äé" + "ã+-? äé" + "ã äé" + "ã2 W&bor teleteksta äé" + "ãí Poisk îäé" + "ã äé" + "ã Format kartinki äé" + "ã3 Stand. revim 16:9 äé" + "ã äé" + "ã4 Qrkostx äé" + "ãí îäé" + "ã5 Prozra~nostx äé" + "ãí îäé" + "ã6 Ispolxzuem&j alfawit äé" + "ã awtoopredelenie äé" + "ãí îäé" + "ãí Qz&k: Russkij îäé" + "åæ www.tuxtxt.net x.xx æçé" + "ëìììììììììììììììììììììììììììììê" + } +}; + +const char catchmenutext[][81] = +{ + { " íïðî w{hlen ñò anzeigen " + "0000000011110000000000110000000000000000" }, + { " íïðî select ñò show " + "0000000011110000000000110000000000000000" }, + { " íïðî selectionner ñò montrer " + "0011110000000000000000110000000000000000" }, + { " íïðî kiezen ñò tonen " + "0000000011110000000000110000000000000000" }, + { " íïðî epikoc^ ñò pqobok^ " + "0000000011110000000000110000000000000000" }, + { " íïðîseleziona ñò mostra " + "0000000011110000000000110000000000000000" }, + { " íïðî wybiez ñò wyswietl " + "0000000011110000000000110000000000000000" }, + { " íïðî v{lj ñò visa " + "0000000011110000000000110000000000000000" }, + { " íïðî valitse ñò n{yt{ " + "0000000011110000000000110000000000000000" }, + { " íïðî seleccao ñò mostrar " + "0000000011110000000000110000000000000000" }, + { " íïðî w&bratx ñò pokazatx " + "0000000011110000000000110000000000000000" }, +}; + +const char message_3[][39] = +{ + { "ã suche nach Teletext-Anbietern äé" }, + { "ã searching for teletext Services äé" }, + { "ã recherche des services teletext äé" }, + { "ã zoeken naar teletekst aanbieders äé" }, + { "ã amaf^tgsg voq]ym Teket]nt äé" }, + { "ã attesa opzioni televideo äé" }, + { "ã poszukiwanie sygna}u telegazety äé" }, + { "ã s|ker efter TextTV tj{nster äé" }, + { "ã etsit{{n Teksti-TV -palvelua äé" }, + { "ã Procurar servicos de teletexto äé" }, + { "ã W&polnqetsq poisk teleteksta äé" }, +}; +const char message_3_blank[] = "ã äé"; +const char message_7[][39] = +{ + { "ã kein Teletext auf dem Transponder äé" }, + { "ã no teletext on the transponder äé" }, + { "ã pas de teletext sur le transponderäé" }, + { "ã geen teletekst op de transponder äé" }, + { "ã jal]la Teket]nt ston amaletadot^ äé" }, + { "ã nessun televideo sul trasponder äé" }, + { "ã brak sygna}u na transponderze äé" }, + { "ã ingen TextTV p} denna transponder äé" }, + { "ã Ei Teksti-TV:t{ l{hettimell{ äé" }, + { "ã nao ha teletexto no transponder äé" }, + { "ã Na transpondere net teleteksta äé" }, +}; +const char message_8[][39] = +{ +/* 00000000001111111111222222222233333333334 */ +/* 01234567890123456789012345678901234567890 */ + { "ã warte auf Empfang von Seite 100 äé" }, + { "ã waiting for reception of page 100 äé" }, + { "ã attentre la réception de page 100 äé" }, + { "ãwachten op ontvangst van pagina 100äé" }, + { "ã amal]my k^xg sek_dar 100 äé" }, + { "ã attesa ricezione pagina 100 äé" }, + { "ã oczekiwanie na stron` 100 äé" }, + { "ã v{ntar p} mottagning av sida 100 äé" }, + { "ã Odotetaan sivua 100 äé" }, + { "ã esperando recepcao na pag 100 äé" }, + { "ã Ovidanie priema stranic& 100 äé" }, +}; +const char message8pagecolumn[] = /* last(!) column of page to show in each language */ +{ + 33, 34, 34, 35, 29, 30, 30, 34, 34, 32, 34 +}; + +enum /* options for charset */ +{ + C_G0P = 0, /* primary G0 */ + C_G0S, /* secondary G0 */ + C_G1C, /* G1 contiguous */ + C_G1S, /* G1 separate */ + C_G2, + C_G3, + C_OFFSET_DRCS = 32 + /* 32..47: 32+subpage# GDRCS (offset/20 in page_char) */ + /* 48..63: 48+subpage# DRCS (offset/20 in page_char) */ +}; + +/* struct for page attributes */ +typedef struct +{ + unsigned char fg :6; /* foreground color */ + unsigned char bg :6; /* background color */ + unsigned char charset :6; /* see enum above */ + unsigned char doubleh :1; /* double height */ + unsigned char doublew :1; /* double width */ + /* ignore at Black Background Color Substitution */ + /* black background set by New Background ($1d) instead of start-of-row default or Black Backgr. ($1c) */ + /* or black background set by level 2.5 extensions */ + unsigned char IgnoreAtBlackBgSubst:1; + unsigned char concealed:1; /* concealed information */ + unsigned char inverted :1; /* colors inverted */ + unsigned char flashing :5; /* flash mode */ + unsigned char diacrit :4; /* diacritical mark */ + unsigned char underline:1; /* Text underlined */ + unsigned char boxwin :1; /* Text boxed/windowed */ + unsigned char setX26 :1; /* Char is set by packet X/26 (no national subset used) */ + unsigned char setG0G2 :7; /* G0+G2 set designation */ +} tstPageAttr; + +enum /* indices in atrtable */ +{ + ATR_WB, /* white on black */ + ATR_PassiveDefault, /* Default for passive objects: white on black, ignore at Black Background Color Substitution */ + ATR_L250, /* line25 */ + ATR_L251, /* line25 */ + ATR_L252, /* line25 */ + ATR_L253, /* line25 */ + ATR_TOPMENU0, /* topmenu */ + ATR_TOPMENU1, /* topmenu */ + ATR_TOPMENU2, /* topmenu */ + ATR_TOPMENU3, /* topmenu */ + ATR_MSG0, /* message */ + ATR_MSG1, /* message */ + ATR_MSG2, /* message */ + ATR_MSG3, /* message */ + ATR_MSGDRM0, /* message */ + ATR_MSGDRM1, /* message */ + ATR_MSGDRM2, /* message */ + ATR_MSGDRM3, /* message */ + ATR_MENUHIL0, /* hilit menu line */ + ATR_MENUHIL1, /* hilit menu line */ + ATR_MENUHIL2, /* hilit menu line */ + ATR_MENU0, /* menu line */ + ATR_MENU1, /* menu line */ + ATR_MENU2, /* menu line */ + ATR_MENU3, /* menu line */ + ATR_MENU4, /* menu line */ + ATR_MENU5, /* menu line */ + ATR_MENU6, /* menu line */ + ATR_CATCHMENU0, /* catch menu line */ + ATR_CATCHMENU1 /* catch menu line */ +}; + +/* define color names */ +enum +{ + black = 0, + red, /* 1 */ + green, /* 2 */ + yellow, /* 3 */ + blue, /* 4 */ + magenta, /* 5 */ + cyan, /* 6 */ + white, /* 7 */ + menu1 = (4*8), + menu2, + menu3, + transp, + transp2, + SIZECOLTABLE +}; + +//const (avoid warnings :<) +tstPageAttr atrtable[] = +{ + { white , black , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_WB */ + { white , black , C_G0P, 0, 0, 1 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_PassiveDefault */ + { white , red , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_L250 */ + { black , green , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_L251 */ + { black , yellow, C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_L252 */ + { white , blue , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_L253 */ + { magenta, black , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_TOPMENU0 */ + { green , black , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_TOPMENU1 */ + { yellow , black , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_TOPMENU2 */ + { cyan , black , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_TOPMENU3 */ + { menu2 , menu3 , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MSG0 */ + { yellow , menu3 , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MSG1 */ + { menu2 , transp, C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MSG2 */ + { white , menu3 , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MSG3 */ + { menu2 , menu1 , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MSGDRM0 */ + { yellow , menu1 , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MSGDRM1 */ + { menu2 , black , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MSGDRM2 */ + { white , menu1 , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MSGDRM3 */ + { menu1 , blue , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MENUHIL0 5a Z */ + { white , blue , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MENUHIL1 58 X */ + { menu2 , transp, C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MENUHIL2 9b › */ + { menu2 , menu1 , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MENU0 ab « */ + { yellow , menu1 , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MENU1 a4 ¤ */ + { menu2 , transp, C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MENU2 9b › */ + { menu2 , menu3 , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MENU3 cb Ë */ + { cyan , menu3 , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MENU4 c7 Ç */ + { white , menu3 , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MENU5 c8 È */ + { white , menu1 , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_MENU6 a8 ¨ */ + { yellow , menu1 , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f}, /* ATR_CATCHMENU0 a4 ¤ */ + { white , menu1 , C_G0P, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0x3f} /* ATR_CATCHMENU1 a8 ¨ */ +}; +/* buffers */ +unsigned char lcd_backbuffer[120*64 / 8]; +unsigned char page_char[40 * 25]; +tstPageAttr page_atrb[40 * 25]; + +//unsigned short page_atrb[40 * 25]; /* ?????:h:cc:bbbb:ffff -> ?=reserved, h=double height, c=charset (0:G0 / 1:G1c / 2:G1s), b=background, f=foreground */ + + +/* colormap */ +const unsigned short defaultcolors[] = /* 0x0bgr */ +{ + 0x000, 0x00f, 0x0f0, 0x0ff, 0xf00, 0xf0f, 0xff0, 0xfff, + 0x000, 0x007, 0x070, 0x077, 0x700, 0x707, 0x770, 0x777, + 0x50f, 0x07f, 0x7f0, 0xbff, 0xac0, 0x005, 0x256, 0x77c, + 0x333, 0x77f, 0x7f7, 0x7ff, 0xf77, 0xf7f, 0xff7, 0xddd, + 0x420, 0x210, 0x420, 0x000, 0x000 +}; + +#if !HAVE_TRIPLEDRAGON +/* 32bit colortable */ +unsigned char bgra[][5] = { +"\0\0\0\xFF", "\0\0\0\xFF", "\0\0\0\xFF", "\0\0\0\xFF", +"\0\0\0\xFF", "\0\0\0\xFF", "\0\0\0\xFF", "\0\0\0\xFF", +"\0\0\0\xFF", "\0\0\0\xFF", "\0\0\0\xFF", "\0\0\0\xFF", +"\0\0\0\xFF", "\0\0\0\xFF", "\0\0\0\xFF", "\0\0\0\xFF", +"\0\0\0\xFF", "\0\0\0\xFF", "\0\0\0\xFF", "\0\0\0\xFF", +"\0\0\0\xFF", "\0\0\0\xFF", "\0\0\0\xFF", "\0\0\0\xFF", +"\0\0\0\xFF", "\0\0\0\xFF", "\0\0\0\xFF", "\0\0\0\xFF", +"\0\0\0\xFF", "\0\0\0\xFF", "\0\0\0\xFF", "\0\0\0\xFF", +"\0\0\0\xFF", "\0\0\0\xFF", "\0\0\0\xC0", "\0\0\0\x00", +"\0\0\0\x33" }; +#else +/* actually "ARGB" */ +unsigned char bgra[][5] = { +"\xFF\0\0\0", "\xFF\0\0\0", "\xFF\0\0\0", "\xFF\0\0\0", +"\xFF\0\0\0", "\xFF\0\0\0", "\xFF\0\0\0", "\xFF\0\0\0", +"\xFF\0\0\0", "\xFF\0\0\0", "\xFF\0\0\0", "\xFF\0\0\0", +"\xFF\0\0\0", "\xFF\0\0\0", "\xFF\0\0\0", "\xFF\0\0\0", +"\xFF\0\0\0", "\xFF\0\0\0", "\xFF\0\0\0", "\xFF\0\0\0", +"\xFF\0\0\0", "\xFF\0\0\0", "\xFF\0\0\0", "\xFF\0\0\0", +"\xFF\0\0\0", "\xFF\0\0\0", "\xFF\0\0\0", "\xFF\0\0\0", +"\xFF\0\0\0", "\xFF\0\0\0", "\xFF\0\0\0", "\xFF\0\0\0", +"\xFF\0\0\0", "\xFF\0\0\0", "\xC0\0\0\0", "\x00\0\0\0", +"\x33\0\0\0" }; +#endif + +/* old 8bit color table */ +unsigned short rd0[] = {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, 0x00<<8, 0x00<<8, 0x00<<8, 0, 0 }; +unsigned short gn0[] = {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, 0x20<<8, 0x10<<8, 0x20<<8, 0, 0 }; +unsigned short bl0[] = {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, 0x40<<8, 0x20<<8, 0x40<<8, 0, 0 }; +unsigned short tr0[] = {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, 0x0000 , 0x0000 , 0x0A00 , 0xFFFF, 0x3000 }; +struct fb_cmap colormap_0 = {0, SIZECOLTABLE, rd0, gn0, bl0, tr0}; + +/* tables for color table remapping, first entry (no remapping) skipped, offsets for color index */ +const unsigned char MapTblFG[] = { 0, 0, 8, 8, 16, 16, 16 }; +const unsigned char MapTblBG[] = { 8, 16, 8, 16, 8, 16, 24 }; + + +/* shapes */ +enum +{ + S_END = 0, + S_FHL, /* full horizontal line: y-offset */ + S_FVL, /* full vertical line: x-offset */ + S_BOX, /* rectangle: x-offset, y-offset, width, height */ + S_TRA, /* trapez: x0, y0, l0, x1, y1, l1 */ + S_BTR, /* trapez in bgcolor: x0, y0, l0, x1, y1, l1 */ + S_INV, /* invert */ + S_LNK, /* call other shape: shapenumber */ + S_CHR, /* Character from freetype hibyte, lowbyte */ + S_ADT, /* Character 2F alternating raster */ + S_FLH, /* flip horizontal */ + S_FLV /* flip vertical */ +}; + +/* shape coordinates */ +enum +{ + S_W13 = 5, /* width*1/3 */ + S_W12, /* width*1/2 */ + S_W23, /* width*2/3 */ + S_W11, /* width */ + S_WM3, /* width-3 */ + S_H13, /* height*1/3 */ + S_H12, /* height*1/2 */ + S_H23, /* height*2/3 */ + S_H11, /* height */ + S_NrShCoord +}; + +/* G3 characters */ +unsigned char aG3_20[] = { S_TRA, 0, S_H23, 1, 0, S_H11, S_W12, S_END }; +unsigned char aG3_21[] = { S_TRA, 0, S_H23, 1, 0, S_H11, S_W11, S_END }; +unsigned char aG3_22[] = { S_TRA, 0, S_H12, 1, 0, S_H11, S_W12, S_END }; +unsigned char aG3_23[] = { S_TRA, 0, S_H12, 1, 0, S_H11, S_W11, S_END }; +unsigned char aG3_24[] = { S_TRA, 0, 0, 1, 0, S_H11, S_W12, S_END }; +unsigned char aG3_25[] = { S_TRA, 0, 0, 1, 0, S_H11, S_W11, S_END }; +unsigned char aG3_26[] = { S_INV, S_LNK, 0x66, S_END }; +unsigned char aG3_27[] = { S_INV, S_LNK, 0x67, S_END }; +unsigned char aG3_28[] = { S_INV, S_LNK, 0x68, S_END }; +unsigned char aG3_29[] = { S_INV, S_LNK, 0x69, S_END }; +unsigned char aG3_2a[] = { S_INV, S_LNK, 0x6a, S_END }; +unsigned char aG3_2b[] = { S_INV, S_LNK, 0x6b, S_END }; +unsigned char aG3_2c[] = { S_INV, S_LNK, 0x6c, S_END }; +unsigned char aG3_2d[] = { S_INV, S_LNK, 0x6d, S_END }; +unsigned char aG3_2e[] = { S_BOX, 2, 0, 3, S_H11, S_END }; +unsigned char aG3_2f[] = { S_ADT }; +unsigned char aG3_30[] = { S_LNK, 0x20, S_FLH, S_END }; +unsigned char aG3_31[] = { S_LNK, 0x21, S_FLH, S_END }; +unsigned char aG3_32[] = { S_LNK, 0x22, S_FLH, S_END }; +unsigned char aG3_33[] = { S_LNK, 0x23, S_FLH, S_END }; +unsigned char aG3_34[] = { S_LNK, 0x24, S_FLH, S_END }; +unsigned char aG3_35[] = { S_LNK, 0x25, S_FLH, S_END }; +unsigned char aG3_36[] = { S_INV, S_LNK, 0x76, S_END }; +unsigned char aG3_37[] = { S_INV, S_LNK, 0x77, S_END }; +unsigned char aG3_38[] = { S_INV, S_LNK, 0x78, S_END }; +unsigned char aG3_39[] = { S_INV, S_LNK, 0x79, S_END }; +unsigned char aG3_3a[] = { S_INV, S_LNK, 0x7a, S_END }; +unsigned char aG3_3b[] = { S_INV, S_LNK, 0x7b, S_END }; +unsigned char aG3_3c[] = { S_INV, S_LNK, 0x7c, S_END }; +unsigned char aG3_3d[] = { S_INV, S_LNK, 0x7d, S_END }; +unsigned char aG3_3e[] = { S_LNK, 0x2e, S_FLH, S_END }; +unsigned char aG3_3f[] = { S_BOX, 0, 0, S_W11, S_H11, S_END }; +unsigned char aG3_40[] = { S_BOX, 0, S_H13, S_W11, S_H13, S_LNK, 0x7e, S_END }; +unsigned char aG3_41[] = { S_BOX, 0, S_H13, S_W11, S_H13, S_LNK, 0x7e, S_FLV, S_END }; +unsigned char aG3_42[] = { S_LNK, 0x50, S_BOX, S_W12, S_H13, S_W12, S_H13, S_END }; +unsigned char aG3_43[] = { S_LNK, 0x50, S_BOX, 0, S_H13, S_W12, S_H13, S_END }; +unsigned char aG3_44[] = { S_LNK, 0x48, S_FLV, S_LNK, 0x48, S_END }; +unsigned char aG3_45[] = { S_LNK, 0x44, S_FLH, S_END }; +unsigned char aG3_46[] = { S_LNK, 0x47, S_FLV, S_END }; +unsigned char aG3_47[] = { S_LNK, 0x48, S_FLH, S_LNK, 0x48, S_END }; +unsigned char aG3_48[] = { S_TRA, 0, 0, S_W23, 0, S_H23, 0, S_BTR, 0, 0, S_W13, 0, S_H13, 0, S_END }; +unsigned char aG3_49[] = { S_LNK, 0x48, S_FLH, S_END }; +unsigned char aG3_4a[] = { S_LNK, 0x48, S_FLV, S_END }; +unsigned char aG3_4b[] = { S_LNK, 0x48, S_FLH, S_FLV, S_END }; +unsigned char aG3_4c[] = { S_LNK, 0x50, S_BOX, 0, S_H13, S_W11, S_H13, S_END }; +unsigned char aG3_4d[] = { S_CHR, 0x25, 0xE6 }; +unsigned char aG3_4e[] = { S_CHR, 0x25, 0xCF }; +unsigned char aG3_4f[] = { S_CHR, 0x25, 0xCB }; +unsigned char aG3_50[] = { S_BOX, S_W12, 0, 2, S_H11, S_FLH, S_BOX, S_W12, 0, 2, S_H11,S_END }; +unsigned char aG3_51[] = { S_BOX, 0, S_H12, S_W11, 2, S_FLV, S_BOX, 0, S_H12, S_W11, 2,S_END }; +unsigned char aG3_52[] = { S_LNK, 0x55, S_FLH, S_FLV, S_END }; +unsigned char aG3_53[] = { S_LNK, 0x55, S_FLV, S_END }; +unsigned char aG3_54[] = { S_LNK, 0x55, S_FLH, S_END }; +unsigned char aG3_55[] = { S_LNK, 0x7e, S_FLV, S_BOX, 0, S_H12, S_W12, 2, S_FLV, S_BOX, 0, S_H12, S_W12, 2, S_END }; +unsigned char aG3_56[] = { S_LNK, 0x57, S_FLH, S_END}; +unsigned char aG3_57[] = { S_LNK, 0x55, S_LNK, 0x50 , S_END}; +unsigned char aG3_58[] = { S_LNK, 0x59, S_FLV, S_END}; +unsigned char aG3_59[] = { S_LNK, 0x7e, S_LNK, 0x51 , S_END}; +unsigned char aG3_5a[] = { S_LNK, 0x50, S_LNK, 0x51 , S_END}; +unsigned char aG3_5b[] = { S_CHR, 0x21, 0x92}; +unsigned char aG3_5c[] = { S_CHR, 0x21, 0x90}; +unsigned char aG3_5d[] = { S_CHR, 0x21, 0x91}; +unsigned char aG3_5e[] = { S_CHR, 0x21, 0x93}; +unsigned char aG3_5f[] = { S_CHR, 0x00, 0x20}; +unsigned char aG3_60[] = { S_INV, S_LNK, 0x20, S_END }; +unsigned char aG3_61[] = { S_INV, S_LNK, 0x21, S_END }; +unsigned char aG3_62[] = { S_INV, S_LNK, 0x22, S_END }; +unsigned char aG3_63[] = { S_INV, S_LNK, 0x23, S_END }; +unsigned char aG3_64[] = { S_INV, S_LNK, 0x24, S_END }; +unsigned char aG3_65[] = { S_INV, S_LNK, 0x25, S_END }; +unsigned char aG3_66[] = { S_LNK, 0x20, S_FLV, S_END }; +unsigned char aG3_67[] = { S_LNK, 0x21, S_FLV, S_END }; +unsigned char aG3_68[] = { S_LNK, 0x22, S_FLV, S_END }; +unsigned char aG3_69[] = { S_LNK, 0x23, S_FLV, S_END }; +unsigned char aG3_6a[] = { S_LNK, 0x24, S_FLV, S_END }; +unsigned char aG3_6b[] = { S_BOX, 0, 0, S_W11, S_H13, S_TRA, 0, S_H13, S_W11, 0, S_H23, 1, S_END }; +unsigned char aG3_6c[] = { S_TRA, 0, 0, 1, 0, S_H12, S_W12, S_FLV, S_TRA, 0, 0, 1, 0, S_H12, S_W12, S_BOX, 0, S_H12, S_W12,1, S_END }; +unsigned char aG3_6d[] = { S_TRA, 0, 0, S_W12, S_W12, S_H12, 0, S_FLH, S_TRA, 0, 0, S_W12, S_W12, S_H12, 0, S_END }; +unsigned char aG3_6e[] = { S_CHR, 0x00, 0x20}; +unsigned char aG3_6f[] = { S_CHR, 0x00, 0x20}; +unsigned char aG3_70[] = { S_INV, S_LNK, 0x30, S_END }; +unsigned char aG3_71[] = { S_INV, S_LNK, 0x31, S_END }; +unsigned char aG3_72[] = { S_INV, S_LNK, 0x32, S_END }; +unsigned char aG3_73[] = { S_INV, S_LNK, 0x33, S_END }; +unsigned char aG3_74[] = { S_INV, S_LNK, 0x34, S_END }; +unsigned char aG3_75[] = { S_INV, S_LNK, 0x35, S_END }; +unsigned char aG3_76[] = { S_LNK, 0x66, S_FLH, S_END }; +unsigned char aG3_77[] = { S_LNK, 0x67, S_FLH, S_END }; +unsigned char aG3_78[] = { S_LNK, 0x68, S_FLH, S_END }; +unsigned char aG3_79[] = { S_LNK, 0x69, S_FLH, S_END }; +unsigned char aG3_7a[] = { S_LNK, 0x6a, S_FLH, S_END }; +unsigned char aG3_7b[] = { S_LNK, 0x6b, S_FLH, S_END }; +unsigned char aG3_7c[] = { S_LNK, 0x6c, S_FLH, S_END }; +unsigned char aG3_7d[] = { S_LNK, 0x6d, S_FLV, S_END }; +unsigned char aG3_7e[] = { S_BOX, S_W12, 0, 2, S_H12, S_FLH, S_BOX, S_W12, 0, 2, S_H12, S_END };// help char, not printed directly (only by S_LNK) + +unsigned char *aShapes[] = +{ + aG3_20, aG3_21, aG3_22, aG3_23, aG3_24, aG3_25, aG3_26, aG3_27, aG3_28, aG3_29, aG3_2a, aG3_2b, aG3_2c, aG3_2d, aG3_2e, aG3_2f, + aG3_30, aG3_31, aG3_32, aG3_33, aG3_34, aG3_35, aG3_36, aG3_37, aG3_38, aG3_39, aG3_3a, aG3_3b, aG3_3c, aG3_3d, aG3_3e, aG3_3f, + aG3_40, aG3_41, aG3_42, aG3_43, aG3_44, aG3_45, aG3_46, aG3_47, aG3_48, aG3_49, aG3_4a, aG3_4b, aG3_4c, aG3_4d, aG3_4e, aG3_4f, + aG3_50, aG3_51, aG3_52, aG3_53, aG3_54, aG3_55, aG3_56, aG3_57, aG3_58, aG3_59, aG3_5a, aG3_5b, aG3_5c, aG3_5d, aG3_5e, aG3_5f, + aG3_60, aG3_61, aG3_62, aG3_63, aG3_64, aG3_65, aG3_66, aG3_67, aG3_68, aG3_69, aG3_6a, aG3_6b, aG3_6c, aG3_6d, aG3_6e, aG3_6f, + aG3_70, aG3_71, aG3_72, aG3_73, aG3_74, aG3_75, aG3_76, aG3_77, aG3_78, aG3_79, aG3_7a, aG3_7b, aG3_7c, aG3_7d, aG3_7e +}; + +#if 0 +/* lcd layout */ +const char lcd_layout[] = +{ +#define ____ 0x0 +#define ___X 0x1 +#define __X_ 0x2 +#define __XX 0x3 +#define _X__ 0x4 +#define _X_X 0x5 +#define _XX_ 0x6 +#define _XXX 0x7 +#define X___ 0x8 +#define X__X 0x9 +#define X_X_ 0xA +#define X_XX 0xB +#define XX__ 0xC +#define XX_X 0xD +#define XXX_ 0xE +#define XXXX 0xF + +#define i <<4| + + ____ i _XXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXX_ i ____, + ___X i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i X___, + __XX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XX__ i ____,XXX_ i _X__,_XXX i __X_,__XX i X___,___X i XX__,X___ i XXX_,____ i _XXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XX__, + _XXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,X_XX i XXXX,_X_X i X_XX,X_X_ i XX_X,XX_X i _XXX,XXX_ i X_XX,_XXX i _X_X,XXXX i X_XX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXX_, + _XXX i XXXX,X___ i ____,____ i ____,____ i __XX,X_XX i XXXX,_X_X i X_XX,X_X_ i XX_X,XX_X i _XXX,XXX_ i X_XX,_XXX i _X_X,XXXX i X_XX,X___ i ____,____ i ____,____ i ___X,XXXX i XXX_, + XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,X_XX i XXXX,_X_X i X_XX,X_X_ i XX_X,XX_X i _XXX,XXX_ i X_XX,_XXX i _X_X,XXXX i X_XX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX, + XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XX__ i XX__,XX_X i X_XX,X_X_ i XXXX,XX_X i X__X,X__X i X_XX,XXXX i _XX_,_XX_ i _XXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX, + XXXX i XX__,____ i ____,____ i ____,____ i __XX,XXX_ i XX_X,XX_X i X_XX,X_XX i _XXX,__XX i XX_X,X_XX i XX_X,XX__ i XXXX,_XX_ i XXXX,X___ i ____,____ i ____,____ i ____,__XX i XXXX, + XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXX_ i XX_X,XX_X i X_XX,X_X_ i XXXX,XX_X i XX_X,X_XX i X_XX,XXXX i _XXX,_XX_ i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX, + XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXX_ i XX_X,XX_X i X_XX,X_X_ i XX_X,XX_X i XX_X,X_XX i X_XX,_XXX i _XXX,_XX_ i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX, + XXX_ i ____,____ i ____,____ i ____,____ i __XX,XXX_ i XX_X,XX_X i XXXX,X_X_ i XX_X,XX_X i XX_X,X_XX i X_XX,_XXX i _XXX,_XX_ i XXXX,X___ i ____,____ i ____,____ i ____,____ i _XXX, + XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXX_ i XX_X,XX_X i XXXX,X_X_ i XX_X,XX_X i XX_X,X_XX i X_XX,_XXX i _XXX,_XX_ i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX, + XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i __XX,XXX_ i ____,_XXX i __X_,__XX i XXX_,_XXX i XX__,X___ i XXXX,X__X i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX, + XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX, + XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i XX__,_XXX i XXX_,__XX i ___X,XXXX i X___,XX__ i _XXX,XXX_ i __XX,____ i ___X,X___ i XXXX,XX__ i _XX_,__XX i XXXX,___X i XXXX,X___ i XX_X,XX__ i _XXX,XXX_ i __XX,XXXX i ___X, + X__X i __X_,X___ i ___X,_X__ i X_X_,____ i _X_X,__X_ i X___,___X i _X__,X___ i __X_,_X_X i ____,__X_ i X__X,_X__ i ____,X_X_ i ____,_X_X i __X_,__X_ i X___,___X i _X__,____ i X__X, + X__X i __X_,X___ i ___X,_X__ i X_X_,____ i _X_X,__X_ i X___,___X i _X__,X___ i __X_,_X_X i ____,__X_ i X__X,_X__ i ____,X_X_ i ____,_X_X i __X_,__X_ i X___,___X i _X__,____ i X__X, + X__X i __X_,X___ i ___X,_X__ i X_X_,____ i _X_X,__X_ i X___,___X i _X__,X___ i __X_,_X_X i ____,__X_ i X__X,_X__ i ____,X_X_ i ____,_X_X i __X_,__X_ i X___,___X i _X__,____ i X__X, + X__X i __X_,X__X i ___X,_X__ i X__X,X__X i X__X,__X_ i X__X,___X i _X__,X___ i __X_,_X_X i __XX,XX__ i X__X,_X__ i XXXX,__X_ i _X__,_X_X i __X_,__X_ i X__X,___X i _X__,XXXX i ___X, + X__X i __X_,X__X i ___X,_X__ i X___,X__X i ___X,__X_ i X___,___X i _X__,X___ i __X_,_X_X i ____,__X_ i X__X,_X__ i ____,X_X_ i ___X,X__X i __X_,__X_ i X__X,___X i _X__,X___ i X__X, + X__X i __X_,X__X i ___X,_X__ i X___,X__X i ___X,__X_ i X___,___X i _X__,X___ i __X_,_X_X i ____,__X_ i X__X,_X__ i ____,X_X_ i ____,_X_X i __X_,__X_ i X__X,___X i _X__,X___ i X__X, + X__X i __X_,X__X i ___X,_X__ i X___,X__X i ___X,__X_ i X__X,___X i _X__,XXXX i __X_,_X__ i XXX_,__X_ i X__X,_X__ i XXXX,__X_ i _X__,_X_X i __X_,__X_ i X__X,___X i _X__,X___ i X__X, + X__X i __X_,X__X i ___X,_X__ i X___,X__X i ___X,__X_ i X__X,___X i _X__,____ i X_X_,_X_X i ____,__X_ i X__X,_X__ i ____,X_X_ i _X__,_X_X i ____,__X_ i X__X,___X i _X__,____ i X__X, + X__X i __X_,X__X i ___X,_X__ i X___,X__X i ___X,__X_ i X__X,___X i _X__,____ i X_X_,_X_X i ____,__X_ i X__X,_X__ i ____,X_X_ i _X__,_X_X i ____,__X_ i X__X,___X i _X__,____ i X__X, + X___ i XX__,XXX_ i XXXX,__XX i ____,_XX_ i ____,XX__ i _XX_,XXX_ i __XX,XXXX i ___X,X___ i XXXX,XX__ i _XX_,__XX i XXXX,___X i X_XX,X___ i XXXX,XX__ i _XX_,XXX_ i __XX,XXXX i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i ____,XXXX i XXXX,X___ i XXXX,XX__ i _XXX,XXXX i XX__,_XXX i XXX_,__XX i XXXX,___X i XXXX,X___ i ____,__XX i XXXX,___X i X___,XXXX i XX__,_XXX i XXX_,__XX i XXXX,____ i ___X, + X___ i ___X,____ i ____,_X_X i ____,__X_ i X___,____ i __X_,X___ i ___X,_X__ i ____,X_X_ i ____,_X__ i ____,_X__ i ____,X_X_ i _X_X,____ i __X_,X___ i ___X,_X__ i ____,X___ i ___X, + X___ i ___X,____ i ____,_X_X i ____,__X_ i X___,____ i __X_,X___ i ___X,_X__ i ____,X_X_ i ____,_X__ i ____,_X__ i ____,X_X_ i _X_X,____ i __X_,X___ i ___X,_X__ i ____,X___ i ___X, + X___ i ___X,____ i ____,_X_X i ____,__X_ i X___,____ i __X_,X___ i ___X,_X__ i ____,X_X_ i ____,_X__ i ____,_X__ i XX__,X_X_ i _X_X,____ i __X_,X___ i ___X,_X__ i ____,X___ i ___X, + X___ i ___X,__X_ i __X_,_X_X i __X_,__X_ i X__X,___X i __X_,X__X i XXX_,_X__ i X___,X__X i X__X,X___ i ____,_X__ i ____,X_X_ i _X__,XX__ i XX__,_XX_ i _XX_,_X__ i XXXX,____ i ___X, + X___ i ___X,__X_ i __X_,_X_X i __X_,__X_ i X__X,___X i __X_,X___ i ___X,_X__ i X___,X___ i X__X,____ i ____,_X__ i __XX,__X_ i _X__,_X__ i X___,__X_ i _X__,_X__ i ____,X___ i ___X, + X___ i ___X,__X_ i __X_,_X_X i __X_,__X_ i X__X,___X i __X_,X___ i ___X,_X__ i X___,X___ i X__X,____ i ____,_X__ i ____,X_X_ i _X__,_X__ i X___,__X_ i _X__,_X__ i ____,X___ i ___X, + X___ i ___X,__X_ i __X_,_X_X i __X_,__X_ i X__X,___X i __X_,X__X i XXX_,_X__ i X___,X___ i X__X,____ i ____,_X__ i XX__,X_X_ i _X__,_X__ i X___,__X_ i _X__,_X__ i XXXX,____ i ___X, + X___ i ___X,__X_ i __X_,_X_X i ____,__X_ i X__X,___X i __X_,X___ i ___X,_X__ i X___,X___ i X__X,____ i ____,_X__ i ____,X_X_ i _X__,_X__ i X___,__X_ i _X__,_X__ i ____,X___ i ___X, + X___ i ___X,__X_ i __X_,_X_X i ____,__X_ i X__X,___X i __X_,X___ i ___X,_X__ i X___,X___ i X__X,____ i ____,_X__ i ____,X_X_ i _X__,_X__ i X___,__X_ i _X__,_X__ i ____,X___ i ___X, + X___ i ____,XX_X i XX_X,X___ i XXXX,XX__ i _XX_,XXX_ i XX__,_XXX i XXX_,__XX i _XXX,____ i _XX_,____ i ____,__XX i XXXX,___X i X___,__XX i ____,___X i X___,__XX i XXXX,____ i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + X___ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ___X, + _X__ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i __X_, + _X__ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i __X_, + __X_ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i _X__, + ___X i X___,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,____ i ____,___X i X___, + ____ i _XXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXXX i XXXX,XXX_ i ____, + +#undef i +}; + +/* lcd digits */ +const char lcd_digits[] = +{ + 0,1,1,1,1,1,1,1,1,0, + 1,1,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,1,1,0,0,0,1, + 1,0,0,0,1,1,0,0,0,1, + 1,0,0,0,1,1,0,0,0,1, + 1,0,0,0,1,1,0,0,0,1, + 1,0,0,0,1,1,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,1,1, + 0,1,1,1,1,1,1,1,1,0, + + 0,0,0,1,1,1,1,0,0,0, + 0,0,1,1,0,0,1,1,0,0, + 0,0,1,0,0,0,0,1,0,0, + 0,0,1,0,0,0,0,1,0,0, + 0,0,1,0,0,0,0,1,0,0, + 0,0,1,0,0,0,0,1,0,0, + 0,0,1,0,0,0,0,1,0,0, + 0,0,1,0,0,0,0,1,0,0, + 0,0,1,0,0,0,0,1,0,0, + 0,0,1,0,0,0,0,1,0,0, + 0,0,1,0,0,0,0,1,0,0, + 0,0,1,0,0,0,0,1,0,0, + 0,0,1,0,0,0,0,1,0,0, + 0,0,1,1,0,0,1,1,0,0, + 0,0,0,1,1,1,1,0,0,0, + + 0,1,1,1,1,1,1,1,1,0, + 1,1,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,0,1, + 0,1,1,1,1,1,0,0,0,1, + 1,1,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,1,1, + 1,0,0,0,0,1,1,1,1,0, + 1,0,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,1,1, + 0,1,1,1,1,1,1,1,1,0, + + 0,1,1,1,1,1,1,1,1,0, + 1,1,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,0,1, + 0,1,1,1,1,1,0,0,0,1, + 1,1,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,1,1,0, + 1,1,0,0,0,0,0,0,1,1, + 0,1,1,1,1,1,0,0,0,1, + 1,1,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,1,1, + 0,1,1,1,1,1,1,1,1,0, + + 0,1,1,1,0,1,1,1,1,0, + 1,1,0,1,1,1,0,0,1,1, + 1,0,0,0,1,0,0,0,0,1, + 1,0,0,0,1,0,0,0,0,1, + 1,0,0,0,1,0,0,0,0,1, + 1,0,0,0,1,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,0,1, + 0,1,1,1,1,0,0,0,0,1, + 0,0,0,0,1,0,0,0,0,1, + 0,0,0,0,1,0,0,0,0,1, + 0,0,0,0,1,0,0,0,0,1, + 0,0,0,0,1,1,0,0,1,1, + 0,0,0,0,0,1,1,1,1,0, + + 0,1,1,1,1,1,1,1,1,0, + 1,1,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,1,1, + 1,0,0,0,0,1,1,1,1,0, + 1,0,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,0,1, + 0,1,1,1,1,1,0,0,0,1, + 1,1,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,1,1, + 0,1,1,1,1,1,1,1,1,0, + + 0,1,1,1,1,1,1,1,1,0, + 1,1,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,1,1, + 1,0,0,0,0,1,1,1,1,0, + 1,0,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,1,1,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,1,1, + 0,1,1,1,1,1,1,1,1,0, + + 0,1,1,1,1,1,1,1,1,0, + 1,1,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,0,1, + 0,1,1,1,1,0,0,0,0,1, + 0,0,0,0,1,0,0,0,0,1, + 0,0,0,0,1,0,0,0,0,1, + 0,0,0,0,1,0,0,0,0,1, + 0,0,0,0,1,0,0,0,0,1, + 0,0,0,0,1,0,0,0,0,1, + 0,0,0,0,1,0,0,0,0,1, + 0,0,0,0,1,0,0,0,0,1, + 0,0,0,0,1,1,0,0,1,1, + 0,0,0,0,0,1,1,1,1,0, + + 0,1,1,1,1,1,1,1,1,0, + 1,1,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,1,1,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,1,1, + 0,1,1,0,0,0,0,1,1,0, + 1,1,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,1,1,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,1,1, + 0,1,1,1,1,1,1,1,1,0, + + 0,1,1,1,1,1,1,1,1,0, + 1,1,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,1,1,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,0,1, + 0,1,1,1,1,0,0,0,0,1, + 1,1,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,1,1, + 0,1,1,1,1,1,1,1,1,0, + + /* 10: - */ + 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,1,1,1,1,1,1,0,0, + 0,1,0,0,0,0,0,0,1,0, + 0,1,0,0,0,0,0,0,1,0, + 0,1,0,0,0,0,0,0,1,0, + 0,0,1,1,1,1,1,1,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, + + /* 11: / */ + 0,0,0,0,1,1,1,1,0,0, + 0,0,0,1,0,0,0,0,1,0, + 0,0,0,1,0,0,0,0,1,0, + 0,0,0,1,0,0,0,0,1,0, + 0,0,0,1,0,0,0,0,1,0, + 0,0,1,0,0,0,0,1,0,0, + 0,0,1,0,0,0,0,1,0,0, + 0,0,1,0,0,0,0,1,0,0, + 0,0,1,0,0,0,0,1,0,0, + 0,0,1,0,0,0,0,1,0,0, + 0,1,0,0,0,0,1,0,0,0, + 0,1,0,0,0,0,1,0,0,0, + 0,1,0,0,0,0,1,0,0,0, + 0,1,0,0,0,0,1,0,0,0, + 0,0,1,1,1,1,0,0,0,0, + + /* 12: ? */ + 0,1,1,1,1,1,1,1,1,0, + 1,1,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,1,0,0,0,0,0,0,0,1, + 0,1,1,1,1,1,0,0,0,1, + 1,1,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,1,1, + 1,1,1,1,1,1,1,1,1,0, + 1,0,0,0,0,1,0,0,0,0, + 1,0,0,0,0,1,0,0,0,0, + 1,0,0,0,0,1,0,0,0,0, + 1,1,0,0,1,1,0,0,0,0, + 0,1,1,1,1,0,0,0,0,0, + + /* 13: " " */ + 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,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, +}; +#endif +/* functions */ +void ConfigMenu(int Init); +void CleanUp(); +void PageInput(int Number); +void ColorKey(int); +void PageCatching(); +void CatchNextPage(int, int); +void GetNextPageOne(int up); +void GetNextSubPage(int offset); +void SwitchZoomMode(); +void SwitchScreenMode(int newscreenmode); +void SwitchTranspMode(); +void SwitchHintMode(); +void CreateLine25(); +void CopyBB2FB(); +void RenderCatchedPage(); +void RenderCharFB(int Char, tstPageAttr *Attribute); +void RenderCharBB(int Char, tstPageAttr *Attribute); +void RenderCharLCD(int Digit, int XPos, int YPos); +void RenderMessage(int Message); +void RenderPage(); +void DecodePage(); +void UpdateLCD(); +int Init(int source); +int GetNationalSubset(const char *country_code); +int GetTeletextPIDs(); +int GetRCCode(); +int eval_triplet(int iOData, tstCachedPage *pstCachedPage, + unsigned char *pAPx, unsigned char *pAPy, + unsigned char *pAPx0, unsigned char *pAPy0, + unsigned char *drcssubp, unsigned char *gdrcssubp, + signed char *endcol, tstPageAttr *attrPassive, unsigned char* pagedata); +void eval_object(int iONr, tstCachedPage *pstCachedPage, + unsigned char *pAPx, unsigned char *pAPy, + unsigned char *pAPx0, unsigned char *pAPy0, + tObjType ObjType, unsigned char* pagedata); + + +#endif +#endif diff --git a/lib/libtuxtxt_mp/tuxtxt2.conf b/lib/libtuxtxt_mp/tuxtxt2.conf new file mode 100644 index 000000000..cbde68f1e --- /dev/null +++ b/lib/libtuxtxt_mp/tuxtxt2.conf @@ -0,0 +1,19 @@ +ScreenMode16x9Normal 0 +ScreenMode16x9Divided 0 +Brightness 10 +MenuLanguage 1 +AutoNational 1 +NationalSubset 5 +SwapUpDown 0 +ShowHexPages 0 +Transparency 0x1 +TTFWidthFactor16 22 +TTFHeightFactor16 14 +TTFShiftX 0 +TTFShiftY -2 +Screenmode 0 +ShowFLOF 1 +Show39 1 +ShowLevel2p5 1 +DumpLevel2p5 0 +UseTTF 1 diff --git a/lib/libtuxtxt_mp/tuxtxt_common.h b/lib/libtuxtxt_mp/tuxtxt_common.h new file mode 100644 index 000000000..6ecee41b5 --- /dev/null +++ b/lib/libtuxtxt_mp/tuxtxt_common.h @@ -0,0 +1,1146 @@ +/* tuxtxt_common.h + * for license info see the other tuxtxt files + */ +#include +#include +#include +#include +#include +#include +#include +#include +#if TUXTXT_COMPRESS == 1 +#include +#endif + +#include + +tuxtxt_cache_struct tuxtxt_cache; +static pthread_mutex_t tuxtxt_cache_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t tuxtxt_cache_biglock = PTHREAD_MUTEX_INITIALIZER; +int tuxtxt_get_zipsize(int p,int sp) +{ + tstCachedPage* pg = tuxtxt_cache.astCachetable[p][sp]; + if (!pg) return 0; +#if TUXTXT_COMPRESS == 1 + return pg->ziplen; +#elif TUXTXT_COMPRESS == 2 + pthread_mutex_lock(&tuxtxt_cache_lock); + int zipsize = 0,i,j; + for (i = 0; i < 23*5; i++) + for (j = 0; j < 8; j++) + zipsize += pg->bitmask[i]>>j & 0x01; + + zipsize+=23*5;//bitmask + pthread_mutex_unlock(&tuxtxt_cache_lock); + return zipsize; +#else + return 23*40; +#endif +} +void tuxtxt_compress_page(int p, int sp, unsigned char* buffer) +{ + pthread_mutex_lock(&tuxtxt_cache_lock); + tstCachedPage* pg = tuxtxt_cache.astCachetable[p][sp]; + if (!pg) + { + printf("tuxtxt: trying to compress a not allocated page!!\n"); + pthread_mutex_unlock(&tuxtxt_cache_lock); + return; + } + +#if TUXTXT_COMPRESS == 1 + unsigned char pagecompressed[23*40]; + uLongf comprlen = 23*40; + if (compress2(pagecompressed,&comprlen,buffer,23*40,Z_BEST_SPEED) == Z_OK) + { + if (pg->pData) free(pg->pData);//realloc(pg->pData,j); realloc scheint nicht richtig zu funktionieren? + pg->pData = malloc(comprlen); + pg->ziplen = 0; + if (pg->pData) + { + pg->ziplen = comprlen; + memmove(pg->pData,pagecompressed,comprlen); + } + } +#elif TUXTXT_COMPRESS == 2 + int i,j=0; + unsigned char cbuf[23*40]; + memset(pg->bitmask,0,sizeof(pg->bitmask)); + for (i = 0; i < 23*40; i++) + { + if (i && buffer[i] == buffer[i-1]) + continue; + pg->bitmask[i>>3] |= 0x80>>(i&0x07); + cbuf[j++]=buffer[i]; + } + if (pg->pData) + free(pg->pData);//realloc(pg->pData,j); realloc scheint nicht richtig zu funktionieren? + pg->pData = (unsigned char*)malloc(j); + if (pg->pData) + { + memmove(pg->pData,cbuf,j); + } + else + memset(pg->bitmask,0,sizeof(pg->bitmask)); +#else + //if (pg->pData) + memmove(pg->data,buffer,23*40); +#endif + pthread_mutex_unlock(&tuxtxt_cache_lock); +} + +void tuxtxt_decompress_page(int p, int sp, unsigned char* buffer) +{ + pthread_mutex_lock(&tuxtxt_cache_lock); + tstCachedPage* pg = tuxtxt_cache.astCachetable[p][sp]; + + memset(buffer,' ',23*40); + if (!pg) + { + printf("tuxtxt: trying to decompress a not allocated page!!\n"); + pthread_mutex_unlock(&tuxtxt_cache_lock); + return; + } +#if TUXTXT_COMPRESS == 1 + if (pg->pData) + { + if (pg->ziplen) + { + uLongf comprlen = 23*40; + uncompress(buffer,&comprlen,pg->pData,pg->ziplen); + } + +#elif TUXTXT_COMPRESS == 2 + if (pg->pData) + { + int i,j=0; + char c=0x20; + for (i = 0; i < 23*40; i++) + { + if (pg->bitmask[i>>3] & 0x80>>(i&0x07)) + c = pg->pData[j++]; + buffer[i] = c; + } +#else + { + memmove(buffer,pg->data,23*40); +#endif + } + pthread_mutex_unlock(&tuxtxt_cache_lock); +} +void tuxtxt_next_dec(int *i) /* skip to next decimal */ +{ + (*i)++; + + if ((*i & 0x0F) > 0x09) + *i += 0x06; + + if ((*i & 0xF0) > 0x90) + *i += 0x60; + + if (*i > 0x899) + *i = 0x100; +} + +void tuxtxt_prev_dec(int *i) /* counting down */ +{ + (*i)--; + + if ((*i & 0x0F) > 0x09) + *i -= 0x06; + + if ((*i & 0xF0) > 0x90) + *i -= 0x60; + + if (*i < 0x100) + *i = 0x899; +} + +int tuxtxt_is_dec(int i) +{ + return ((i & 0x00F) <= 9) && ((i & 0x0F0) <= 0x90); +} + +int tuxtxt_next_hex(int i) /* return next existing non-decimal page number */ +{ + int startpage = i; + if (startpage < 0x100) + startpage = 0x100; + + do + { + i++; + if (i > 0x8FF) + i = 0x100; + if (i == startpage) + break; + } while ((tuxtxt_cache.subpagetable[i] == 0xFF) || tuxtxt_is_dec(i)); + return i; +} +/* + * TOP-Text + * Info entnommen aus videotext-0.6.19991029, + * Copyright (c) 1994-96 Martin Buck + */ +void tuxtxt_decode_btt() +{ + /* basic top table */ + int i, current, b1, b2, b3, b4; + unsigned char btt[23*40] = {0}; + + if (tuxtxt_cache.subpagetable[0x1f0] == 0xff || 0 == tuxtxt_cache.astCachetable[0x1f0][tuxtxt_cache.subpagetable[0x1f0]]) /* not yet received */ + return; + tuxtxt_decompress_page(0x1f0,tuxtxt_cache.subpagetable[0x1f0],btt); + if (btt[799] == ' ') /* not completely received or error */ + return; + + current = 0x100; + for (i = 0; i < 800; i++) + { + b1 = btt[i]; + if (b1 == ' ') + b1 = 0; + else + { + b1 = dehamming[b1]; + if (b1 == 0xFF) /* hamming error in btt */ + { + btt[799] = ' '; /* mark btt as not received */ + return; + } + } + tuxtxt_cache.basictop[current] = b1; + tuxtxt_next_dec(¤t); + } + /* page linking table */ + tuxtxt_cache.maxadippg = -1; /* rebuild table of adip pages */ + for (i = 0; i < 10; i++) + { + b1 = dehamming[btt[800 + 8*i +0]]; + + if (b1 == 0xE) + continue; /* unused */ + else if (b1 == 0xF) + break; /* end */ + + b4 = dehamming[btt[800 + 8*i +7]]; + + if (b4 != 2) /* only adip, ignore multipage (1) */ + continue; + + b2 = dehamming[btt[800 + 8*i +1]]; + b3 = dehamming[btt[800 + 8*i +2]]; + + if (b1 == 0xFF || b2 == 0xFF || b3 == 0xFF) + { + printf("TuxTxt \n", i); + btt[799] = ' '; /* mark btt as not received */ + return; + } + + b1 = b1<<8 | b2<<4 | b3; /* page number */ + tuxtxt_cache.adippg[++tuxtxt_cache.maxadippg] = b1; + } +#if TUXTXT_DEBUG + printf("TuxTxt \n"); +#endif + tuxtxt_cache.bttok = 1; +} + +void tuxtxt_decode_adip() /* additional information table */ +{ + int i, p, j, b1, b2, b3, charfound; + unsigned char padip[23*40]; + + for (i = 0; i <= tuxtxt_cache.maxadippg; i++) + { + p = tuxtxt_cache.adippg[i]; + if (!p || tuxtxt_cache.subpagetable[p] == 0xff || 0 == tuxtxt_cache.astCachetable[p][tuxtxt_cache.subpagetable[p]]) /* not cached (avoid segfault) */ + continue; + + tuxtxt_decompress_page(p,tuxtxt_cache.subpagetable[p],padip); + for (j = 0; j < 44; j++) + { + b1 = dehamming[padip[20*j+0]]; + if (b1 == 0xE) + continue; /* unused */ + + if (b1 == 0xF) + break; /* end */ + + b2 = dehamming[padip[20*j+1]]; + b3 = dehamming[padip[20*j+2]]; + + if (b1 == 0xFF || b2 == 0xFF || b3 == 0xFF) + { + printf("TuxTxt \n", p, j, + padip[20*j+0], + padip[20*j+1], + padip[20*j+2], + b1, b2, b3 + ); + return; + } + + if (b1>8 || b2>9 || b3>9) /* ignore extries with invalid or hex page numbers */ + { + continue; + } + + b1 = b1<<8 | b2<<4 | b3; /* page number */ + charfound = 0; /* flag: no printable char found */ + + for (b2 = 11; b2 >= 0; b2--) + { + b3 = deparity[padip[20*j + 8 + b2]]; + if (b3 < ' ') + b3 = ' '; + + if (b3 == ' ' && !charfound) + tuxtxt_cache.adip[b1][b2] = '\0'; + else + { + tuxtxt_cache.adip[b1][b2] = b3; + charfound = 1; + } + } + } /* next link j */ + tuxtxt_cache.adippg[i] = 0; /* completely decoded: clear entry */ +#if TUXTXT_DEBUG + printf("TuxTxt \n", p); +#endif + } /* next adip page i */ + + while (!tuxtxt_cache.adippg[tuxtxt_cache.maxadippg] && (tuxtxt_cache.maxadippg >= 0)) /* and shrink table */ + tuxtxt_cache.maxadippg--; +} +/****************************************************************************** + * GetSubPage * + ******************************************************************************/ +int tuxtxt_GetSubPage(int page, int subpage, int offset) +{ + int loop; + + + for (loop = subpage + offset; loop != subpage; loop += offset) + { + if (loop < 0) + loop = 0x79; + else if (loop > 0x79) + loop = 0; + if (loop == subpage) + break; + + if (tuxtxt_cache.astCachetable[page][loop]) + { +#if TUXTXT_DEBUG + printf("TuxTxt \n", page, subpage); +#endif + return loop; + } + } + +#if TUXTXT_DEBUG + printf("TuxTxt \n"); +#endif + return subpage; +} + +/****************************************************************************** + * clear_cache * + ******************************************************************************/ + +void tuxtxt_clear_cache(void) +{ + pthread_mutex_lock(&tuxtxt_cache_biglock); + pthread_mutex_lock(&tuxtxt_cache_lock); + int clear_page, clear_subpage, d26; + tuxtxt_cache.maxadippg = -1; + tuxtxt_cache.bttok = 0; + tuxtxt_cache.cached_pages = 0; + tuxtxt_cache.page_receiving = -1; + tuxtxt_cache.vtxtpid = -1; + memset(&tuxtxt_cache.subpagetable, 0xFF, sizeof(tuxtxt_cache.subpagetable)); + memset(&tuxtxt_cache.basictop, 0, sizeof(tuxtxt_cache.basictop)); + memset(&tuxtxt_cache.adip, 0, sizeof(tuxtxt_cache.adip)); + memset(&tuxtxt_cache.flofpages, 0 , sizeof(tuxtxt_cache.flofpages)); + memset(&tuxtxt_cache.timestring, 0x20, 8); + unsigned char magazine; + for (magazine = 1; magazine < 9; magazine++) + { + tuxtxt_cache.current_page [magazine] = -1; + tuxtxt_cache.current_subpage [magazine] = -1; + } + + for (clear_page = 0; clear_page < 0x900; clear_page++) + for (clear_subpage = 0; clear_subpage < 0x80; clear_subpage++) + if (tuxtxt_cache.astCachetable[clear_page][clear_subpage]) + { + tstPageinfo *p = &(tuxtxt_cache.astCachetable[clear_page][clear_subpage]->pageinfo); + if (p->p24) + free(p->p24); + if (p->ext) + { + if (p->ext->p27) + free(p->ext->p27); + for (d26=0; d26 < 16; d26++) + if (p->ext->p26[d26]) + free(p->ext->p26[d26]); + free(p->ext); + } +#if TUXTXT_COMPRESS >0 + if (tuxtxt_cache.astCachetable[clear_page][clear_subpage]->pData) + free(tuxtxt_cache.astCachetable[clear_page][clear_subpage]->pData); +#endif + free(tuxtxt_cache.astCachetable[clear_page][clear_subpage]); + tuxtxt_cache.astCachetable[clear_page][clear_subpage] = 0; + } + for (clear_page = 0; clear_page < 9; clear_page++) + { + if (tuxtxt_cache.astP29[clear_page]) + { + if (tuxtxt_cache.astP29[clear_page]->p27) + free(tuxtxt_cache.astP29[clear_page]->p27); + for (d26=0; d26 < 16; d26++) + if (tuxtxt_cache.astP29[clear_page]->p26[d26]) + free(tuxtxt_cache.astP29[clear_page]->p26[d26]); + free(tuxtxt_cache.astP29[clear_page]); + tuxtxt_cache.astP29[clear_page] = 0; + } + tuxtxt_cache.current_page [clear_page] = -1; + tuxtxt_cache.current_subpage [clear_page] = -1; + } + memset(&tuxtxt_cache.astCachetable, 0, sizeof(tuxtxt_cache.astCachetable)); + memset(&tuxtxt_cache.astP29, 0, sizeof(tuxtxt_cache.astP29)); +#if TUXTXT_DEBUG + printf("TuxTxt cache cleared\n"); +#endif + pthread_mutex_unlock(&tuxtxt_cache_lock); + pthread_mutex_unlock(&tuxtxt_cache_biglock); +} +/****************************************************************************** + * init_demuxer * + ******************************************************************************/ +static cDemux * dmx = NULL; +int tuxtxt_init_demuxer(int source = 0); + +int tuxtxt_init_demuxer(int source) +{ + + if(dmx == NULL) { + dmx = new cDemux(source); + dmx->Open(DMX_PES_CHANNEL, NULL, 2* 3008 * 62 /*64*1024*/); + printf("TuxTxt: source demux %d\n", source); + } +#if TUXTXT_DEBUG + printf("TuxTxt: initialized\n"); +#endif + /* init successfull */ + + return 1; +} +/****************************************************************************** + * CacheThread support functions * + ******************************************************************************/ + +void tuxtxt_decode_p2829(unsigned char *vtxt_row, tstExtData **ptExtData) +{ + int bitsleft, colorindex; + unsigned char *p; + int t1 = deh24(&vtxt_row[7-4]); + int t2 = deh24(&vtxt_row[10-4]); + + if (t1 < 0 || t2 < 0) + { +#if TUXTXT_DEBUG + printf("TuxTxt \n"); +#endif + return; + } + + if (!(*ptExtData)) + (*ptExtData) = (tstExtData*)calloc(1, sizeof(tstExtData)); + if (!(*ptExtData)) + return; + + (*ptExtData)->p28Received = 1; + (*ptExtData)->DefaultCharset = (t1>>7) & 0x7f; + (*ptExtData)->SecondCharset = ((t1>>14) & 0x0f) | ((t2<<4) & 0x70); + (*ptExtData)->LSP = !!(t2 & 0x08); + (*ptExtData)->RSP = !!(t2 & 0x10); + (*ptExtData)->SPL25 = !!(t2 & 0x20); + (*ptExtData)->LSPColumns = (t2>>6) & 0x0f; + + bitsleft = 8; /* # of bits not evaluated in val */ + t2 >>= 10; /* current data */ + p = &vtxt_row[13-4]; /* pointer to next data triplet */ + for (colorindex = 0; colorindex < 16; colorindex++) + { + if (bitsleft < 12) + { + t2 |= deh24(p) << bitsleft; + if (t2 < 0) /* hamming error */ + break; + p += 3; + bitsleft += 18; + } + (*ptExtData)->bgr[colorindex] = t2 & 0x0fff; + bitsleft -= 12; + t2 >>= 12; + } + if (t2 < 0 || bitsleft != 14) + { +#if TUXTXT_DEBUG + printf("TuxTxt \n", t2, bitsleft); +#endif + (*ptExtData)->p28Received = 0; + return; + } + (*ptExtData)->DefScreenColor = t2 & 0x1f; + t2 >>= 5; + (*ptExtData)->DefRowColor = t2 & 0x1f; + (*ptExtData)->BlackBgSubst = !!(t2 & 0x20); + t2 >>= 6; + (*ptExtData)->ColorTableRemapping = t2 & 0x07; +} + +void tuxtxt_erase_page(int magazine) +{ + tstCachedPage* pg = tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]; + if (pg) + { + memset(&(pg->pageinfo), 0, sizeof(tstPageinfo)); /* struct pageinfo */ + memset(pg->p0, ' ', 24); +#if TUXTXT_COMPRESS == 1 + if (pg->pData) { + free(pg->pData); + pg->pData = NULL; + } +#elif TUXTXT_COMPRESS == 2 + memset(pg->bitmask, 0, 23*5); +#else + memset(pg->data, ' ', 23*40); +#endif + } +} + +void tuxtxt_clear_p26(tstExtData* extData) +{ + pthread_mutex_lock(&tuxtxt_cache_lock); + + for(int i = 0; i < 16; ++i) + { + if(0 != extData->p26[i]) + { + memset(extData->p26[i], 0x00, 13 * 3); + } + } + + pthread_mutex_unlock(&tuxtxt_cache_lock); +} + +void tuxtxt_allocate_cache(int magazine) +{ + // Lock here as we have a possible race here with + // tuxtxt_clear_cache(). We should not be allocating and + // freeing at the same time. + // *** this is probably worked around by tuxtxt_cacehe_biglock now *** --seife + pthread_mutex_lock(&tuxtxt_cache_lock); + + /* check cachetable and allocate memory if needed */ + if (tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]] == 0) + { + tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]] = (tstCachedPage*) malloc(sizeof(tstCachedPage)); + if (tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]] ) + { +#if TUXTXT_COMPRESS >0 + tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->pData = 0; +#endif + tuxtxt_erase_page(magazine); + tuxtxt_cache.cached_pages++; + } + else // Be a little verbose in case a crash is going to happen. + { + printf("tuxtxt: memory allocation failed!!! expect a crash\n"); + } + } + pthread_mutex_unlock(&tuxtxt_cache_lock); +} + +/****************************************************************************** + * CacheThread * + ******************************************************************************/ +static int stop_cache = 0; +void *tuxtxt_CacheThread(void * /*arg*/) +{ + const unsigned char rev_lut[32] = { + 0x00,0x08,0x04,0x0c, /* upper nibble */ + 0x02,0x0a,0x06,0x0e, + 0x01,0x09,0x05,0x0d, + 0x03,0x0b,0x07,0x0f, + 0x00,0x80,0x40,0xc0, /* lower nibble */ + 0x20,0xa0,0x60,0xe0, + 0x10,0x90,0x50,0xd0, + 0x30,0xb0,0x70,0xf0 }; + unsigned char pes_packet[184*20]; + unsigned char vtxt_row[42]; + int line, byte/*, bit*/; + int b1, b2, b3, b4; + int packet_number; + int doupdate=0; + unsigned char magazine = 0xff; + unsigned char pagedata[9][23*40]; + tstPageinfo *pageinfo_thread; + + printf("TuxTxt running thread...(%04x)\n",tuxtxt_cache.vtxtpid); + tuxtxt_cache.receiving = 1; + nice(3); + while (!stop_cache) + { + /* check stopsignal */ + pthread_testcancel(); + + if (!tuxtxt_cache.receiving) + continue; + + /* read packet */ + ssize_t readcnt; + + readcnt = dmx->Read(pes_packet, sizeof (pes_packet), 1000); + //if (readcnt != sizeof(pes_packet)) + if ((readcnt <= 0) || (readcnt % 184)) + { +#if TUXTXT_DEBUG + if(readcnt > 0) + printf ("TuxTxt: readerror: %d\n", readcnt); +#endif + continue; + } + + /* this "big hammer lock" is a hack: it avoids a crash if + * tuxtxt_clear_cache() is called while the cache thread is in the + * middle of the following loop, leading to tuxtxt_cache.current_page[] + * etc. being set to -1 and tuxtxt_cache.astCachetable[] etc. being set + * to NULL + * it probably also avoids the possible race in tuxtxt_allocate_cache() */ + pthread_mutex_lock(&tuxtxt_cache_biglock); + /* analyze it */ + for (line = 0; line < readcnt/0x2e /*4*/; line++) + { + unsigned char *vtx_rowbyte = &pes_packet[line*0x2e]; + if ((vtx_rowbyte[1] == 0x2C) && (vtx_rowbyte[0] == 0x02 || vtx_rowbyte[0] == 0x03)) + { + /* clear rowbuffer */ + /* convert row from lsb to msb (begin with magazin number) */ + for (byte = 4; byte < 46; byte++) + { + unsigned char upper,lower; + upper = (vtx_rowbyte[byte] >> 4) & 0xf; + lower = vtx_rowbyte[byte] & 0xf; + vtxt_row[byte-4] = (rev_lut[upper]) | (rev_lut[lower+16]); + } + + /* get packet number */ + b1 = dehamming[vtxt_row[0]]; + b2 = dehamming[vtxt_row[1]]; + + if (b1 == 0xFF || b2 == 0xFF) + { +#if TUXTXT_DEBUG + printf("TuxTxt \n"); +#endif + continue; + } + + b1 &= 8; + + packet_number = b1>>3 | b2<<1; + + /* get magazine number */ + magazine = dehamming[vtxt_row[0]] & 7; + if (!magazine) magazine = 8; + + if (packet_number == 0 && tuxtxt_cache.current_page[magazine] != -1 && tuxtxt_cache.current_subpage[magazine] != -1) + tuxtxt_compress_page(tuxtxt_cache.current_page[magazine],tuxtxt_cache.current_subpage[magazine],pagedata[magazine]); + + //printf("********************** receiving packet %d page %03x subpage %02x\n",packet_number, tuxtxt_cache.current_page[magazine],tuxtxt_cache.current_subpage[magazine]);//FIXME + + /* analyze row */ + if (packet_number == 0) + { + /* get pagenumber */ + b2 = dehamming[vtxt_row[3]]; + b3 = dehamming[vtxt_row[2]]; + + if (b2 == 0xFF || b3 == 0xFF) + { + tuxtxt_cache.current_page[magazine] = tuxtxt_cache.page_receiving = -1; +#if TUXTXT_DEBUG + printf("TuxTxt \n"); +#endif + continue; + } + + tuxtxt_cache.current_page[magazine] = tuxtxt_cache.page_receiving = magazine<<8 | b2<<4 | b3; + + if (b2 == 0x0f && b3 == 0x0f) + { + tuxtxt_cache.current_subpage[magazine] = -1; /* ?ff: ignore data transmissions */ + continue; + } + + /* get subpagenumber */ + b1 = dehamming[vtxt_row[7]]; + b2 = dehamming[vtxt_row[6]]; + b3 = dehamming[vtxt_row[5]]; + b4 = dehamming[vtxt_row[4]]; + + if (b1 == 0xFF || b2 == 0xFF || b3 == 0xFF || b4 == 0xFF) + { +#if TUXTXT_DEBUG + printf("TuxTxt \n"); +#endif + tuxtxt_cache.current_subpage[magazine] = -1; + continue; + } + + b1 &= 3; + b3 &= 7; + + if (tuxtxt_is_dec(tuxtxt_cache.page_receiving)) /* ignore other subpage bits for hex pages */ + { +#if 0 /* ? */ + if (b1 != 0 || b2 != 0) + { +#if TUXTXT_DEBUG + printf("TuxTxt \n", tuxtxt_cache.page_receiving, b1, b2, b3, b4); +#endif + tuxtxt_cache.current_subpage[magazine] = -1; + continue; + } + else +#endif + tuxtxt_cache.current_subpage[magazine] = b3<<4 | b4; + } + else + tuxtxt_cache.current_subpage[magazine] = b4; /* max 16 subpages for hex pages */ + + /* store current subpage for this page */ + tuxtxt_cache.subpagetable[tuxtxt_cache.current_page[magazine]] = tuxtxt_cache.current_subpage[magazine]; + + tuxtxt_allocate_cache(magazine); + tuxtxt_decompress_page(tuxtxt_cache.current_page[magazine],tuxtxt_cache.current_subpage[magazine],pagedata[magazine]); + pageinfo_thread = &(tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->pageinfo); + + if ((tuxtxt_cache.page_receiving & 0xff) == 0xfe) /* ?fe: magazine organization table (MOT) */ + pageinfo_thread->function = FUNC_MOT; + + /* check controlbits */ + if (dehamming[vtxt_row[5]] & 8) /* C4 -> erase page */ + { +#if TUXTXT_COMPRESS == 1 + tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->ziplen = 0; +#elif TUXTXT_COMPRESS == 2 + memset(tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->bitmask, 0, 23*5); +#else + memset(tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->data, ' ', 23*40); +#endif + memset(pagedata[magazine],' ', 23*40); + } + if (dehamming[vtxt_row[9]] & 8) /* C8 -> update page */ + doupdate = tuxtxt_cache.page_receiving; + + pageinfo_thread->boxed = !!(dehamming[vtxt_row[7]] & 0x0c); + + /* get country control bits */ + b1 = dehamming[vtxt_row[9]]; + if (b1 == 0xFF) + { +#if TUXTXT_DEBUG + printf("TuxTxt \n"); +#endif + } + else + { + //pageinfo_thread->nationalvalid = 1;// FIXME without full eval some is broken + pageinfo_thread->national = rev_lut[b1] & 0x07; +//printf("TuxTxt 0: b1=%x\n", rev_lut[b1]); + } + + /* check parity, copy line 0 to cache (start and end 8 bytes are not needed and used otherwise) */ + unsigned char *p = tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->p0; + for (byte = 10; byte < 42-8; byte++) + *p++ = deparity[vtxt_row[byte]]; + + if (!tuxtxt_is_dec(tuxtxt_cache.page_receiving)) + continue; /* valid hex page number: just copy headline, ignore timestring */ + + /* copy timestring */ + p = tuxtxt_cache.timestring; + for (; byte < 42; byte++) + *p++ = deparity[vtxt_row[byte]]; + } /* (packet_number == 0) */ + else if (packet_number == 29 && dehamming[vtxt_row[2]]== 0) /* packet 29/0 replaces 28/0 for a whole magazine */ + { + tuxtxt_decode_p2829(vtxt_row, &(tuxtxt_cache.astP29[magazine])); + } + else if (tuxtxt_cache.current_page[magazine] != -1 && tuxtxt_cache.current_subpage[magazine] != -1) + /* packet>0, 0 has been correctly received, buffer allocated */ + { + pageinfo_thread = &(tuxtxt_cache.astCachetable[tuxtxt_cache.current_page[magazine]][tuxtxt_cache.current_subpage[magazine]]->pageinfo); + /* pointer to current info struct */ + + if (packet_number <= 25) + { + unsigned char *p = NULL; + if (packet_number < 24) + p = pagedata[magazine] + 40*(packet_number-1); + else + { + if (!(pageinfo_thread->p24)) + pageinfo_thread->p24 = (unsigned char*) calloc(2, 40); + if (pageinfo_thread->p24) + p = pageinfo_thread->p24 + (packet_number - 24) * 40; + } + if (p) + { + if (tuxtxt_is_dec(tuxtxt_cache.current_page[magazine])) + for (byte = 2; byte < 42; byte++) + *p++ = deparity[vtxt_row[byte]]; /* check/remove parity bit */ + else if ((tuxtxt_cache.current_page[magazine] & 0xff) == 0xfe) + for (byte = 2; byte < 42; byte++) + *p++ = dehamming[vtxt_row[byte]]; /* decode hamming 8/4 */ + else /* other hex page: no parity check, just copy */ + memmove(p, &vtxt_row[2], 40); + } + } + else if (packet_number == 27) + { + int descode = dehamming[vtxt_row[2]]; /* designation code (0..15) */ + + if (descode == 0xff) + { +#if TUXTXT_DEBUG + printf("TuxTxt \n"); +#endif + continue; + } + if (descode == 0) // reading FLOF-Pagelinks + { + b1 = dehamming[vtxt_row[0]]; + if (b1 != 0xff) + { + b1 &= 7; + + for (byte = 0; byte < FLOFSIZE; byte++) + { + b2 = dehamming[vtxt_row[4+byte*6]]; + b3 = dehamming[vtxt_row[3+byte*6]]; + + if (b2 != 0xff && b3 != 0xff) + { + b4 = ((b1 ^ (dehamming[vtxt_row[8+byte*6]]>>1)) & 6) | + ((b1 ^ (dehamming[vtxt_row[6+byte*6]]>>3)) & 1); + if (b4 == 0) + b4 = 8; + if (b2 <= 9 && b3 <= 9) + tuxtxt_cache.flofpages[tuxtxt_cache.current_page[magazine] ][byte] = b4<<8 | b2<<4 | b3; + } + } + + /* copy last 2 links to adip for TOP-Index */ + if (pageinfo_thread->p24) /* packet 24 received */ + { + int a, a1, e=39, l=3; + char *p = (char*) pageinfo_thread->p24; + do + { + for (; + l >= 2 && 0 == tuxtxt_cache.flofpages[tuxtxt_cache.current_page[magazine]][l]; + l--) + ; /* find used linkindex */ + for (; + e >= 1 && !isalnum(p[e]); + e--) + ; /* find end */ + for (a = a1 = e - 1; + a >= 0 && p[a] >= ' '; + a--) /* find start */ + if (p[a] > ' ') + a1 = a; /* first non-space */ + if (a >= 0 && l >= 2) + { + strncpy((char *) tuxtxt_cache.adip[tuxtxt_cache.flofpages[tuxtxt_cache.current_page[magazine]][l]], + &p[a1], + 12); + if (e-a1 < 11) + tuxtxt_cache.adip[tuxtxt_cache.flofpages[tuxtxt_cache.current_page[magazine]][l]][e-a1+1] = '\0'; +#if 0 //TUXTXT_DEBUG + printf(" %03x/%02x %d %d %d %d %03x %s\n", + tuxtxt_cache.current_page[magazine], tuxtxt_cache.current_subpage[magazine], + l, a, a1, e, + tuxtxt_cache.flofpages[tuxtxt_cache.current_page[magazine]][l], + tuxtxt_cache.adip[tuxtxt_cache.flofpages[tuxtxt_cache.current_page[magazine]][l]] + ); +#endif + } + e = a - 1; + l--; + } while (l >= 2); + } + } + } + else if (descode == 4) /* level 2.5 links (ignore level 3.5 links of /4 and /5) */ + { + int i; + tstp27 *p; + + if (!pageinfo_thread->ext) + pageinfo_thread->ext = (tstExtData*) calloc(1, sizeof(tstExtData)); + if (!pageinfo_thread->ext) + continue; + if (!(pageinfo_thread->ext->p27)) + pageinfo_thread->ext->p27 = (tstp27*) calloc(4, sizeof(tstp27)); + if (!(pageinfo_thread->ext->p27)) + continue; + p = pageinfo_thread->ext->p27; + for (i = 0; i < 4; i++) + { + int d1 = deh24(&vtxt_row[6*i + 3]); + int d2 = deh24(&vtxt_row[6*i + 6]); + if (d1 < 0 || d2 < 0) + { +#if TUXTXT_DEBUG + printf("TuxTxt \n"); +#endif + continue; + } + p->local = i & 0x01; + p->drcs = !!(i & 0x02); + p->l25 = !!(d1 & 0x04); + p->l35 = !!(d1 & 0x08); + p->page = + (((d1 & 0x000003c0) >> 6) | + ((d1 & 0x0003c000) >> (14-4)) | + ((d1 & 0x00003800) >> (11-8))) ^ + (dehamming[vtxt_row[0]] << 8); + if (p->page < 0x100) + p->page += 0x800; + p->subpage = d2 >> 2; + if ((p->page & 0xff) == 0xff) + p->page = 0; + else if (p->page > 0x899) + { + // workaround for crash on RTL + printf("[TuxTxt] page > 0x899 ... ignore!!!!!!\n"); + continue; + } + else if (tuxtxt_cache.astCachetable[p->page][0]) /* link valid && linked page cached */ + { + tstPageinfo *pageinfo_link = &(tuxtxt_cache.astCachetable[p->page][0]->pageinfo); + if (p->local) + pageinfo_link->function = p->drcs ? FUNC_DRCS : FUNC_POP; + else + pageinfo_link->function = p->drcs ? FUNC_GDRCS : FUNC_GPOP; + } + p++; /* */ + } + } + } + + else if (packet_number == 26) + { + int descode = dehamming[vtxt_row[2]]; /* designation code (0..15) */ + + if (descode == 0xff) + { +#if TUXTXT_DEBUG + printf("TuxTxt \n"); +#endif + continue; + } + if (!pageinfo_thread->ext) + pageinfo_thread->ext = (tstExtData*) calloc(1, sizeof(tstExtData)); + if (!pageinfo_thread->ext) + continue; + if (!(pageinfo_thread->ext->p26[descode])) + pageinfo_thread->ext->p26[descode] = (unsigned char*) malloc(13 * 3); + if (pageinfo_thread->ext->p26[descode]) + memmove(pageinfo_thread->ext->p26[descode], &vtxt_row[3], 13 * 3); +#if 0//TUXTXT_DEBUG + int i, t, m; + + printf("P%03x/%02x %02d/%x", + tuxtxt_cache.current_page[magazine], tuxtxt_cache.current_subpage[magazine], + packet_number, dehamming[vtxt_row[2]]); + for (i=7-4; i <= 45-4; i+=3) /* dump all triplets */ + { + t = deh24(&vtxt_row[i]); /* mode/adr/data */ + m = (t>>6) & 0x1f; + printf(" M%02xA%02xD%03x", m, t & 0x3f, (t>>11) & 0x7f); + if (m == 0x1f) /* terminator */ + break; + } + putchar('\n'); +#endif + } + else if (packet_number == 28) + { + int descode = dehamming[vtxt_row[2]]; /* designation code (0..15) */ + + if (descode == 0xff) + { +#if TUXTXT_DEBUG + printf("TuxTxt \n"); +#endif + continue; + } + if (descode != 2) + { + int t1 = deh24(&vtxt_row[7-4]); + pageinfo_thread->function = t1 & 0x0f; + if (!pageinfo_thread->nationalvalid) + { +//printf("TuxTxt 28: t1=%x\n", t1>>4); + // pageinfo_thread->nationalvalid = 1; // FIXME without full eval some is broken + pageinfo_thread->national = (t1>>4) & 0x07; + } + } + + switch (descode) /* designation code */ + { + case 0: /* basic level 1 page */ + { + tuxtxt_decode_p2829(vtxt_row, &(pageinfo_thread->ext)); + break; + } + case 1: /* G0/G1 designation for older decoders, level 3.5: DCLUT4/16, colors for multicolored bitmaps */ + { + break; /* ignore */ + } + case 2: /* page key */ + { + break; /* ignore */ + } + case 3: /* types of PTUs in DRCS */ + { + break; /* TODO */ + } + case 4: /* CLUTs 0/1, only level 3.5 */ + { + break; /* ignore */ + } + default: + { + break; /* invalid, ignore */ + } + } /* switch designation code */ + } + else if (packet_number == 30) + { +#if 0//TUXTXT_DEBUG + int i; + + printf("p%03x/%02x %02d/%x ", + tuxtxt_cache.current_page[magazine], tuxtxt_cache.current_subpage[magazine], + packet_number, dehamming[vtxt_row[2]]); + for (i=26-4; i <= 45-4; i++) /* station ID */ + putchar(deparity[vtxt_row[i]]); + putchar('\n'); +#endif + } + } + /* set update flag */ + if (tuxtxt_cache.current_page[magazine] == tuxtxt_cache.page && tuxtxt_cache.current_subpage[magazine] != -1) + { + tuxtxt_compress_page(tuxtxt_cache.current_page[magazine],tuxtxt_cache.current_subpage[magazine],pagedata[magazine]); + tuxtxt_cache.pageupdate = 1+(doupdate == tuxtxt_cache.page ? 1: 0); + doupdate=0; + if (!tuxtxt_cache.zap_subpage_manual) + tuxtxt_cache.subpage = tuxtxt_cache.current_subpage[magazine]; + } + } +#if 0 + else + printf("line %d row %X %X, continue\n", line, vtx_rowbyte[0], vtx_rowbyte[1]); +#endif + } + pthread_mutex_unlock(&tuxtxt_cache_biglock); + } + + pthread_exit(NULL); +} +/****************************************************************************** + * start_thread * + ******************************************************************************/ +int tuxtxt_start_thread(int source = 0); +int tuxtxt_start_thread(int source) +{ + if (tuxtxt_cache.vtxtpid == -1) + return 0; + + tuxtxt_cache.thread_starting = 1; + tuxtxt_init_demuxer(source); + + dmx->pesFilter(tuxtxt_cache.vtxtpid); + dmx->Start(); + stop_cache = 0; + + /* create decode-thread */ + if (pthread_create(&tuxtxt_cache.thread_id, NULL, tuxtxt_CacheThread, NULL) != 0) + { + perror("TuxTxt "); + tuxtxt_cache.thread_starting = 0; + return 0; + } +#if 1//TUXTXT_DEBUG + printf("TuxTxt service started %x\n", tuxtxt_cache.vtxtpid); +#endif + tuxtxt_cache.receiving = 1; + tuxtxt_cache.thread_starting = 0; + return 1; +} +/****************************************************************************** + * stop_thread * + ******************************************************************************/ + +int tuxtxt_stop_thread() +{ + /* stop decode-thread */ + if (tuxtxt_cache.thread_id != 0) + { +#if 0 + if (pthread_cancel(tuxtxt_cache.thread_id) != 0) + { + perror("TuxTxt "); + return 0; + } +#endif + stop_cache = 1; + if (pthread_join(tuxtxt_cache.thread_id, &tuxtxt_cache.thread_result) != 0) + { + perror("TuxTxt "); + return 0; + } + tuxtxt_cache.thread_id = 0; + } + if(dmx) { + dmx->Stop(); + delete dmx; + dmx = NULL; + } +#if 0 + if (tuxtxt_cache.dmx != -1) + { + //ioctl(tuxtxt_cache.dmx, DMX_STOP); + +// close(tuxtxt_cache.dmx); + } +// tuxtxt_cache.dmx = -1; +#endif +#if 1//TUXTXT_DEBUG + printf("TuxTxt stopped service %x\n", tuxtxt_cache.vtxtpid); +#endif + return 1; +} diff --git a/lib/libtuxtxt_mp/tuxtxt_def.h b/lib/libtuxtxt_mp/tuxtxt_def.h new file mode 100644 index 000000000..255db1f74 --- /dev/null +++ b/lib/libtuxtxt_mp/tuxtxt_def.h @@ -0,0 +1,370 @@ +/****************************************************************************** + * definitions for plugin and lib * + ******************************************************************************/ +#define TUXTXT_COMPRESS 2 // compress page data: 0 no compression, 1 with zlib, 2 with own algorithm + +#include + +#define FLOFSIZE 4 + +#define PAGESIZE (40*25) + + +enum /* page function */ +{ + FUNC_LOP = 0, /* Basic Level 1 Teletext page (LOP) */ + FUNC_DATA, /* Data broadcasting page coded according to EN 300 708 [2] clause 4 */ + FUNC_GPOP, /* Global Object definition page (GPOP) - (see clause 10.5.1) */ + FUNC_POP, /* Normal Object definition page (POP) - (see clause 10.5.1) */ + FUNC_GDRCS, /* Global DRCS downloading page (GDRCS) - (see clause 10.5.2) */ + FUNC_DRCS, /* Normal DRCS downloading page (DRCS) - (see clause 10.5.2) */ + FUNC_MOT, /* Magazine Organization table (MOT) - (see clause 10.6) */ + FUNC_MIP, /* Magazine Inventory page (MIP) - (see clause 11.3) */ + FUNC_BTT, /* Basic TOP table (BTT) } */ + FUNC_AIT, /* Additional Information Table (AIT) } (see clause 11.2) */ + FUNC_MPT, /* Multi-page table (MPT) } */ + FUNC_MPTEX, /* Multi-page extension table (MPT-EX) } */ + FUNC_TRIGGER /* Page contain trigger messages defined according to [8] */ +}; + + +/* struct for (G)POP/(G)DRCS links for level 2.5, allocated at reception of p27/4 or /5, initialized with 0 after allocation */ +typedef struct +{ + short page; /* linked page number */ + unsigned short subpage; /* 1 bit for each needed (1) subpage */ + unsigned char l25:1; /* 1: page required at level 2.5 */ + unsigned char l35:1; /* 1: page required at level 3.5 */ + unsigned char drcs:1; /* 1: link to (G)DRCS, 0: (G)POP */ + unsigned char local:1; /* 1: global (G*), 0: local */ +} tstp27; + +/* struct for extension data for level 2.5, allocated at reception, initialized with 0 after allocation */ +typedef struct +{ + unsigned char *p26[16]; /* array of pointers to max. 16 designation codes of packet 26 */ + tstp27 *p27; /* array of 4 structs for (G)POP/(G)DRCS links for level 2.5 */ + unsigned short bgr[16]; /* CLUT 2+3, 2*8 colors, 0x0bgr */ + unsigned char DefaultCharset:7; /* default G0/G2 charset + national option */ + unsigned char LSP:1; /* 1: left side panel to be displayed */ + unsigned char SecondCharset:7; /* second G0 charset */ + unsigned char RSP:1; /* 1: right side panel to be displayed */ + unsigned char DefScreenColor:5; /* default screen color (above and below lines 0..24) */ + unsigned char ColorTableRemapping:3; /* 1: index in table of CLUTs to use */ + unsigned char DefRowColor:5; /* default row color (left and right to lines 0..24) */ + unsigned char BlackBgSubst:1; /* 1: substitute black background (as result of start-of-line or 1c, not 00/10+1d) */ + unsigned char SPL25:1; /* 1: side panel required at level 2.5 */ + unsigned char p28Received:1; /* 1: extension data valid (p28/0 received) */ + unsigned char LSPColumns:4; /* number of columns in left side panel, 0->16, rsp=16-lsp */ +} tstExtData; + + +/* struct for pageinfo, max. 16 Bytes, at beginning of each cached page buffer, initialized with 0 after allocation */ +typedef struct +{ + unsigned char *p24; /* pointer to lines 25+26 (packets 24+25) (2*40 bytes) for FLOF or level 2.5 data */ + tstExtData *ext; /* pointer to array[16] of data for level 2.5 */ + unsigned char boxed :1; /* p0: boxed (newsflash or subtitle) */ + unsigned char nationalvalid :1; /* p0: national option character subset is valid (no biterror detected) */ + unsigned char national :3; /* p0: national option character subset */ + unsigned char function :3; /* p28/0: page function */ +} tstPageinfo; + +/* one cached page: struct for pageinfo, 24 lines page data */ +typedef struct +{ + tstPageinfo pageinfo; + unsigned char p0[24]; /* packet 0: center of headline */ +#if TUXTXT_COMPRESS == 1 + unsigned char * pData;/* packet 1-23 */ + unsigned short ziplen; +#elif TUXTXT_COMPRESS == 2 + unsigned char * pData;/* packet 1-23 */ + unsigned char bitmask[23*5]; +#else + unsigned char data[23*40]; /* packet 1-23 */ +#endif +} tstCachedPage; + +/* main data structure */ +typedef struct +{ + short flofpages[0x900][FLOFSIZE]; + unsigned char adip[0x900][13]; + unsigned char subpagetable[0x900]; + int dmx; + int vtxtpid; + int cached_pages, page, subpage, pageupdate,page_receiving, current_page[9], current_subpage[9]; + int receiving, thread_starting, zap_subpage_manual; + char bttok; + int adippg[10]; + int maxadippg; + unsigned char basictop[0x900]; + + unsigned char timestring[8]; + /* cachetable for packets 29 (one for each magazine) */ + tstExtData *astP29[9]; + /* cachetable */ + tstCachedPage *astCachetable[0x900][0x80]; + + pthread_t thread_id; + void *thread_result; +} tuxtxt_cache_struct; + +/* hamming table */ +const unsigned char dehamming[] = +{ + 0x01, 0xFF, 0x01, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x02, 0x01, 0xFF, 0x0A, 0xFF, 0xFF, 0x07, + 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x06, 0xFF, 0xFF, 0x0B, 0xFF, 0x00, 0x03, 0xFF, + 0xFF, 0x0C, 0x01, 0xFF, 0x04, 0xFF, 0xFF, 0x07, 0x06, 0xFF, 0xFF, 0x07, 0xFF, 0x07, 0x07, 0x07, + 0x06, 0xFF, 0xFF, 0x05, 0xFF, 0x00, 0x0D, 0xFF, 0x06, 0x06, 0x06, 0xFF, 0x06, 0xFF, 0xFF, 0x07, + 0xFF, 0x02, 0x01, 0xFF, 0x04, 0xFF, 0xFF, 0x09, 0x02, 0x02, 0xFF, 0x02, 0xFF, 0x02, 0x03, 0xFF, + 0x08, 0xFF, 0xFF, 0x05, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x02, 0x03, 0xFF, 0x03, 0xFF, 0x03, 0x03, + 0x04, 0xFF, 0xFF, 0x05, 0x04, 0x04, 0x04, 0xFF, 0xFF, 0x02, 0x0F, 0xFF, 0x04, 0xFF, 0xFF, 0x07, + 0xFF, 0x05, 0x05, 0x05, 0x04, 0xFF, 0xFF, 0x05, 0x06, 0xFF, 0xFF, 0x05, 0xFF, 0x0E, 0x03, 0xFF, + 0xFF, 0x0C, 0x01, 0xFF, 0x0A, 0xFF, 0xFF, 0x09, 0x0A, 0xFF, 0xFF, 0x0B, 0x0A, 0x0A, 0x0A, 0xFF, + 0x08, 0xFF, 0xFF, 0x0B, 0xFF, 0x00, 0x0D, 0xFF, 0xFF, 0x0B, 0x0B, 0x0B, 0x0A, 0xFF, 0xFF, 0x0B, + 0x0C, 0x0C, 0xFF, 0x0C, 0xFF, 0x0C, 0x0D, 0xFF, 0xFF, 0x0C, 0x0F, 0xFF, 0x0A, 0xFF, 0xFF, 0x07, + 0xFF, 0x0C, 0x0D, 0xFF, 0x0D, 0xFF, 0x0D, 0x0D, 0x06, 0xFF, 0xFF, 0x0B, 0xFF, 0x0E, 0x0D, 0xFF, + 0x08, 0xFF, 0xFF, 0x09, 0xFF, 0x09, 0x09, 0x09, 0xFF, 0x02, 0x0F, 0xFF, 0x0A, 0xFF, 0xFF, 0x09, + 0x08, 0x08, 0x08, 0xFF, 0x08, 0xFF, 0xFF, 0x09, 0x08, 0xFF, 0xFF, 0x0B, 0xFF, 0x0E, 0x03, 0xFF, + 0xFF, 0x0C, 0x0F, 0xFF, 0x04, 0xFF, 0xFF, 0x09, 0x0F, 0xFF, 0x0F, 0x0F, 0xFF, 0x0E, 0x0F, 0xFF, + 0x08, 0xFF, 0xFF, 0x05, 0xFF, 0x0E, 0x0D, 0xFF, 0xFF, 0x0E, 0x0F, 0xFF, 0x0E, 0x0E, 0xFF, 0x0E +}; + +/* odd parity table, error=0x20 (space) */ +const unsigned char deparity[] = +{ + ' ' , 0x01, 0x02, ' ' , 0x04, ' ' , ' ' , 0x07, 0x08, ' ' , ' ' , 0x0b, ' ' , 0x0d, 0x0e, ' ' , + 0x10, ' ' , ' ' , 0x13, ' ' , 0x15, 0x16, ' ' , ' ' , 0x19, 0x1a, ' ' , 0x1c, ' ' , ' ' , 0x1f, + 0x20, ' ' , ' ' , 0x23, ' ' , 0x25, 0x26, ' ' , ' ' , 0x29, 0x2a, ' ' , 0x2c, ' ' , ' ' , 0x2f, + ' ' , 0x31, 0x32, ' ' , 0x34, ' ' , ' ' , 0x37, 0x38, ' ' , ' ' , 0x3b, ' ' , 0x3d, 0x3e, ' ' , + 0x40, ' ' , ' ' , 0x43, ' ' , 0x45, 0x46, ' ' , ' ' , 0x49, 0x4a, ' ' , 0x4c, ' ' , ' ' , 0x4f, + ' ' , 0x51, 0x52, ' ' , 0x54, ' ' , ' ' , 0x57, 0x58, ' ' , ' ' , 0x5b, ' ' , 0x5d, 0x5e, ' ' , + ' ' , 0x61, 0x62, ' ' , 0x64, ' ' , ' ' , 0x67, 0x68, ' ' , ' ' , 0x6b, ' ' , 0x6d, 0x6e, ' ' , + 0x70, ' ' , ' ' , 0x73, ' ' , 0x75, 0x76, ' ' , ' ' , 0x79, 0x7a, ' ' , 0x7c, ' ' , ' ' , 0x7f, + 0x00, ' ' , ' ' , 0x03, ' ' , 0x05, 0x06, ' ' , ' ' , 0x09, 0x0a, ' ' , 0x0c, ' ' , ' ' , 0x0f, + ' ' , 0x11, 0x12, ' ' , 0x14, ' ' , ' ' , 0x17, 0x18, ' ' , ' ' , 0x1b, ' ' , 0x1d, 0x1e, ' ' , + ' ' , 0x21, 0x22, ' ' , 0x24, ' ' , ' ' , 0x27, 0x28, ' ' , ' ' , 0x2b, ' ' , 0x2d, 0x2e, ' ' , + 0x30, ' ' , ' ' , 0x33, ' ' , 0x35, 0x36, ' ' , ' ' , 0x39, 0x3a, ' ' , 0x3c, ' ' , ' ' , 0x3f, + ' ' , 0x41, 0x42, ' ' , 0x44, ' ' , ' ' , 0x47, 0x48, ' ' , ' ' , 0x4b, ' ' , 0x4d, 0x4e, ' ' , + 0x50, ' ' , ' ' , 0x53, ' ' , 0x55, 0x56, ' ' , ' ' , 0x59, 0x5a, ' ' , 0x5c, ' ' , ' ' , 0x5f, + 0x60, ' ' , ' ' , 0x63, ' ' , 0x65, 0x66, ' ' , ' ' , 0x69, 0x6a, ' ' , 0x6c, ' ' , ' ' , 0x6f, + ' ' , 0x71, 0x72, ' ' , 0x74, ' ' , ' ' , 0x77, 0x78, ' ' , ' ' , 0x7b, ' ' , 0x7d, 0x7e, ' ' , +}; + +#if 1 /* lookup-table algorithm for decoding Hamming 24/18, credits to: */ +/* + * libzvbi - Error correction functions + * + * Copyright (C) 2001 Michael H. Schimek + * + * Based on code from AleVT 1.5.1 + * Copyright (C) 1998, 1999 Edgar Toernig + * + * 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. + */ +/* + * [AleVT] + * + * This table generates the parity checks for hamm24/18 decoding. + * Bit 0 is for test A, 1 for B, ... + * + * Thanks to R. Gancarz for this fine table *g* + */ +const unsigned char hamm24par[3][256] = { + { + /* Parities of first byte */ + 0, 33, 34, 3, 35, 2, 1, 32, 36, 5, 6, 39, 7, 38, 37, 4, + 37, 4, 7, 38, 6, 39, 36, 5, 1, 32, 35, 2, 34, 3, 0, 33, + 38, 7, 4, 37, 5, 36, 39, 6, 2, 35, 32, 1, 33, 0, 3, 34, + 3, 34, 33, 0, 32, 1, 2, 35, 39, 6, 5, 36, 4, 37, 38, 7, + 39, 6, 5, 36, 4, 37, 38, 7, 3, 34, 33, 0, 32, 1, 2, 35, + 2, 35, 32, 1, 33, 0, 3, 34, 38, 7, 4, 37, 5, 36, 39, 6, + 1, 32, 35, 2, 34, 3, 0, 33, 37, 4, 7, 38, 6, 39, 36, 5, + 36, 5, 6, 39, 7, 38, 37, 4, 0, 33, 34, 3, 35, 2, 1, 32, + 40, 9, 10, 43, 11, 42, 41, 8, 12, 45, 46, 15, 47, 14, 13, 44, + 13, 44, 47, 14, 46, 15, 12, 45, 41, 8, 11, 42, 10, 43, 40, 9, + 14, 47, 44, 13, 45, 12, 15, 46, 42, 11, 8, 41, 9, 40, 43, 10, + 43, 10, 9, 40, 8, 41, 42, 11, 15, 46, 45, 12, 44, 13, 14, 47, + 15, 46, 45, 12, 44, 13, 14, 47, 43, 10, 9, 40, 8, 41, 42, 11, + 42, 11, 8, 41, 9, 40, 43, 10, 14, 47, 44, 13, 45, 12, 15, 46, + 41, 8, 11, 42, 10, 43, 40, 9, 13, 44, 47, 14, 46, 15, 12, 45, + 12, 45, 46, 15, 47, 14, 13, 44, 40, 9, 10, 43, 11, 42, 41, 8 + }, { + /* Parities of second byte */ + 0, 41, 42, 3, 43, 2, 1, 40, 44, 5, 6, 47, 7, 46, 45, 4, + 45, 4, 7, 46, 6, 47, 44, 5, 1, 40, 43, 2, 42, 3, 0, 41, + 46, 7, 4, 45, 5, 44, 47, 6, 2, 43, 40, 1, 41, 0, 3, 42, + 3, 42, 41, 0, 40, 1, 2, 43, 47, 6, 5, 44, 4, 45, 46, 7, + 47, 6, 5, 44, 4, 45, 46, 7, 3, 42, 41, 0, 40, 1, 2, 43, + 2, 43, 40, 1, 41, 0, 3, 42, 46, 7, 4, 45, 5, 44, 47, 6, + 1, 40, 43, 2, 42, 3, 0, 41, 45, 4, 7, 46, 6, 47, 44, 5, + 44, 5, 6, 47, 7, 46, 45, 4, 0, 41, 42, 3, 43, 2, 1, 40, + 48, 25, 26, 51, 27, 50, 49, 24, 28, 53, 54, 31, 55, 30, 29, 52, + 29, 52, 55, 30, 54, 31, 28, 53, 49, 24, 27, 50, 26, 51, 48, 25, + 30, 55, 52, 29, 53, 28, 31, 54, 50, 27, 24, 49, 25, 48, 51, 26, + 51, 26, 25, 48, 24, 49, 50, 27, 31, 54, 53, 28, 52, 29, 30, 55, + 31, 54, 53, 28, 52, 29, 30, 55, 51, 26, 25, 48, 24, 49, 50, 27, + 50, 27, 24, 49, 25, 48, 51, 26, 30, 55, 52, 29, 53, 28, 31, 54, + 49, 24, 27, 50, 26, 51, 48, 25, 29, 52, 55, 30, 54, 31, 28, 53, + 28, 53, 54, 31, 55, 30, 29, 52, 48, 25, 26, 51, 27, 50, 49, 24 + }, { + /* Parities of third byte */ + 63, 14, 13, 60, 12, 61, 62, 15, 11, 58, 57, 8, 56, 9, 10, 59, + 10, 59, 56, 9, 57, 8, 11, 58, 62, 15, 12, 61, 13, 60, 63, 14, + 9, 56, 59, 10, 58, 11, 8, 57, 61, 12, 15, 62, 14, 63, 60, 13, + 60, 13, 14, 63, 15, 62, 61, 12, 8, 57, 58, 11, 59, 10, 9, 56, + 8, 57, 58, 11, 59, 10, 9, 56, 60, 13, 14, 63, 15, 62, 61, 12, + 61, 12, 15, 62, 14, 63, 60, 13, 9, 56, 59, 10, 58, 11, 8, 57, + 62, 15, 12, 61, 13, 60, 63, 14, 10, 59, 56, 9, 57, 8, 11, 58, + 11, 58, 57, 8, 56, 9, 10, 59, 63, 14, 13, 60, 12, 61, 62, 15, + 31, 46, 45, 28, 44, 29, 30, 47, 43, 26, 25, 40, 24, 41, 42, 27, + 42, 27, 24, 41, 25, 40, 43, 26, 30, 47, 44, 29, 45, 28, 31, 46, + 41, 24, 27, 42, 26, 43, 40, 25, 29, 44, 47, 30, 46, 31, 28, 45, + 28, 45, 46, 31, 47, 30, 29, 44, 40, 25, 26, 43, 27, 42, 41, 24, + 40, 25, 26, 43, 27, 42, 41, 24, 28, 45, 46, 31, 47, 30, 29, 44, + 29, 44, 47, 30, 46, 31, 28, 45, 41, 24, 27, 42, 26, 43, 40, 25, + 30, 47, 44, 29, 45, 28, 31, 46, 42, 27, 24, 41, 25, 40, 43, 26, + 43, 26, 25, 40, 24, 41, 42, 27, 31, 46, 45, 28, 44, 29, 30, 47 + } +}; + +/* + * [AleVT] + * + * Table to extract the lower 4 bit from hamm24/18 encoded bytes + */ +const unsigned char hamm24val[256] = { + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, + 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 5, 5, 5, 5, 4, 4, 4, 4, 5, 5, 5, 5, + 6, 6, 6, 6, 7, 7, 7, 7, 6, 6, 6, 6, 7, 7, 7, 7, + 8, 8, 8, 8, 9, 9, 9, 9, 8, 8, 8, 8, 9, 9, 9, 9, + 10, 10, 10, 10, 11, 11, 11, 11, 10, 10, 10, 10, 11, 11, 11, 11, + 12, 12, 12, 12, 13, 13, 13, 13, 12, 12, 12, 12, 13, 13, 13, 13, + 14, 14, 14, 14, 15, 15, 15, 15, 14, 14, 14, 14, 15, 15, 15, 15, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, + 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 5, 5, 5, 5, 4, 4, 4, 4, 5, 5, 5, 5, + 6, 6, 6, 6, 7, 7, 7, 7, 6, 6, 6, 6, 7, 7, 7, 7, + 8, 8, 8, 8, 9, 9, 9, 9, 8, 8, 8, 8, 9, 9, 9, 9, + 10, 10, 10, 10, 11, 11, 11, 11, 10, 10, 10, 10, 11, 11, 11, 11, + 12, 12, 12, 12, 13, 13, 13, 13, 12, 12, 12, 12, 13, 13, 13, 13, + 14, 14, 14, 14, 15, 15, 15, 15, 14, 14, 14, 14, 15, 15, 15, 15 +}; + +const signed char hamm24err[64] = { + 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, +}; + +/* + * [AleVT] + * + * Mapping from parity checks made by table hamm24par to faulty bit + * in the decoded 18 bit word. + */ +const unsigned int hamm24cor[64] = { + 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, + 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, + 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, + 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, + 0x00000, 0x00000, 0x00000, 0x00001, 0x00000, 0x00002, 0x00004, 0x00008, + 0x00000, 0x00010, 0x00020, 0x00040, 0x00080, 0x00100, 0x00200, 0x00400, + 0x00000, 0x00800, 0x01000, 0x02000, 0x04000, 0x08000, 0x10000, 0x20000, + 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, +}; + +/** + * @internal + * @param p Pointer to a byte triplet, bytes in transmission order, + * lsb first transmitted. + * + * This function decodes a Hamming 24/18 protected byte triplet + * as specified in ETS 300 706 8.3. + * + * @return + * Triplet data bits D18 [msb] ... D1 [lsb] or a negative + * value if the triplet contained incorrectable errors. + */ +static signed int deh24(unsigned char *p) +{ + int e = hamm24par[0][p[0]] + ^ hamm24par[1][p[1]] + ^ hamm24par[2][p[2]]; + + int x = hamm24val[p[0]] + + (p[1] & 127) * 16 + + (p[2] & 127) * 2048; + + return (x ^ hamm24cor[e]) | hamm24err[e]; +} + +#else /* my (rm) slower but smaller solution without lookup tables */ + +/* calc parity */ +int parity(int c) +{ + int n = 0; + for (; c; c &= (c-1)) /* reset least significant set bit */ + n ^= 1; + return n; +} + +#if 0 /* just for testing */ +/* encode hamming 24/18 */ +unsigned int ham24(unsigned int val) +{ + val = ((val & 0x000001) << 2) | + ((val & 0x00000e) << 3) | + ((val & 0x0007f0) << 4) | + ((val & 0x03f800) << 5); + val |= parity(val & 0x555554); + val |= parity(val & 0x666664) << 1; + val |= parity(val & 0x787870) << 3; + val |= parity(val & 0x007f00) << 7; + val |= parity(val & 0x7f0000) << 15; + val |= parity(val) << 23; + return val; +} +#endif + +/* decode hamming 24/18, error=-1 */ +signed int deh24(unsigned char *ph24) +{ + int h24 = *ph24 | (*(ph24+1)<<8) | (*(ph24+2)<<16); + int a = parity(h24 & 0x555555); + int f = parity(h24 & 0xaaaaaa) ^ a; + a |= (parity(h24 & 0x666666) << 1) | + (parity(h24 & 0x787878) << 2) | + (parity(h24 & 0x007f80) << 3) | + (parity(h24 & 0x7f8000) << 4); + if (a != 0x1f) + { + if (f) /* 2 biterrors */ + return -1; + else /* correct 1 biterror */ + h24 ^= (1 << ((a ^ 0x1f)-1)); + } + return + ((h24 & 0x000004) >> 2) | + ((h24 & 0x000070) >> 3) | + ((h24 & 0x007f00) >> 4) | + ((h24 & 0x7f0000) >> 5); +} +#endif /* table or serial */ diff --git a/src/Makefile.am b/src/Makefile.am index 6fa3ba682..054699350 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -108,7 +108,6 @@ neutrino_LDADD = \ $(top_builddir)/lib/jsoncpp/libjsoncpp.a \ $(top_builddir)/lib/libnet/libtuxbox-net.a \ $(top_builddir)/lib/libmd5sum/libtuxbox-md5sum.a \ - $(top_builddir)/lib/libtuxtxt/libtuxtxt.a \ $(top_builddir)/lib/libdvbsub/libdvbsub.a \ $(top_builddir)/lib/libiw/libiw.a \ @CURL_LIBS@ \ @@ -143,8 +142,15 @@ endif if BOXTYPE_COOL neutrino_LDADD += \ + $(top_builddir)/lib/libtuxtxt/libtuxtxt.a +else +neutrino_LDADD += \ + $(top_builddir)/lib/libtuxtxt_mp/libtuxtxt.a +endif + +if BOXTYPE_COOL +neutrino_LDADD += -lcoolstream-mt -lca-sc \ $(top_builddir)/lib/libcoolstream/libhwcaps.a -neutrino_LDADD += -lcoolstream-mt -lca-sc if ENABLE_TMSDK else if BOXMODEL_APOLLO