📄 skincurses.c
字号:
/* * skincurses.c: A plugin for the Video Disk Recorder * * See the README file for copyright information and how to reach the author. * * $Id: skincurses.c 1.11 2006/09/10 14:23:55 kls Exp $ */#include <ncurses.h>#include <vdr/osd.h>#include <vdr/plugin.h>#include <vdr/skins.h>static const char *VERSION = "0.0.8";static const char *DESCRIPTION = "A text only skin";static const char *MAINMENUENTRY = NULL;// --- cCursesFont -----------------------------------------------------------class cCursesFont : public cFont {public: cCursesFont(void): cFont(NULL) {} virtual int Width(unsigned char c) const { return 1; } virtual int Width(const char *s) const { return s ? strlen(s) : 0; } virtual int Height(unsigned char c) const { return 1; } virtual int Height(const char *s) const { return 1; } virtual int Height(void) const { return 1; } };static const cCursesFont Font;// --- cCursesOsd ------------------------------------------------------------#define clrBackground COLOR_BLACK#define clrTransparent clrBackground#define clrBlack clrBackground#define clrRed COLOR_RED#define clrGreen COLOR_GREEN#define clrYellow COLOR_YELLOW#define clrBlue COLOR_BLUE#define clrMagenta COLOR_MAGENTA#define clrCyan COLOR_CYAN#define clrWhite COLOR_WHITEstatic int clrMessage[] = { clrBlack, clrCyan, clrBlack, clrGreen, clrBlack, clrYellow, clrWhite, clrRed };static int OsdWidth = 50;static int OsdHeight = 20;class cCursesOsd : public cOsd {private: WINDOW *savedRegion; WINDOW *window; enum { MaxColorPairs = 16 }; int colorPairs[MaxColorPairs]; void SetColor(int colorFg, int colorBg = clrBackground);public: cCursesOsd(int Left, int Top); virtual ~cCursesOsd(); virtual void SaveRegion(int x1, int y1, int x2, int y2); virtual void RestoreRegion(void); virtual void DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width = 0, int Height = 0, int Alignment = taDefault); virtual void DrawRectangle(int x1, int y1, int x2, int y2, tColor Color); virtual void Flush(void); };cCursesOsd::cCursesOsd(int Left, int Top):cOsd(Left, Top){ savedRegion = NULL; memset(colorPairs, 0x00, sizeof(colorPairs)); start_color(); leaveok(stdscr, true); window = subwin(stdscr, OsdHeight, OsdWidth, 0, 0); syncok(window, true);}cCursesOsd::~cCursesOsd(){ if (window) { werase(window); Flush(); delwin(window); window = NULL; }}void cCursesOsd::SetColor(int colorFg, int colorBg){ int color = (colorBg << 16) | colorFg | 0x80000000; for (int i = 0; i < MaxColorPairs; i++) { if (!colorPairs[i]) { colorPairs[i] = color; init_pair(i + 1, colorFg, colorBg); //XXX??? attron(COLOR_PAIR(WHITE_ON_BLUE)); wattrset(window, COLOR_PAIR(i + 1)); break; } else if (color == colorPairs[i]) { wattrset(window, COLOR_PAIR(i + 1)); break; } }}void cCursesOsd::SaveRegion(int x1, int y1, int x2, int y2){ if (savedRegion) { delwin(savedRegion); savedRegion = NULL; } savedRegion = newwin(y2 - y1 + 1, x2 - x1 + 1, y1, x1); copywin(window, savedRegion, y1, x1, 0, 0, y2 - y1, x2 - x1, false);}void cCursesOsd::RestoreRegion(void){ if (savedRegion) { copywin(savedRegion, window, 0, 0, savedRegion->_begy, savedRegion->_begx, savedRegion->_maxy - savedRegion->_begy, savedRegion->_maxx - savedRegion->_begx, false); delwin(savedRegion); savedRegion = NULL; }}void cCursesOsd::DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width, int Height, int Alignment){ int w = Font->Width(s); int h = Font->Height(); if (Width || Height) { int cw = Width ? Width : w; int ch = Height ? Height : h; DrawRectangle(x, y, x + cw - 1, y + ch - 1, ColorBg); if (Width) { if ((Alignment & taLeft) != 0) ; else if ((Alignment & taRight) != 0) { if (w < Width) x += Width - w; } else { // taCentered if (w < Width) x += (Width - w) / 2; } } if (Height) { if ((Alignment & taTop) != 0) ; else if ((Alignment & taBottom) != 0) { if (h < Height) y += Height - h; } else { // taCentered if (h < Height) y += (Height - h) / 2; } } } SetColor(ColorFg, ColorBg); wmove(window, y, x); // ncurses wants 'y' before 'x'! waddnstr(window, s, OsdWidth - x);}void cCursesOsd::DrawRectangle(int x1, int y1, int x2, int y2, tColor Color){ SetColor(Color, Color); for (int y = y1; y <= y2; y++) { wmove(window, y, x1); // ncurses wants 'y' before 'x'! whline(window, ' ', x2 - x1 + 1); } wsyncup(window); // shouldn't be necessary because of 'syncok()', but w/o it doesn't work}void cCursesOsd::Flush(void){ refresh();}// --- cSkinCursesDisplayChannel ---------------------------------------------class cSkinCursesDisplayChannel : public cSkinDisplayChannel {private: cOsd *osd; int timeWidth; bool message;public: cSkinCursesDisplayChannel(bool WithInfo); virtual ~cSkinCursesDisplayChannel(); virtual void SetChannel(const cChannel *Channel, int Number); virtual void SetEvents(const cEvent *Present, const cEvent *Following); virtual void SetMessage(eMessageType Type, const char *Text); virtual void Flush(void); };cSkinCursesDisplayChannel::cSkinCursesDisplayChannel(bool WithInfo){ int Lines = WithInfo ? 5 : 1; message = false; osd = new cCursesOsd(0, Setup.ChannelInfoPos ? 0 : OsdHeight - Lines); timeWidth = strlen("00:00"); osd->DrawRectangle(0, 0, OsdWidth - 1, Lines - 1, clrBackground);}cSkinCursesDisplayChannel::~cSkinCursesDisplayChannel(){ delete osd;}void cSkinCursesDisplayChannel::SetChannel(const cChannel *Channel, int Number){ osd->DrawRectangle(0, 0, OsdWidth - 1, 0, clrBackground); osd->DrawText(0, 0, ChannelString(Channel, Number), clrWhite, clrBackground, &Font);}void cSkinCursesDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following){ osd->DrawRectangle(0, 1, timeWidth - 1, 4, clrRed); osd->DrawRectangle(timeWidth, 1, OsdWidth - 1, 4, clrBackground); for (int i = 0; i < 2; i++) { const cEvent *e = !i ? Present : Following; if (e) { osd->DrawText( 0, 2 * i + 1, e->GetTimeString(), clrWhite, clrRed, &Font); osd->DrawText(timeWidth + 1, 2 * i + 1, e->Title(), clrCyan, clrBackground, &Font); osd->DrawText(timeWidth + 1, 2 * i + 2, e->ShortText(), clrYellow, clrBackground, &Font); } }}void cSkinCursesDisplayChannel::SetMessage(eMessageType Type, const char *Text){ if (Text) { osd->SaveRegion(0, 0, OsdWidth - 1, 0); osd->DrawText(0, 0, Text, clrMessage[2 * Type], clrMessage[2 * Type + 1], &Font, OsdWidth, 0, taCenter); message = true; } else { osd->RestoreRegion(); message = false; }}void cSkinCursesDisplayChannel::Flush(void){ if (!message) { cString date = DayDateTime(); osd->DrawText(OsdWidth - strlen(date), 0, date, clrWhite, clrBackground, &Font); } osd->Flush();}// --- cSkinCursesDisplayMenu ------------------------------------------------class cSkinCursesDisplayMenu : public cSkinDisplayMenu {private: cOsd *osd; void SetScrollbar(void);public: cSkinCursesDisplayMenu(void); virtual ~cSkinCursesDisplayMenu(); virtual void Scroll(bool Up, bool Page); virtual int MaxItems(void); virtual void Clear(void); virtual void SetTitle(const char *Title); virtual void SetButtons(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL); virtual void SetMessage(eMessageType Type, const char *Text); virtual void SetItem(const char *Text, int Index, bool Current, bool Selectable); virtual void SetEvent(const cEvent *Event); virtual void SetRecording(const cRecording *Recording); virtual void SetText(const char *Text, bool FixedFont); virtual const cFont *GetTextAreaFont(bool FixedFont) const { return &Font; } virtual void Flush(void); };cSkinCursesDisplayMenu::cSkinCursesDisplayMenu(void){ osd = new cCursesOsd(0, 0); osd->DrawRectangle(0, 0, OsdWidth - 1, OsdHeight - 1, clrBackground);}cSkinCursesDisplayMenu::~cSkinCursesDisplayMenu(){ delete osd;}void cSkinCursesDisplayMenu::SetScrollbar(void){ if (textScroller.CanScroll()) { int yt = textScroller.Top(); int yb = yt + textScroller.Height() - 1; int st = yt; int sb = yb; int tt = st + (sb - st) * textScroller.Offset() / textScroller.Total(); int tb = tt + (sb - st) * textScroller.Shown() / textScroller.Total(); int xl = OsdWidth - 1; osd->DrawRectangle(xl, st, xl, sb, clrCyan); osd->DrawRectangle(xl, tt, xl, tb, clrWhite); }}void cSkinCursesDisplayMenu::Scroll(bool Up, bool Page){ cSkinDisplayMenu::Scroll(Up, Page); SetScrollbar();}int cSkinCursesDisplayMenu::MaxItems(void){ return OsdHeight - 4;}void cSkinCursesDisplayMenu::Clear(void){ osd->DrawRectangle(0, 1, OsdWidth - 1, OsdHeight - 2, clrBackground); textScroller.Reset();}void cSkinCursesDisplayMenu::SetTitle(const char *Title){ osd->DrawText(0, 0, Title, clrBlack, clrCyan, &Font, OsdWidth);}void cSkinCursesDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue){ int w = OsdWidth; int t0 = 0; int t1 = 0 + w / 4; int t2 = 0 + w / 2; int t3 = w - w / 4; int t4 = w; int y = OsdHeight - 1; osd->DrawText(t0, y, Red, clrWhite, Red ? clrRed : clrBackground, &Font, t1 - t0, 0, taCenter); osd->DrawText(t1, y, Green, clrBlack, Green ? clrGreen : clrBackground, &Font, t2 - t1, 0, taCenter); osd->DrawText(t2, y, Yellow, clrBlack, Yellow ? clrYellow : clrBackground, &Font, t3 - t2, 0, taCenter); osd->DrawText(t3, y, Blue, clrWhite, Blue ? clrBlue : clrBackground, &Font, t4 - t3, 0, taCenter);}void cSkinCursesDisplayMenu::SetMessage(eMessageType Type, const char *Text){ if (Text) osd->DrawText(0, OsdHeight - 2, Text, clrMessage[2 * Type], clrMessage[2 * Type + 1], &Font, OsdWidth, 0, taCenter); else osd->DrawRectangle(0, OsdHeight - 2, OsdWidth - 1, OsdHeight - 2, clrBackground);}void cSkinCursesDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable){ int y = 2 + Index; int ColorFg, ColorBg; if (Current) { ColorFg = clrBlack; ColorBg = clrCyan; } else { ColorFg = Selectable ? clrWhite : clrCyan; ColorBg = clrBackground; } for (int i = 0; i < MaxTabs; i++) { const char *s = GetTabbedText(Text, i); if (s) { int xt = Tab(i) / 12;// Tab() is in "pixel" - see also skins.c!!! osd->DrawText(xt, y, s, ColorFg, ColorBg, &Font, OsdWidth - xt); } if (!Tab(i + 1)) break; } SetEditableWidth(OsdWidth - Tab(1) / 12); // Tab() is in "pixel" - see also skins.c!!!}void cSkinCursesDisplayMenu::SetEvent(const cEvent *Event){ if (!Event) return; int y = 2; cTextScroller ts; char t[32]; snprintf(t, sizeof(t), "%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString()); ts.Set(osd, 0, y, OsdWidth, OsdHeight - y - 2, t, &Font, clrYellow, clrBackground); if (Event->Vps() && Event->Vps() != Event->StartTime()) { char *buffer; asprintf(&buffer, " VPS: %s", *Event->GetVpsString()); osd->DrawText(OsdWidth - strlen(buffer), y, buffer, clrBlack, clrYellow, &Font); free(buffer); } y += ts.Height(); y += 1; ts.Set(osd, 0, y, OsdWidth, OsdHeight - y - 2, Event->Title(), &Font, clrCyan, clrBackground); y += ts.Height(); if (!isempty(Event->ShortText())) { ts.Set(osd, 0, y, OsdWidth, OsdHeight - y - 2, Event->ShortText(), &Font, clrYellow, clrBackground); y += ts.Height(); } y += 1; if (!isempty(Event->Description())) { textScroller.Set(osd, 0, y, OsdWidth - 2, OsdHeight - y - 2, Event->Description(), &Font, clrCyan, clrBackground); SetScrollbar(); }}void cSkinCursesDisplayMenu::SetRecording(const cRecording *Recording){ if (!Recording) return; const cRecordingInfo *Info = Recording->Info();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -