summaryrefslogtreecommitdiff
path: root/menuitems.c
diff options
context:
space:
mode:
Diffstat (limited to 'menuitems.c')
-rw-r--r--menuitems.c476
1 files changed, 476 insertions, 0 deletions
diff --git a/menuitems.c b/menuitems.c
new file mode 100644
index 00000000..d09f5b70
--- /dev/null
+++ b/menuitems.c
@@ -0,0 +1,476 @@
+/*
+ * menuitems.c: General purpose menu items
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ *
+ * $Id: menuitems.c 1.1 2002/05/09 10:10:12 kls Exp $
+ */
+
+#include "menuitems.h"
+#include <ctype.h>
+#include "i18n.h"
+
+// --- cMenuEditItem ---------------------------------------------------------
+
+cMenuEditItem::cMenuEditItem(const char *Name)
+{
+ name = strdup(Name);
+ value = NULL;
+}
+
+cMenuEditItem::~cMenuEditItem()
+{
+ delete name;
+ delete value;
+}
+
+void cMenuEditItem::SetValue(const char *Value)
+{
+ delete value;
+ value = strdup(Value);
+ char *buffer = NULL;
+ asprintf(&buffer, "%s:\t%s", name, value);
+ SetText(buffer, false);
+ Display();
+}
+
+// --- cMenuEditIntItem ------------------------------------------------------
+
+cMenuEditIntItem::cMenuEditIntItem(const char *Name, int *Value, int Min, int Max)
+:cMenuEditItem(Name)
+{
+ value = Value;
+ min = Min;
+ max = Max;
+ Set();
+}
+
+void cMenuEditIntItem::Set(void)
+{
+ char buf[16];
+ snprintf(buf, sizeof(buf), "%d", *value);
+ SetValue(buf);
+}
+
+eOSState cMenuEditIntItem::ProcessKey(eKeys Key)
+{
+ eOSState state = cMenuEditItem::ProcessKey(Key);
+
+ if (state == osUnknown) {
+ int newValue;
+ if (k0 <= Key && Key <= k9) {
+ if (fresh) {
+ *value = 0;
+ fresh = false;
+ }
+ newValue = *value * 10 + (Key - k0);
+ }
+ else if (NORMALKEY(Key) == kLeft) { // TODO might want to increase the delta if repeated quickly?
+ newValue = *value - 1;
+ fresh = true;
+ }
+ else if (NORMALKEY(Key) == kRight) {
+ newValue = *value + 1;
+ fresh = true;
+ }
+ else
+ return state;
+ if ((!fresh || min <= newValue) && newValue <= max) {
+ *value = newValue;
+ Set();
+ }
+ state = osContinue;
+ }
+ return state;
+}
+
+// --- cMenuEditBoolItem -----------------------------------------------------
+
+cMenuEditBoolItem::cMenuEditBoolItem(const char *Name, int *Value, const char *FalseString, const char *TrueString)
+:cMenuEditIntItem(Name, Value, 0, 1)
+{
+ falseString = FalseString ? FalseString : tr("no");
+ trueString = TrueString ? TrueString : tr("yes");
+ Set();
+}
+
+void cMenuEditBoolItem::Set(void)
+{
+ char buf[16];
+ snprintf(buf, sizeof(buf), "%s", *value ? trueString : falseString);
+ SetValue(buf);
+}
+
+// --- cMenuEditChrItem ------------------------------------------------------
+
+cMenuEditChrItem::cMenuEditChrItem(const char *Name, char *Value, const char *Allowed)
+:cMenuEditItem(Name)
+{
+ value = Value;
+ allowed = strdup(Allowed);
+ current = strchr(allowed, *Value);
+ if (!current)
+ current = allowed;
+ Set();
+}
+
+cMenuEditChrItem::~cMenuEditChrItem()
+{
+ delete allowed;
+}
+
+void cMenuEditChrItem::Set(void)
+{
+ char buf[2];
+ snprintf(buf, sizeof(buf), "%c", *value);
+ SetValue(buf);
+}
+
+eOSState cMenuEditChrItem::ProcessKey(eKeys Key)
+{
+ eOSState state = cMenuEditItem::ProcessKey(Key);
+
+ if (state == osUnknown) {
+ if (NORMALKEY(Key) == kLeft) {
+ if (current > allowed)
+ current--;
+ }
+ else if (NORMALKEY(Key) == kRight) {
+ if (*(current + 1))
+ current++;
+ }
+ else
+ return state;
+ *value = *current;
+ Set();
+ state = osContinue;
+ }
+ return state;
+}
+
+// --- cMenuEditStrItem ------------------------------------------------------
+
+cMenuEditStrItem::cMenuEditStrItem(const char *Name, char *Value, int Length, const char *Allowed)
+:cMenuEditItem(Name)
+{
+ value = Value;
+ length = Length;
+ allowed = strdup(Allowed);
+ pos = -1;
+ insert = uppercase = false;
+ newchar = true;
+ Set();
+}
+
+cMenuEditStrItem::~cMenuEditStrItem()
+{
+ delete allowed;
+}
+
+void cMenuEditStrItem::SetHelpKeys(void)
+{
+ if (pos >= 0)
+ Interface->Help(tr("ABC/abc"), tr(insert ? "Overwrite" : "Insert"), tr("Delete"));
+ else
+ Interface->Help(NULL);
+}
+
+void cMenuEditStrItem::Set(void)
+{
+ char buf[1000];
+ const char *fmt = insert && newchar ? "[]%c%s" : "[%c]%s";
+
+ if (pos >= 0) {
+ strncpy(buf, value, pos);
+ snprintf(buf + pos, sizeof(buf) - pos - 2, fmt, *(value + pos), value + pos + 1);
+ int width = Interface->Width() - Interface->GetCols()[0];
+ if (cDvbApi::PrimaryDvbApi->WidthInCells(buf) <= width) {
+ // the whole buffer fits on the screen
+ SetValue(buf);
+ return;
+ }
+ width *= cDvbApi::PrimaryDvbApi->CellWidth();
+ width -= cDvbApi::PrimaryDvbApi->Width('>'); // assuming '<' and '>' have the same with
+ int w = 0;
+ int i = 0;
+ int l = strlen(buf);
+ while (i < l && w <= width)
+ w += cDvbApi::PrimaryDvbApi->Width(buf[i++]);
+ if (i >= pos + 4) {
+ // the cursor fits on the screen
+ buf[i - 1] = '>';
+ buf[i] = 0;
+ SetValue(buf);
+ return;
+ }
+ // the cursor doesn't fit on the screen
+ w = 0;
+ if (buf[i = pos + 3]) {
+ buf[i] = '>';
+ buf[i + 1] = 0;
+ }
+ else
+ i--;
+ while (i >= 0 && w <= width)
+ w += cDvbApi::PrimaryDvbApi->Width(buf[i--]);
+ buf[++i] = '<';
+ SetValue(buf + i);
+ }
+ else
+ SetValue(value);
+}
+
+char cMenuEditStrItem::Inc(char c, bool Up)
+{
+ const char *p = strchr(allowed, c);
+ if (!p)
+ p = allowed;
+ if (Up) {
+ if (!*++p)
+ p = allowed;
+ }
+ else if (--p < allowed)
+ p = allowed + strlen(allowed) - 1;
+ return *p;
+}
+
+eOSState cMenuEditStrItem::ProcessKey(eKeys Key)
+{
+ switch (Key) {
+ case kRed: // Switch between upper- and lowercase characters
+ if (pos >= 0 && (!insert || !newchar)) {
+ uppercase = !uppercase;
+ value[pos] = uppercase ? toupper(value[pos]) : tolower(value[pos]);
+ }
+ break;
+ case kGreen: // Toggle insert/overwrite modes
+ if (pos >= 0) {
+ insert = !insert;
+ newchar = true;
+ }
+ SetHelpKeys();
+ break;
+ case kYellow|k_Repeat:
+ case kYellow: // Remove the character at current position; in insert mode it is the character to the right of cursor
+ if (pos >= 0) {
+ if (strlen(value) > 1) {
+ memmove(value + pos, value + pos + 1, strlen(value) - pos);
+ // reduce position, if we removed the last character
+ if (pos == int(strlen(value)))
+ pos--;
+ }
+ else if (strlen(value) == 1)
+ value[0] = ' '; // This is the last character in the string, replace it with a blank
+ if (isalpha(value[pos]))
+ uppercase = isupper(value[pos]);
+ newchar = true;
+ }
+ break;
+ case kLeft|k_Repeat:
+ case kLeft: if (pos > 0) {
+ if (!insert || newchar)
+ pos--;
+ newchar = true;
+ }
+ if (!insert && isalpha(value[pos]))
+ uppercase = isupper(value[pos]);
+ break;
+ case kRight|k_Repeat:
+ case kRight: if (pos < length && pos < int(strlen(value)) ) {
+ if (++pos >= int(strlen(value))) {
+ if (pos >= 2 && value[pos - 1] == ' ' && value[pos - 2] == ' ')
+ pos--; // allow only two blanks at the end
+ else {
+ value[pos] = ' ';
+ value[pos + 1] = 0;
+ }
+ }
+ }
+ newchar = true;
+ if (!insert && isalpha(value[pos]))
+ uppercase = isupper(value[pos]);
+ if (pos == 0)
+ SetHelpKeys();
+ break;
+ case kUp|k_Repeat:
+ case kUp:
+ case kDown|k_Repeat:
+ case kDown: if (pos >= 0) {
+ if (insert && newchar) {
+ // create a new character in insert mode
+ if (int(strlen(value)) < length) {
+ memmove(value + pos + 1, value + pos, strlen(value) - pos + 1);
+ value[pos] = ' ';
+ }
+ }
+ if (uppercase)
+ value[pos] = toupper(Inc(tolower(value[pos]), NORMALKEY(Key) == kUp));
+ else
+ value[pos] = Inc( value[pos], NORMALKEY(Key) == kUp);
+ newchar = false;
+ }
+ else
+ return cMenuEditItem::ProcessKey(Key);
+ break;
+ case kOk: if (pos >= 0) {
+ pos = -1;
+ newchar = true;
+ stripspace(value);
+ SetHelpKeys();
+ break;
+ }
+ // run into default
+ default: return cMenuEditItem::ProcessKey(Key);
+ }
+ Set();
+ return osContinue;
+}
+
+// --- cMenuEditStraItem -----------------------------------------------------
+
+cMenuEditStraItem::cMenuEditStraItem(const char *Name, int *Value, int NumStrings, const char * const *Strings)
+:cMenuEditIntItem(Name, Value, 0, NumStrings - 1)
+{
+ strings = Strings;
+ Set();
+}
+
+void cMenuEditStraItem::Set(void)
+{
+ SetValue(strings[*value]);
+}
+
+// --- cMenuTextItem ---------------------------------------------------------
+
+cMenuTextItem::cMenuTextItem(const char *Text, int X, int Y, int W, int H, eDvbColor FgColor, eDvbColor BgColor, eDvbFont Font)
+{
+ x = X;
+ y = Y;
+ w = W;
+ h = H;
+ fgColor = FgColor;
+ bgColor = BgColor;
+ font = Font;
+ offset = 0;
+ eDvbFont oldFont = Interface->SetFont(font);
+ text = Interface->WrapText(Text, w - 1, &lines);
+ Interface->SetFont(oldFont);
+ if (h < 0)
+ h = lines;
+}
+
+cMenuTextItem::~cMenuTextItem()
+{
+ delete text;
+}
+
+void cMenuTextItem::Clear(void)
+{
+ Interface->Fill(x, y, w, h, bgColor);
+}
+
+void cMenuTextItem::Display(int Offset, eDvbColor FgColor, eDvbColor BgColor)
+{
+ int l = 0;
+ char *t = text;
+ eDvbFont oldFont = Interface->SetFont(font);
+ while (*t) {
+ char *n = strchr(t, '\n');
+ if (l >= offset) {
+ if (n)
+ *n = 0;
+ Interface->Write(x, y + l - offset, t, fgColor, bgColor);
+ if (n)
+ *n = '\n';
+ else
+ break;
+ }
+ if (!n)
+ break;
+ t = n + 1;
+ if (++l >= h + offset)
+ break;
+ }
+ Interface->SetFont(oldFont);
+ // scroll indicators use inverted color scheme!
+ if (CanScrollUp()) Interface->Write(x + w - 1, y, "^", bgColor, fgColor);
+ if (CanScrollDown()) Interface->Write(x + w - 1, y + h - 1, "v", bgColor, fgColor);
+}
+
+void cMenuTextItem::ScrollUp(bool Page)
+{
+ if (CanScrollUp()) {
+ Clear();
+ offset = max(offset - (Page ? h : 1), 0);
+ Display();
+ }
+}
+
+void cMenuTextItem::ScrollDown(bool Page)
+{
+ if (CanScrollDown()) {
+ Clear();
+ offset = min(offset + (Page ? h : 1), lines - h);
+ Display();
+ }
+}
+
+eOSState cMenuTextItem::ProcessKey(eKeys Key)
+{
+ switch (Key) {
+ case kLeft|k_Repeat:
+ case kLeft:
+ case kUp|k_Repeat:
+ case kUp: ScrollUp(NORMALKEY(Key) == kLeft); break;
+ case kRight|k_Repeat:
+ case kRight:
+ case kDown|k_Repeat:
+ case kDown: ScrollDown(NORMALKEY(Key) == kRight); break;
+ default: return osUnknown;
+ }
+ return osContinue;
+}
+
+// --- cMenuSetupPage --------------------------------------------------------
+
+cMenuSetupPage::cMenuSetupPage(void)
+:cOsdMenu("", 33)
+{
+ data = Setup;
+ osdLanguage = Setup.OSDLanguage;
+}
+
+void cMenuSetupPage::SetupTitle(const char *s)
+{
+ char buf[40]; // can't call tr() for more than one string at a time!
+ char *q = buf + snprintf(buf, sizeof(buf), "%s - ", tr("Setup"));
+ snprintf(q, sizeof(buf) - strlen(buf), "%s", tr(s));
+ SetTitle(buf);
+}
+
+eOSState cMenuSetupPage::ProcessKey(eKeys Key)
+{
+ eOSState state = cOsdMenu::ProcessKey(Key);
+
+ if (state == osUnknown) {
+ switch (Key) {
+ case kOk: state = (Setup.PrimaryDVB != data.PrimaryDVB) ? osSwitchDvb : osBack;
+ cDvbApi::PrimaryDvbApi->SetVideoFormat(data.VideoFormat ? VIDEO_FORMAT_16_9 : VIDEO_FORMAT_4_3);
+ Setup = data;
+ Setup.Save();
+ cDvbApi::SetCaCaps();
+ break;
+ default: break;
+ }
+ }
+ if (data.OSDLanguage != osdLanguage) {
+ int OriginalOSDLanguage = Setup.OSDLanguage;
+ Setup.OSDLanguage = data.OSDLanguage;
+ Set();
+ Display();
+ osdLanguage = data.OSDLanguage;
+ Setup.OSDLanguage = OriginalOSDLanguage;
+ }
+ return state;
+}