From 837f5e2ea9fafe3d4a8d5f4d939c5d746ee6df7b Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Fri, 20 Jan 2006 14:15:27 +0100 Subject: [PATCH] Fixed a crash in the Schedule menu with events that have no title (cEvent::FixEpgBugs() now assigns a "No title" string to events that have no title) --- CONTRIBUTORS | 1 + HISTORY | 3 + epg.c | 361 +++++++++++++++++++++++++-------------------------- 3 files changed, 184 insertions(+), 181 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index fe0481ae..546ca09d 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -936,6 +936,7 @@ Rolf Ahrenberg for reporting a bug in handling key macros with keys after @plugin for adding compiler options "-fPIC -g" to all plugins for adding a leading '0' to the day in the DayDateTime() function + for reporting a crash in the Schedule menu with events that have no title Ralf Klueber for reporting a bug in cutting a recording if there is only a single editing mark diff --git a/HISTORY b/HISTORY index 2a952cb1..abdbc825 100644 --- a/HISTORY +++ b/HISTORY @@ -4202,3 +4202,6 @@ Video Disk Recorder Revision History pointers from cChannel objects (reported by Malte Schröder). - Updated the Finnish OSD texts (thanks to Rolf Ahrenberg). - Improved NULL checking in strreplace(). +- Fixed a crash in the Schedule menu with events that have no title (reported by + Rolf Ahrenberg). cEvent::FixEpgBugs() now assigns a "No title" string to events + that have no title. diff --git a/epg.c b/epg.c index 93104f0e..384f86b3 100644 --- a/epg.c +++ b/epg.c @@ -7,7 +7,7 @@ * Original version (as used in VDR before 1.3.0) written by * Robert Schneider and Rolf Hakenes . * - * $Id: epg.c 1.50 2006/01/20 13:42:38 kls Exp $ + * $Id: epg.c 1.51 2006/01/20 14:09:48 kls Exp $ */ #include "epg.h" @@ -422,197 +422,196 @@ void cEvent::FixEpgBugs(void) strreplace(description, '\x86', ' '); strreplace(description, '\x87', ' '); + if (!title) { + // we don't want any "(null)" titles + title = strcpyrealloc(title, tr("No title")); + EpgBugFixStat(12, ChannelID()); + } + if (Setup.EPGBugfixLevel == 0) return; // Some TV stations apparently have their own idea about how to fill in the // EPG data. Let's fix their bugs as good as we can: - if (title) { - // Some channels put the ShortText in quotes and use either the ShortText - // or the Description field, depending on how long the string is: - // - // Title - // "ShortText". Description - // - if ((shortText == NULL) != (description == NULL)) { - char *p = shortText ? shortText : description; - if (*p == '"') { - const char *delim = "\"."; - char *e = strstr(p + 1, delim); - if (e) { - *e = 0; - char *s = strdup(p + 1); - char *d = strdup(e + strlen(delim)); - free(shortText); - free(description); - shortText = s; - description = d; - EpgBugFixStat(1, ChannelID()); - } - } - } - - // Some channels put the Description into the ShortText (preceded - // by a blank) if there is no actual ShortText and the Description - // is short enough: - // - // Title - // Description - // - if (shortText && !description) { - if (*shortText == ' ') { - memmove(shortText, shortText + 1, strlen(shortText)); - description = shortText; - shortText = NULL; - EpgBugFixStat(2, ChannelID()); - } - } - - // Sometimes they repeat the Title in the ShortText: - // - // Title - // Title - // - if (shortText && strcmp(title, shortText) == 0) { - free(shortText); - shortText = NULL; - EpgBugFixStat(3, ChannelID()); - } - - // Some channels put the ShortText between double quotes, which is nothing - // but annoying (some even put a '.' after the closing '"'): - // - // Title - // "ShortText"[.] - // - if (shortText && *shortText == '"') { - int l = strlen(shortText); - if (l > 2 && (shortText[l - 1] == '"' || (shortText[l - 1] == '.' && shortText[l - 2] == '"'))) { - memmove(shortText, shortText + 1, l); - char *p = strrchr(shortText, '"'); - if (p) - *p = 0; - EpgBugFixStat(4, ChannelID()); - } - } - - if (Setup.EPGBugfixLevel <= 1) - return; - - // Some channels apparently try to do some formatting in the texts, - // which is a bad idea because they have no way of knowing the width - // of the window that will actually display the text. - // Remove excess whitespace: - title = compactspace(title); - shortText = compactspace(shortText); - description = compactspace(description); - -#define MAX_USEFUL_EPISODE_LENGTH 40 - // Some channels put a whole lot of information in the ShortText and leave - // the Description totally empty. So if the ShortText length exceeds - // MAX_USEFUL_EPISODE_LENGTH, let's put this into the Description - // instead: - if (!isempty(shortText) && isempty(description)) { - if (strlen(shortText) > MAX_USEFUL_EPISODE_LENGTH) { - free(description); - description = shortText; - shortText = NULL; - EpgBugFixStat(6, ChannelID()); - } - } - - // Some channels put the same information into ShortText and Description. - // In that case we delete one of them: - if (shortText && description && strcmp(shortText, description) == 0) { - if (strlen(shortText) > MAX_USEFUL_EPISODE_LENGTH) { + // Some channels put the ShortText in quotes and use either the ShortText + // or the Description field, depending on how long the string is: + // + // Title + // "ShortText". Description + // + if ((shortText == NULL) != (description == NULL)) { + char *p = shortText ? shortText : description; + if (*p == '"') { + const char *delim = "\"."; + char *e = strstr(p + 1, delim); + if (e) { + *e = 0; + char *s = strdup(p + 1); + char *d = strdup(e + strlen(delim)); free(shortText); - shortText = NULL; - } - else { free(description); - description = NULL; + shortText = s; + description = d; + EpgBugFixStat(1, ChannelID()); } - EpgBugFixStat(7, ChannelID()); - } - - // Some channels use the ` ("backtick") character, where a ' (single quote) - // would be normally used. Actually, "backticks" in normal text don't make - // much sense, so let's replace them: - strreplace(title, '`', '\''); - strreplace(shortText, '`', '\''); - strreplace(description, '`', '\''); - - if (Setup.EPGBugfixLevel <= 2) - return; - - // The stream components have a "description" field which some channels - // apparently have no idea of how to set correctly: - if (components) { - for (int i = 0; i < components->NumComponents(); i++) { - tComponent *p = components->Component(i); - switch (p->stream) { - case 0x01: { // video - if (p->description) { - if (strcasecmp(p->description, "Video") == 0 || - strcasecmp(p->description, "Bildformat") == 0) { - // Yes, we know it's video - that's what the 'stream' code - // is for! But _which_ video is it? - free(p->description); - p->description = NULL; - EpgBugFixStat(8, ChannelID()); - } - } - if (!p->description) { - switch (p->type) { - case 0x01: - case 0x05: p->description = strdup("4:3"); break; - case 0x02: - case 0x03: - case 0x06: - case 0x07: p->description = strdup("16:9"); break; - case 0x04: - case 0x08: p->description = strdup(">16:9"); break; - case 0x09: - case 0x0D: p->description = strdup("HD 4:3"); break; - case 0x0A: - case 0x0B: - case 0x0E: - case 0x0F: p->description = strdup("HD 16:9"); break; - case 0x0C: - case 0x10: p->description = strdup("HD >16:9"); break; - } - EpgBugFixStat(9, ChannelID()); - } - } - break; - case 0x02: { // audio - if (p->description) { - if (strcasecmp(p->description, "Audio") == 0) { - // Yes, we know it's audio - that's what the 'stream' code - // is for! But _which_ audio is it? - free(p->description); - p->description = NULL; - EpgBugFixStat(10, ChannelID()); - } - } - if (!p->description) { - switch (p->type) { - case 0x05: p->description = strdup("Dolby Digital"); break; - // all others will just display the language - } - EpgBugFixStat(11, ChannelID()); - } - } - break; - } - } } } - else { - // we don't want any "(null)" titles - title = strcpyrealloc(title, tr("No title")); - EpgBugFixStat(12, ChannelID()); + + // Some channels put the Description into the ShortText (preceded + // by a blank) if there is no actual ShortText and the Description + // is short enough: + // + // Title + // Description + // + if (shortText && !description) { + if (*shortText == ' ') { + memmove(shortText, shortText + 1, strlen(shortText)); + description = shortText; + shortText = NULL; + EpgBugFixStat(2, ChannelID()); + } + } + + // Sometimes they repeat the Title in the ShortText: + // + // Title + // Title + // + if (shortText && strcmp(title, shortText) == 0) { + free(shortText); + shortText = NULL; + EpgBugFixStat(3, ChannelID()); + } + + // Some channels put the ShortText between double quotes, which is nothing + // but annoying (some even put a '.' after the closing '"'): + // + // Title + // "ShortText"[.] + // + if (shortText && *shortText == '"') { + int l = strlen(shortText); + if (l > 2 && (shortText[l - 1] == '"' || (shortText[l - 1] == '.' && shortText[l - 2] == '"'))) { + memmove(shortText, shortText + 1, l); + char *p = strrchr(shortText, '"'); + if (p) + *p = 0; + EpgBugFixStat(4, ChannelID()); + } + } + + if (Setup.EPGBugfixLevel <= 1) + return; + + // Some channels apparently try to do some formatting in the texts, + // which is a bad idea because they have no way of knowing the width + // of the window that will actually display the text. + // Remove excess whitespace: + title = compactspace(title); + shortText = compactspace(shortText); + description = compactspace(description); + +#define MAX_USEFUL_EPISODE_LENGTH 40 + // Some channels put a whole lot of information in the ShortText and leave + // the Description totally empty. So if the ShortText length exceeds + // MAX_USEFUL_EPISODE_LENGTH, let's put this into the Description + // instead: + if (!isempty(shortText) && isempty(description)) { + if (strlen(shortText) > MAX_USEFUL_EPISODE_LENGTH) { + free(description); + description = shortText; + shortText = NULL; + EpgBugFixStat(6, ChannelID()); + } + } + + // Some channels put the same information into ShortText and Description. + // In that case we delete one of them: + if (shortText && description && strcmp(shortText, description) == 0) { + if (strlen(shortText) > MAX_USEFUL_EPISODE_LENGTH) { + free(shortText); + shortText = NULL; + } + else { + free(description); + description = NULL; + } + EpgBugFixStat(7, ChannelID()); + } + + // Some channels use the ` ("backtick") character, where a ' (single quote) + // would be normally used. Actually, "backticks" in normal text don't make + // much sense, so let's replace them: + strreplace(title, '`', '\''); + strreplace(shortText, '`', '\''); + strreplace(description, '`', '\''); + + if (Setup.EPGBugfixLevel <= 2) + return; + + // The stream components have a "description" field which some channels + // apparently have no idea of how to set correctly: + if (components) { + for (int i = 0; i < components->NumComponents(); i++) { + tComponent *p = components->Component(i); + switch (p->stream) { + case 0x01: { // video + if (p->description) { + if (strcasecmp(p->description, "Video") == 0 || + strcasecmp(p->description, "Bildformat") == 0) { + // Yes, we know it's video - that's what the 'stream' code + // is for! But _which_ video is it? + free(p->description); + p->description = NULL; + EpgBugFixStat(8, ChannelID()); + } + } + if (!p->description) { + switch (p->type) { + case 0x01: + case 0x05: p->description = strdup("4:3"); break; + case 0x02: + case 0x03: + case 0x06: + case 0x07: p->description = strdup("16:9"); break; + case 0x04: + case 0x08: p->description = strdup(">16:9"); break; + case 0x09: + case 0x0D: p->description = strdup("HD 4:3"); break; + case 0x0A: + case 0x0B: + case 0x0E: + case 0x0F: p->description = strdup("HD 16:9"); break; + case 0x0C: + case 0x10: p->description = strdup("HD >16:9"); break; + } + EpgBugFixStat(9, ChannelID()); + } + } + break; + case 0x02: { // audio + if (p->description) { + if (strcasecmp(p->description, "Audio") == 0) { + // Yes, we know it's audio - that's what the 'stream' code + // is for! But _which_ audio is it? + free(p->description); + p->description = NULL; + EpgBugFixStat(10, ChannelID()); + } + } + if (!p->description) { + switch (p->type) { + case 0x05: p->description = strdup("Dolby Digital"); break; + // all others will just display the language + } + EpgBugFixStat(11, ChannelID()); + } + } + break; + } + } } }