From c80a53ff6ea22aa14d1f9772b310b77ea0da7c42 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 16 May 2004 18:00:00 +0200 Subject: =?UTF-8?q?Version=201.3.7=20-=20Fixed=20a=20memory=20leak=20in=20?= =?UTF-8?q?thread=20handling=20when=20using=20NPTL=20(thanks=20to=20Jon=20?= =?UTF-8?q?Burgess).=20-=20Fixed=20handling=20Setup.RecordDolbyDigital,=20?= =?UTF-8?q?which=20was=20broken=20since=20version=201.1.6.=20-=20Fixed=20h?= =?UTF-8?q?andling=20text=20lengths=20for=20itemized=20EPG=20texts=20(than?= =?UTF-8?q?ks=20to=20Marcel=20Wiesweg).=20-=20Fixed=20the=20help=20for=20L?= =?UTF-8?q?STE=20and=20LSTR=20(was=20broken=20in=201.3.6).=20-=20Improved?= =?UTF-8?q?=20iso8859-7=20fonts=20(thanks=20to=20Dimitrios=20Dimitrakos).?= =?UTF-8?q?=20-=20Added=20some=203-letter=20language=20codes=20(thanks=20t?= =?UTF-8?q?o=20Marcus=20M=C3=B6nnig).=20-=20Added=20language=20code=20hand?= =?UTF-8?q?ling=20to=20the=20subtitling=20descriptor=20in=20'libsi'=20(tha?= =?UTF-8?q?nks=20to=20=20=20Pekka=20Virtanen).=20-=20Moved=20several=20men?= =?UTF-8?q?u=20item=20classes=20from=20menu.c=20to=20menuitems.[hc]=20to?= =?UTF-8?q?=20make=20them=20=20=20available=20for=20plugins.=20-=20The=20e?= =?UTF-8?q?pg2html.pl=20script=20now=20handles=20'|'=20in=20description=20?= =?UTF-8?q?texts.=20-=20The=20new=20setup=20option=20"OSD/Use=20small=20fo?= =?UTF-8?q?nt"=20can=20be=20used=20to=20control=20the=20use=20of=20=20=20t?= =?UTF-8?q?he=20small=20font=20(see=20MANUAL=20for=20details).=20-=20Swapp?= =?UTF-8?q?ed=20osd.[hc]=20and=20osdbase.[hc]=20to=20have=20the=20virtual?= =?UTF-8?q?=20OSD=20base=20class=20named=20cOsd.=20=20=20Plugins=20may=20n?= =?UTF-8?q?eed=20to=20adjust=20their=20#include=20statements.=20-=20Colors?= =?UTF-8?q?=20are=20now=20given=20as=20AARRGGBB=20instead=20of=20AABBGGRR.?= =?UTF-8?q?=20The=20values=20are=20mapped=20to=20=20=20the=20driver's=20(w?= =?UTF-8?q?rong)=20sequence=20in=20dvbosd.c=20(this=20should=20really=20be?= =?UTF-8?q?=20fixed=20in=20the=20=20=20driver,=20together=20with=20the=20e?= =?UTF-8?q?ndian=20problem).=20-=20The=20new=20OSD=20setup=20parameters=20?= =?UTF-8?q?"Left"=20and=20"Top"=20can=20be=20used=20to=20define=20the=20to?= =?UTF-8?q?p=20left=20=20=20corner=20of=20the=20OSD.=20-=20The=20OSD=20siz?= =?UTF-8?q?e=20parameters=20are=20now=20in=20pixel=20(as=20opposed=20to=20?= =?UTF-8?q?formerly=20characters).=20=20=20When=20reading=20a=20'setup.con?= =?UTF-8?q?f'=20file=20from=20an=20older=20version=20of=20VDR,=20the=20OSD?= =?UTF-8?q?width=20=20=20and=20OSDheight=20values=20will=20be=20converted?= =?UTF-8?q?=20to=20pixel=20automatically.=20-=20The=20OSD=20is=20now=20ful?= =?UTF-8?q?ly=20device=20independent.=20See=20the=20comments=20in=20VDR/os?= =?UTF-8?q?d.h=20and=20the=20=20=20description=20in=20PLUGINS.html=20for?= =?UTF-8?q?=20information=20on=20how=20a=20plugin=20can=20implement=20an?= =?UTF-8?q?=20OSD=20=20=20display=20on=20arbitrary=20hardware.=20-=20The?= =?UTF-8?q?=20OSD=20(actually=20its=20cBitmap=20class)=20can=20now=20handl?= =?UTF-8?q?e=20XPM=20files.=20There=20are=20several=20=20=20XPM=20files=20?= =?UTF-8?q?in=20the=20VDR/symbols=20directory=20which=20can=20be=20used=20?= =?UTF-8?q?by=20skins=20(some=20of=20these=20=20=20have=20been=20taken=20f?= =?UTF-8?q?rom=20the=20"elchi"=20patch).=20See=20VDR/skinsttng.c=20for=20e?= =?UTF-8?q?xamples=20on=20how=20=20=20to=20use=20these.=20-=20Due=20to=20t?= =?UTF-8?q?he=20changes=20in=20the=20OSD=20handling=20the=20DEBUG=5FOSD=20?= =?UTF-8?q?option=20for=20a=20textual=20OSD=20=20=20has=20been=20dropped.?= =?UTF-8?q?=20There=20will=20be=20a=20plugin=20that=20implements=20a=20ski?= =?UTF-8?q?n=20with=20this=20=20=20functionality=20later.=20-=20The=20enti?= =?UTF-8?q?re=20OSD=20display=20can=20now=20be=20implemented=20via=20"skin?= =?UTF-8?q?s".=20See=20VDR/skins.[hc],=20=20=20VDR/skinclassic.[hc],=20VDR?= =?UTF-8?q?/skinsttng.[hc]=20and=20PLUGINS.html=20for=20information=20on?= =?UTF-8?q?=20how=20=20=20a=20plugin=20can=20implement=20its=20own=20skin.?= =?UTF-8?q?=20By=20default=20VDR=20comes=20with=20a=20"Classic"=20skin=20?= =?UTF-8?q?=20=20that=20implements=20the=20OSD=20display=20known=20from=20?= =?UTF-8?q?previous=20versions,=20and=20the=20new=20skin=20=20=20named=20"?= =?UTF-8?q?ST:TNG=20Panels",=20which=20is=20also=20the=20default=20skin=20?= =?UTF-8?q?now.=20The=20actual=20skin=20can=20=20=20be=20selected=20throug?= =?UTF-8?q?h=20"Setup/OSD/Skin".=20-=20The=20colors=20used=20in=20a=20skin?= =?UTF-8?q?=20can=20now=20be=20configured=20using=20"themes".=20See=20PLUG?= =?UTF-8?q?INS.html=20=20=20for=20information=20on=20how=20a=20skin=20can?= =?UTF-8?q?=20make=20use=20of=20themes,=20and=20man=20vdr(5)=20for=20the?= =?UTF-8?q?=20=20=20structure=20of=20a=20theme=20file.=20The=20actual=20th?= =?UTF-8?q?eme=20to=20use=20can=20be=20selected=20through=20=20=20"Setup/O?= =?UTF-8?q?SD/Theme".=20-=20Added=20Croatian=20language=20texts=20(thanks?= =?UTF-8?q?=20to=20Drazen=20Dupor).=20=20=20NOTE:=20there=20is=20apparentl?= =?UTF-8?q?y=20a=20problem=20with=20the=20newly=20introduced=20iso8859-2?= =?UTF-8?q?=20font,=20=20=20because=20as=20soon=20as=20Setup/OSD/Language?= =?UTF-8?q?=20is=20set=20to=20Croatian=20(currently=20the=20last=20one=20?= =?UTF-8?q?=20=20in=20the=20list)=20everything=20freezes=20and=20the=20vdr?= =?UTF-8?q?=20processes=20have=20to=20be=20killed=20with=20-9=20=20=20and?= =?UTF-8?q?=20the=20driver=20needs=20to=20be=20reloaded.=20Maybe=20somebod?= =?UTF-8?q?y=20else=20can=20find=20out=20what's=20=20=20going=20wrong=20he?= =?UTF-8?q?re...=20-=20Added=20missing=20NULL=20checks=20when=20accessing?= =?UTF-8?q?=20sectionHandler=20in=20device.c=20(thanks=20to=20=20=20Pekka?= =?UTF-8?q?=20Virtanen).=20-=20Fixed=20setting=20the=20time=20from=20the?= =?UTF-8?q?=20DVB=20data=20stream=20(thanks=20to=20Helmut=20Auer=20for=20?= =?UTF-8?q?=20=20pointing=20out=20a=20frequency/transponder=20handling=20m?= =?UTF-8?q?ixup).=20This=20now=20also=20takes=20the=20=20=20actual=20sourc?= =?UTF-8?q?e=20(sat,=20cable=20etc.)=20into=20account.=20Please=20go=20int?= =?UTF-8?q?o=20"Setup/EPG"=20and=20=20=20set=20the=20"Set=20system=20time"?= =?UTF-8?q?=20and=20"Use=20time=20from=20transponder"=20parameters=20accor?= =?UTF-8?q?dingly=20=20=20(this=20is=20necessary=20even=20if=20you=20have?= =?UTF-8?q?=20already=20set=20them=20before!).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- osdbase.c | 667 +++++++++++++++++++++++++++----------------------------------- 1 file changed, 291 insertions(+), 376 deletions(-) (limited to 'osdbase.c') diff --git a/osdbase.c b/osdbase.c index 7179406..08aef96 100644 --- a/osdbase.c +++ b/osdbase.c @@ -4,495 +4,410 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: osdbase.c 1.12 2004/01/31 10:31:13 kls Exp $ + * $Id: osdbase.c 1.13 2004/05/01 10:51:43 kls Exp $ */ #include "osdbase.h" -#include -#include -#include -#include -#include -#include "tools.h" +#include +#include "device.h" +#include "i18n.h" +#include "remote.h" +#include "status.h" -// --- cPalette -------------------------------------------------------------- +// --- cOsdItem -------------------------------------------------------------- -cPalette::cPalette(int Bpp) +cOsdItem::cOsdItem(eOSState State) { - maxColors = 1 << Bpp; - numColors = 0; - full = false; + text = NULL; + offset = -1; + state = State; + selectable = true; + fresh = true; } -void cPalette::SetColor(int Index, eDvbColor Color) +cOsdItem::cOsdItem(const char *Text, eOSState State) { - if (Index < maxColors) { - if (numColors < Index) - numColors = Index + 1; - used[Index] = true; - color[Index] = Color; - fetched[Index] = false; - } + text = NULL; + offset = -1; + state = State; + selectable = true; + fresh = true; + SetText(Text); } -int cPalette::Index(eDvbColor Color) +cOsdItem::~cOsdItem() { -#if __BYTE_ORDER == __BIG_ENDIAN - Color = eDvbColor(((Color & 0xFF) << 24) | ((Color & 0xFF00) << 8) | ((Color & 0xFF0000) >> 8) | ((Color & 0xFF000000) >> 24)); -#endif - for (int i = 0; i < numColors; i++) { - if (color[i] == Color) { - used[i] = true; - return i; - } - } - if (!full) { - if (numColors < maxColors) { - color[numColors++] = Color; - used[numColors - 1] = true; - fetched[numColors - 1] = false; - return numColors - 1; - } - for (int i = maxColors; --i >= 0; ) { - if (!used[i]) { - color[i] = Color; - used[i] = true; - fetched[i] = false; - return i; - } - } - esyslog("ERROR: too many different colors used in palette"); - full = true; - } - return 0; + free(text); } -void cPalette::Reset(void) +void cOsdItem::SetText(const char *Text, bool Copy) { - for (int i = 0; i < numColors; i++) - used[i] = fetched[i] = false; - full = false; + free(text); + text = Copy ? strdup(Text) : (char *)Text; // text assumes ownership! } -const eDvbColor *cPalette::NewColors(int &FirstColor, int &LastColor) +void cOsdItem::SetSelectable(bool Selectable) { - for (FirstColor = 0; FirstColor < numColors; FirstColor++) { - if (!fetched[FirstColor]) { - for (LastColor = FirstColor; LastColor < numColors && !fetched[LastColor]; LastColor++) - fetched[LastColor] = true; - LastColor--; // the loop ended one past the last one! - return &color[FirstColor]; - } - } - return NULL; + selectable = Selectable; } -const eDvbColor *cPalette::AllColors(int &NumColors) +void cOsdItem::SetFresh(bool Fresh) { - NumColors = numColors; - return numColors ? color : NULL; + fresh = Fresh; } -void cPalette::Take(const cPalette &Palette, tIndexes *Indexes) +eOSState cOsdItem::ProcessKey(eKeys Key) { - for (int i = 0; i < Palette.numColors; i++) { - if (Palette.used[i]) { - int n = Index(Palette.color[i]); - if (Indexes) - (*Indexes)[i] = n; - } - } + return Key == kOk ? state : osUnknown; } -// --- cBitmap --------------------------------------------------------------- +// --- cOsdMenu -------------------------------------------------------------- -cBitmap::cBitmap(int Width, int Height, int Bpp, bool ClearWithBackground) -:cPalette(Bpp) -{ - width = Width; - height = Height; - clearWithBackground = ClearWithBackground; - bitmap = NULL; - fontType = fontOsd; - font = NULL; - if (width > 0 && height > 0) { - bitmap = MALLOC(u_char, width * height); - if (bitmap) { - Clean(); - memset(bitmap, 0x00, width * height); - SetFont(fontOsd); - } - else - esyslog("ERROR: can't allocate bitmap!"); - } - else - esyslog("ERROR: illegal bitmap parameters (%d, %d)!", width, height); -} +cSkinDisplayMenu *cOsdMenu::displayMenu = NULL; +int cOsdMenu::displayMenuCount = 0; +int cOsdMenu::displayMenuItems = 0;//XXX dynamic??? -cBitmap::~cBitmap() +cOsdMenu::cOsdMenu(const char *Title, int c0, int c1, int c2, int c3, int c4) { - free(bitmap); -} - -eDvbFont cBitmap::SetFont(eDvbFont Font) -{ - eDvbFont oldFont = fontType; - if (fontType != Font || !font) { - font = cFont::GetFont(Font); - fontType = Font; + isMenu = true; + digit = 0; + hasHotkeys = false; + title = NULL; + SetTitle(Title); + cols[0] = c0; + cols[1] = c1; + cols[2] = c2; + cols[3] = c3; + cols[4] = c4; + first = 0; + current = marked = -1; + subMenu = NULL; + helpRed = helpGreen = helpYellow = helpBlue = NULL; + status = NULL; + if (!displayMenuCount++) { + displayMenu = Skins.Current()->DisplayMenu(); + displayMenuItems = displayMenu->MaxItems(); } - return oldFont; } -bool cBitmap::Dirty(int &x1, int &y1, int &x2, int &y2) +cOsdMenu::~cOsdMenu() { - if (dirtyX2 >= 0) { - //XXX Workaround: apparently the bitmap sent to the driver always has to be a multiple - //XXX of 8 bits wide, and (dx * dy) also has to be a multiple of 8. - //TODO Fix driver (should be able to handle any size bitmaps!) - while ((dirtyX1 > 0 || dirtyX2 < width - 1) && ((dirtyX2 - dirtyX1) & 7) != 7) { - if (dirtyX2 < width - 1) - dirtyX2++; - else if (dirtyX1 > 0) - dirtyX1--; - } - //XXX "... / 2" <==> Bpp??? - while ((dirtyY1 > 0 || dirtyY2 < height - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) { - if (dirtyY2 < height - 1) - dirtyY2++; - else if (dirtyY1 > 0) - dirtyY1--; - } - while ((dirtyX1 > 0 || dirtyX2 < width - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) { - if (dirtyX2 < width - 1) - dirtyX2++; - else if (dirtyX1 > 0) - dirtyX1--; - } - x1 = dirtyX1; - y1 = dirtyY1; - x2 = dirtyX2; - y2 = dirtyY2; - return true; - } - return false; -} - -void cBitmap::Clean(void) -{ - dirtyX1 = width; - dirtyY1 = height; - dirtyX2 = -1; - dirtyY2 = -1; + free(title); + delete subMenu; + free(status); + displayMenu->Clear(); + cStatus::MsgOsdClear(); + if (!--displayMenuCount) + DELETENULL(displayMenu); } -void cBitmap::SetIndex(int x, int y, u_char Index) +const char *cOsdMenu::hk(const char *s) { - if (bitmap) { - if (0 <= x && x < width && 0 <= y && y < height) { - if (bitmap[width * y + x] != Index) { - bitmap[width * y + x] = Index; - if (dirtyX1 > x) dirtyX1 = x; - if (dirtyY1 > y) dirtyY1 = y; - if (dirtyX2 < x) dirtyX2 = x; - if (dirtyY2 < y) dirtyY2 = y; - } + static char buffer[64]; + if (s && hasHotkeys) { + if (digit == 0 && '1' <= *s && *s <= '9' && *(s + 1) == ' ') + digit = -1; // prevents automatic hotkeys - input already has them + if (digit >= 0) { + digit++; + snprintf(buffer, sizeof(buffer), " %c %s", (digit < 10) ? '0' + digit : ' ' , s); + s = buffer; } } + return s; } -void cBitmap::SetPixel(int x, int y, eDvbColor Color) +void cOsdMenu::SetHasHotkeys(void) { - SetIndex(x, y, Index(Color)); + hasHotkeys = true; + digit = 0; } -void cBitmap::SetBitmap(int x, int y, const cBitmap &Bitmap) +void cOsdMenu::SetStatus(const char *s) { - if (bitmap && Bitmap.bitmap) { - tIndexes Indexes; - Take(Bitmap, &Indexes); - for (int ix = 0; ix < Bitmap.width; ix++) { - for (int iy = 0; iy < Bitmap.height; iy++) - SetIndex(x + ix, y + iy, Indexes[int(Bitmap.bitmap[Bitmap.width * iy + ix])]); - } - } + free(status); + status = s ? strdup(s) : NULL; + displayMenu->SetMessage(mtStatus, s); } -int cBitmap::Width(unsigned char c) +void cOsdMenu::SetTitle(const char *Title) { - return font ? font->Width(c) : -1; + free(title); + title = strdup(Title); } -int cBitmap::Width(const char *s) +void cOsdMenu::SetHelp(const char *Red, const char *Green, const char *Yellow, const char *Blue) { - return font ? font->Width(s) : -1; + // strings are NOT copied - must be constants!!! + helpRed = Red; + helpGreen = Green; + helpYellow = Yellow; + helpBlue = Blue; + displayMenu->SetButtons(helpRed, helpGreen, helpYellow, helpBlue); + cStatus::MsgOsdHelpKeys(helpRed, helpGreen, helpYellow, helpBlue); } -void cBitmap::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg) +void cOsdMenu::Del(int Index) { - if (bitmap) { - u_char fg = Index(ColorFg); - u_char bg = Index(ColorBg); - int h = font->Height(s); - while (s && *s) { - const cFont::tCharData *CharData = font->CharData(*s++); - if (int(x + CharData->width) > width) - break; - for (int row = 0; row < h; row++) { - cFont::tPixelData PixelData = CharData->lines[row]; - for (int col = CharData->width; col-- > 0; ) { - SetIndex(x + col, y + row, (PixelData & 1) ? fg : bg); - PixelData >>= 1; - } - } - x += CharData->width; - } - } + cList::Del(Get(Index)); + if (current == Count()) + current--; + if (Index == first && first > 0) + first--; } -void cBitmap::Fill(int x1, int y1, int x2, int y2, eDvbColor Color) -{ - if (bitmap) { - u_char c = Index(Color); - for (int y = y1; y <= y2; y++) - for (int x = x1; x <= x2; x++) - SetIndex(x, y, c); - } -} - -void cBitmap::Clear(void) -{ - Reset(); - if (clearWithBackground) - Fill(0, 0, width - 1, height - 1, clrBackground); -} - -const u_char *cBitmap::Data(int x, int y) -{ - return &bitmap[y * width + x]; -} - -// --- cWindow --------------------------------------------------------------- - -cWindow::cWindow(int Handle, int x, int y, int w, int h, int Bpp, bool ClearWithBackground, bool Tiled) -:cBitmap(w, h, Bpp, ClearWithBackground) +void cOsdMenu::Add(cOsdItem *Item, bool Current, cOsdItem *After) { - handle = Handle; - x0 = x; - y0 = y; - bpp = Bpp; - tiled = Tiled; - shown = false; + cList::Add(Item, After); + if (Current) + current = Item->Index(); } -bool cWindow::Contains(int x, int y) +void cOsdMenu::Ins(cOsdItem *Item, bool Current, cOsdItem *Before) { - x -= x0; - y -= y0; - return x >= 0 && y >= 0 && x < width && y < height; + cList::Ins(Item, Before); + if (Current) + current = Item->Index(); } -void cWindow::Relocate(int x, int y) +void cOsdMenu::Display(void) { - x0 = x; - y0 = y; + if (subMenu) { + subMenu->Display(); + return; + } + displayMenu->Clear(); + cStatus::MsgOsdClear(); + displayMenu->SetTabs(cols[0], cols[1], cols[2], cols[3], cols[4]);//XXX + displayMenu->SetTitle(title); + cStatus::MsgOsdTitle(title); + displayMenu->SetButtons(helpRed, helpGreen, helpYellow, helpBlue); + cStatus::MsgOsdHelpKeys(helpRed, helpGreen, helpYellow, helpBlue); + int count = Count(); + if (count > 0) { + int ni = 0; + for (cOsdItem *item = First(); item; item = Next(item)) + cStatus::MsgOsdItem(item->Text(), ni++); + if (current < 0) + current = 0; // just for safety - there HAS to be a current item! + if (current - first >= displayMenuItems || current < first) { + first = current - displayMenuItems / 2; + if (first + displayMenuItems > count) + first = count - displayMenuItems; + if (first < 0) + first = 0; + } + int i = first; + int n = 0; + for (cOsdItem *item = Get(first); item; item = Next(item)) { + displayMenu->SetItem(item->Text(), i - first, i == current, item->Selectable()); + if (i == current) + cStatus::MsgOsdCurrentItem(item->Text()); + if (++n == displayMenuItems) + break; + i++; + } + } + if (!isempty(status)) + displayMenu->SetMessage(mtStatus, status); } -void cWindow::Fill(int x1, int y1, int x2, int y2, eDvbColor Color) +void cOsdMenu::SetCurrent(cOsdItem *Item) { - if (tiled) { - x1 -= x0; - y1 -= y0; - x2 -= x0; - y2 -= y0; - } - cBitmap::Fill(x1, y1, x2, y2, Color); + current = Item ? Item->Index() : -1; } -void cWindow::SetBitmap(int x, int y, const cBitmap &Bitmap) +void cOsdMenu::RefreshCurrent(void) { - if (tiled) { - x -= x0; - y -= y0; - } - cBitmap::SetBitmap(x, y, Bitmap); + cOsdItem *item = Get(current); + if (item) + item->Set(); } -void cWindow::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg) +void cOsdMenu::DisplayCurrent(bool Current) { - if (tiled) { - x -= x0; - y -= y0; + cOsdItem *item = Get(current); + if (item) { + displayMenu->SetItem(item->Text(), current - first, Current, item->Selectable()); + if (Current) + cStatus::MsgOsdCurrentItem(item->Text()); + if (!Current) + item->SetFresh(true); // leaving the current item resets 'fresh' } - cBitmap::Text(x, y, s, ColorFg, ColorBg); } -const u_char *cWindow::Data(int x, int y) +void cOsdMenu::Clear(void) { - return cBitmap::Data(x, y); + first = 0; + current = marked = -1; + cList::Clear(); } -// --- cOsdBase -------------------------------------------------------------- - -cOsdBase::cOsdBase(int x, int y) +bool cOsdMenu::SelectableItem(int idx) { - numWindows = 0; - x0 = x; - y0 = y; + cOsdItem *item = Get(idx); + return item && item->Selectable(); } -cOsdBase::~cOsdBase() +void cOsdMenu::CursorUp(void) { - for (int i = 0; i < numWindows; i++) - delete window[i]; + if (current > 0) { + int tmpCurrent = current; + while (--tmpCurrent >= 0 && !SelectableItem(tmpCurrent)); + if (tmpCurrent < 0) + return; + if (tmpCurrent >= first) + DisplayCurrent(false); + current = tmpCurrent; + if (current < first) { + first = first > displayMenuItems - 1 ? first - (displayMenuItems - 1) : 0; + if (Setup.MenuScrollPage) + current = !SelectableItem(first) ? first + 1 : first; + Display(); + } + else + DisplayCurrent(true); + } } -tWindowHandle cOsdBase::Create(int x, int y, int w, int h, int Bpp, bool ClearWithBackground, bool Tiled) -{ - if (numWindows < MAXNUMWINDOWS) { - if (x >= 0 && y >= 0 && w > 0 && h > 0 && (Bpp == 1 || Bpp == 2 || Bpp == 4 || Bpp == 8)) { - if ((w & 0x03) != 0) { - w += 4 - (w & 0x03); - dsyslog("OSD window width must be a multiple of 4 - increasing to %d", w); +void cOsdMenu::CursorDown(void) +{ + int last = Count() - 1; + int lastOnScreen = first + displayMenuItems - 1; + + if (current < last) { + int tmpCurrent = current; + while (++tmpCurrent <= last && !SelectableItem(tmpCurrent)); + if (tmpCurrent > last) + return; + if (tmpCurrent <= lastOnScreen) + DisplayCurrent(false); + current = tmpCurrent; + if (current > lastOnScreen) { + first += displayMenuItems - 1; + lastOnScreen = first + displayMenuItems - 1; + if (lastOnScreen > last) { + first = last - (displayMenuItems - 1); + lastOnScreen = last; } - cWindow *win = new cWindow(numWindows, x, y, w, h, Bpp, ClearWithBackground, Tiled); - if (OpenWindow(win)) { - window[win->Handle()] = win; - numWindows++; - return win->Handle(); - } - else - delete win; + if (Setup.MenuScrollPage) + current = !SelectableItem(lastOnScreen) ? lastOnScreen - 1 : lastOnScreen; + Display(); } else - esyslog("ERROR: illegal OSD parameters"); + DisplayCurrent(true); } - else - esyslog("ERROR: too many OSD windows"); - return -1; } -void cOsdBase::AddColor(eDvbColor Color, tWindowHandle Window) +void cOsdMenu::PageUp(void) { - cWindow *w = GetWindow(Window); - if (w) { - w->Index(Color); - w->Reset(); + current -= displayMenuItems; + first -= displayMenuItems; + if (first < 0) + first = current = 0; + if (!SelectableItem(current)) { + current -= (current > 0) ? 1 : -1; + first = min(first, current - 1); } + Display(); + DisplayCurrent(true); } -cWindow *cOsdBase::GetWindow(int x, int y) -{ - for (int i = 0; i < numWindows; i++) { - if (window[i]->Tiled() && window[i]->Contains(x, y)) - return window[i]; - } - return NULL; -} - -cWindow *cOsdBase::GetWindow(tWindowHandle Window) -{ - if (0 <= Window && Window < numWindows) - return window[Window]; - if (Window == LAST_CREATED_WINDOW && numWindows > 0) - return window[numWindows - 1]; - return NULL; -} - -void cOsdBase::Flush(void) -{ - for (int i = 0; i < numWindows; i++) { - CommitWindow(window[i]); - window[i]->Clean(); - } - // Showing the windows in a separate loop to avoid seeing them come up one after another - for (int i = 0; i < numWindows; i++) { - if (!window[i]->Shown()) - ShowWindow(window[i]); - } -} - -void cOsdBase::Clear(tWindowHandle Window) +void cOsdMenu::PageDown(void) { - if (Window == ALL_TILED_WINDOWS || Window == ALL_WINDOWS) { - for (int i = 0; i < numWindows; i++) - if (Window == ALL_WINDOWS || window[i]->Tiled()) - window[i]->Clear(); + current += displayMenuItems; + first += displayMenuItems; + int count = Count(); + if (current > count - 1) { + current = count - 1; + first = max(0, count - displayMenuItems); } - else { - cWindow *w = GetWindow(Window); - if (w) - w->Clear(); + if (!SelectableItem(current)) { + current += (current < count - 1) ? 1 : -1; + first = max(first, current - displayMenuItems); } + Display(); + DisplayCurrent(true); } -void cOsdBase::Fill(int x1, int y1, int x2, int y2, eDvbColor Color, tWindowHandle Window) -{ - cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x1, y1) : GetWindow(Window); - if (w) - w->Fill(x1, y1, x2, y2, Color); -} - -void cOsdBase::SetBitmap(int x, int y, const cBitmap &Bitmap, tWindowHandle Window) +void cOsdMenu::Mark(void) { - cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x, y) : GetWindow(Window); - if (w) - w->SetBitmap(x, y, Bitmap); + if (Count() && marked < 0) { + marked = current; + SetStatus(tr("Up/Dn for new location - OK to move")); + } } -int cOsdBase::Width(unsigned char c) +eOSState cOsdMenu::HotKey(eKeys Key) { - return numWindows ? window[0]->Width(c) : 0; + for (cOsdItem *item = First(); item; item = Next(item)) { + const char *s = item->Text(); + if (s && (s = skipspace(s)) != NULL) { + if (*s == Key - k1 + '1') { + current = item->Index(); + cRemote::Put(kOk, true); + break; + } + } + } + return osContinue; } -int cOsdBase::Width(const char *s) +eOSState cOsdMenu::AddSubMenu(cOsdMenu *SubMenu) { - return numWindows ? window[0]->Width(s) : 0; + delete subMenu; + subMenu = SubMenu; + subMenu->Display(); + return osContinue; // convenience return value } -eDvbFont cOsdBase::SetFont(eDvbFont Font) +eOSState cOsdMenu::CloseSubMenu() { - eDvbFont oldFont = Font; - for (int i = 0; i < numWindows; i++) - oldFont = window[i]->SetFont(Font); - return oldFont; + delete subMenu; + subMenu = NULL; + RefreshCurrent(); + Display(); + return osContinue; // convenience return value } -void cOsdBase::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg, tWindowHandle Window) +eOSState cOsdMenu::ProcessKey(eKeys Key) { - cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x, y) : GetWindow(Window); - if (w) - w->Text(x, y, s, ColorFg, ColorBg); -} + if (subMenu) { + eOSState state = subMenu->ProcessKey(Key); + if (state == osBack) + return CloseSubMenu(); + return state; + } -void cOsdBase::Relocate(tWindowHandle Window, int x, int y, int NewWidth, int NewHeight) -{ - cWindow *w = GetWindow(Window); - if (w) { - if (NewWidth > 0 && NewHeight > 0) { - if ((NewWidth & 0x03) != 0) { - NewWidth += 4 - (NewWidth & 0x03); - dsyslog("OSD window width must be a multiple of 4 - increasing to %d", NewWidth); - } - CloseWindow(w); - cWindow *NewWindow = new cWindow(w->Handle(), x, y, NewWidth, NewHeight, w->Bpp(), w->ClearWithBackground(), w->Tiled()); - window[w->Handle()] = NewWindow; - delete w; - OpenWindow(NewWindow); - } - else { - MoveWindow(w, x, y); - w->Relocate(x, y); + cOsdItem *item = Get(current); + if (marked < 0 && item) { + eOSState state = item->ProcessKey(Key); + if (state != osUnknown) { + DisplayCurrent(true); + return state; } } + switch (Key) { + case k1...k9: return hasHotkeys ? HotKey(Key) : osUnknown; + case kUp|k_Repeat: + case kUp: CursorUp(); break; + case kDown|k_Repeat: + case kDown: CursorDown(); break; + case kLeft|k_Repeat: + case kLeft: PageUp(); break; + case kRight|k_Repeat: + case kRight: PageDown(); break; + case kBack: return osBack; + case kOk: if (marked >= 0) { + SetStatus(NULL); + if (marked != current) + Move(marked, current); + marked = -1; + break; + } + // else run into default + default: if (marked < 0) + return osUnknown; + } + return osContinue; } -void cOsdBase::Hide(tWindowHandle Window) -{ - HideWindow(GetWindow(Window), true); -} - -void cOsdBase::Show(tWindowHandle Window) -{ - HideWindow(GetWindow(Window), false); -} -- cgit v1.2.3