diff --git a/mythtv/libs/libmythtv/cc608decoder.cpp b/mythtv/libs/libmythtv/cc608decoder.cpp
index 9e21e1f..f9e24cf 100644
--- a/mythtv/libs/libmythtv/cc608decoder.cpp
+++ b/mythtv/libs/libmythtv/cc608decoder.cpp
@@ -197,11 +197,21 @@ void CC608Decoder::FormatCCField(int tc, int field, int data)
             ccbuf[mode] += CharCC(b1);
             len++;
             col[mode]++;
+            if (b1 == '%') // specially encode the % character as "%%"
+            {
+                ccbuf[mode] += CharCC(b1);
+                len++;
+            }
             if (b2 & 0x60)
             {
                 ccbuf[mode] += CharCC(b2);
                 len++;
                 col[mode]++;
+                if (b2 == '%') // specially encode the % character as "%%"
+                {
+                    ccbuf[mode] += CharCC(b2);
+                    len++;
+                }
             }
         }
     }
@@ -260,6 +270,28 @@ void CC608Decoder::FormatCCField(int tc, int field, int data)
 
             // row, indent settings are not final
             // until text code arrives
+            if (b2 & 0x10) // indent with or without underline
+            {
+                if (b2 & 0x1)
+                {
+                    VERBOSE(VB_VBI,
+                            QString("cc608 preamble indent with underline, b2=%1")
+                            .arg(b2, 2, 16));
+                    // XXX- Need to insert an underline code when the
+                    // next real character arrives.
+                }
+            }
+            else // color with or without underline
+            {
+                if (b2 & 0xf)
+                {
+                    VERBOSE(VB_VBI,
+                            QString("cc608 preamble color change, b2=%1")
+                            .arg(b2, 2, 16));
+                    // XXX- Need to insert color/underline/italics
+                    // codes when the next real character arrives.
+                }
+            }
         }
         else
         {
@@ -278,8 +310,20 @@ void CC608Decoder::FormatCCField(int tc, int field, int data)
                     switch (b2 & 0x70)
                     {
                         case 0x20:      //midrow attribute change
-                            // TODO: we _do_ want colors, is that an attribute?
+                            VERBOSE(VB_VBI,
+                                    QString("cc608 mid-row color change, b2=%1")
+                                    .arg(b2, 2, 16));
+                            // Encode as "%a" through "%p" for the 16
+                            // possible values of b2.
                             ccbuf[mode] += ' ';
+                            // Insert the space character before the
+                            // control sequence, otherwise the space
+                            // character will be lost due to the
+                            // text.trimmed() operation in the
+                            // MythUIText constructor, combined with
+                            // the left-justification of captions.
+                            ccbuf[mode] += '%';
+                            ccbuf[mode] += 'a' + (b2 & 0xf);
                             len = ccbuf[mode].length();
                             col[mode]++;
                             break;
diff --git a/mythtv/libs/libmythtv/subtitlescreen.cpp b/mythtv/libs/libmythtv/subtitlescreen.cpp
index 7c949f8..37482ce 100644
--- a/mythtv/libs/libmythtv/subtitlescreen.cpp
+++ b/mythtv/libs/libmythtv/subtitlescreen.cpp
@@ -339,6 +339,8 @@ void SubtitleScreen::DisplayTextSubtitles(void)
             changed = true;
             int height = (m_safeArea.height() * m_textFontZoom) / 1800;
             gTextSubFont->GetFace()->setPixelSize(height);
+            gTextSubFont->GetFace()->setItalic(false);
+            gTextSubFont->GetFace()->setUnderline(false);
             gTextSubFont->SetColor(Qt::white);
         }
     }
@@ -424,6 +426,8 @@ void SubtitleScreen::DisplayRawTextSubtitles(void)
         {
             int height = (m_safeArea.height() * m_textFontZoom) / 1800;
             gTextSubFont->GetFace()->setPixelSize(height);
+            gTextSubFont->GetFace()->setItalic(false);
+            gTextSubFont->GetFace()->setUnderline(false);
             gTextSubFont->SetColor(Qt::white);
         }
     }
@@ -576,12 +580,55 @@ void SubtitleScreen::DisplayDVDButton(AVSubtitle* dvdButton, QRect &buttonPos)
     AddScaledImage(fg_image, button);
 }
 
+// Extract everything from the cc buffer up until the next text format
+// control sequence.  Return that substring, and remove it from the cc
+// buffer.  The "%%" escape sequence is replaced with the original
+// "%".  Bogus control sequences are left unchanged.  If the buffer
+// starts with a valid control sequence, the output parameters are
+// corresondingly updated (and the control sequence is stripped).
+static QString GetNextCC608Chunk(CC608Text *cc, int &color,
+                                 bool &isItalic, bool &isUnderline)
+{
+    QString result;
+
+    if (cc->teletextmode)
+    {
+        result = cc->text;
+        cc->text = QString::null;
+        return result;
+    }
+
+    // Handle an initial control sequence.
+    if (cc->text.length() >= 2 && cc->text[0] == '%' &&
+        cc->text[1] >= 'a' && cc->text[1] < 'a' + 16)
+    {
+        int op = cc->text[1].unicode() - 'a';
+        isUnderline = (op & 0x1);
+        if (op < 14)
+        {
+            isItalic = false;
+            color = op >> 1;
+        }
+        else
+            isItalic = true; // leave the color unchanged
+        cc->text = cc->text.mid(2);
+    }
+
+    // Copy the string into the result, up to the next control
+    // sequence.  Convert any "%%" into "%".
+    int nextControl = cc->text.indexOf(QRegExp("%[a-p]"));
+    result = cc->text.left(nextControl).replace("%%", "%");
+    cc->text = (nextControl < 0 ? QString::null : cc->text.mid(nextControl));
+
+    return result;
+}
+
 void SubtitleScreen::DisplayCC608Subtitles(void)
 {
     static const QColor clr[8] =
     {
-        Qt::white,   Qt::red,     Qt::green, Qt::yellow,
-        Qt::blue,    Qt::magenta, Qt::cyan,  Qt::white,
+        Qt::white,   Qt::green,   Qt::blue,    Qt::cyan,
+        Qt::red,     Qt::yellow,  Qt::magenta, Qt::white,
     };
 
     if (!InitialiseFont(m_fontStretch) || !m_608reader)
@@ -621,21 +668,37 @@ void SubtitleScreen::DisplayCC608Subtitles(void)
     int xscale = teletextmode ? 40 : 36;
     int yscale = teletextmode ? 25 : 17;
     gTextSubFont->GetFace()->setPixelSize(m_safeArea.height() / (yscale * 1.2));
-    QFontMetrics font(*(gTextSubFont->GetFace()));
     QBrush bgfill = QBrush(QColor(0, 0, 0), Qt::SolidPattern);
-    int height = font.height() * (1 + PAD_HEIGHT);
-    int pad_width = font.maxWidth() * PAD_WIDTH;
 
     for (; i != textlist->buffers.end(); i++)
     {
         CC608Text *cc = (*i);
+        int color = 0;
+        bool isItalic = false, isUnderline = false;
+        bool first = true;
+        int x = 0, width = 0;
 
-        if (cc && (cc->text != QString::null))
+        for (int chunk = 0; cc && (cc->text != QString::null); first = false, chunk++)
         {
-            int width  = font.width(cc->text) + pad_width;
-            int x = teletextmode ? cc->y : (cc->x + 3);
+            QString captionText = GetNextCC608Chunk(cc, color, isItalic, isUnderline);
+            gTextSubFont->GetFace()->setItalic(isItalic);
+            gTextSubFont->GetFace()->setUnderline(isUnderline);
+            gTextSubFont->SetColor(clr[min(max(0, color), 7)]);
+            QFontMetrics font(*(gTextSubFont->GetFace()));
+            // XXX- could there be different heights across the same line?
+            int height = font.height() * (1 + PAD_HEIGHT);
+            if (first)
+            {
+                x = teletextmode ? cc->y : (cc->x + 3);
+                x = (int)(((float)x / (float)xscale) * (float)m_safeArea.width());
+            }
+            else
+            {
+                x += width; // bump x by the previous width
+            }
+            int pad_width = font.maxWidth() * PAD_WIDTH;
+            width = font.width(captionText) + pad_width;
             int y = teletextmode ? cc->x : cc->y;
-            x = (int)(((float)x / (float)xscale) * (float)m_safeArea.width());
             y = (int)(((float)y / (float)yscale) * (float)m_safeArea.height());
             QRect rect(x, y, width, height);
 
@@ -648,15 +711,15 @@ void SubtitleScreen::DisplayCC608Subtitles(void)
                 shape->SetArea(MythRect(bgrect));
             }
 
-            gTextSubFont->SetColor(clr[min(max(0, cc->color), 7)]);
             MythUIText *text = new MythUIText(
-                   cc->text, *gTextSubFont, rect, rect, (MythUIType*)this,
-                   QString("cc608txt%1%2%3").arg(cc->x).arg(cc->y).arg(width));
+                   captionText, *gTextSubFont, rect, rect, (MythUIType*)this,
+                   QString("cc608txt%1%2%3%4").arg(cc->x).arg(cc->y).arg(width).arg(chunk));
             if (text)
                 text->SetJustification(Qt::AlignLeft);
             m_refreshArea = true;
-            VERBOSE(VB_VBI, QString("x %1 y %2 String: '%3'")
-                                .arg(cc->x).arg(cc->y).arg(cc->text));
+            VERBOSE(VB_VBI, QString("x %1 y %2 uline=%4 ital=%5 color=%6 coord=%7,%8 String: '%3'")
+                                .arg(cc->x).arg(cc->y).arg(captionText)
+                    .arg(isUnderline).arg(isItalic).arg(color).arg(x).arg(y));
         }
     }
     textlist->lock.unlock();
