diff --git a/mythtv/libs/libmythtv/cc608decoder.cpp b/mythtv/libs/libmythtv/cc608decoder.cpp
index 9e21e1f..9649c87 100644
--- a/mythtv/libs/libmythtv/cc608decoder.cpp
+++ b/mythtv/libs/libmythtv/cc608decoder.cpp
@@ -43,6 +43,7 @@ CC608Decoder::CC608Decoder(CC608Input *ccr)
     memset(lastrow,    0, sizeof(lastrow));
     memset(newrow,     0, sizeof(newrow));
     memset(newcol,     0, sizeof(newcol));
+    memset(newattr,    0, sizeof(newattr));
     memset(timecode,   0, sizeof(timecode));
     memset(row,        0, sizeof(row));
     memset(col,        0, sizeof(col));
@@ -254,11 +255,27 @@ void CC608Decoder::FormatCCField(int tc, int field, int data)
                 newrow[mode] = lastrow[mode] + 1;
 
             if (b2 & 0x10)        //row contains indent flag
+            {
                 newcol[mode] = (b2 & 0x0E) << 1;
+                // Encode as 0x7020 or 0x7021 depending on the
+                // underline flag.
+                newattr[mode] = (b2 & 0x1) + 0x20;
+                VERBOSE(VB_VBI,
+                        QString("cc608 preamble indent, b2=%1")
+                        .arg(b2, 2, 16));
+            }
             else
+            {
                 newcol[mode] = 0;
+                newattr[mode] = (b2 & 0xf) + 0x10;
+                // Encode as 0x7010 through 0x702f for the 16 possible
+                // values of b2.
+                VERBOSE(VB_VBI,
+                        QString("cc608 preamble color change, b2=%1")
+                        .arg(b2, 2, 16));
+            }
 
-            // row, indent settings are not final
+            // row, indent, attribute settings are not final
             // until text code arrives
         }
         else
@@ -278,8 +295,12 @@ 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?
-                            ccbuf[mode] += ' ';
+                            VERBOSE(VB_VBI,
+                                    QString("cc608 mid-row color change, b2=%1")
+                                    .arg(b2, 2, 16));
+                            // Encode as 0x7000 through 0x700f for the
+                            // 16 possible values of b2.
+                            ccbuf[mode] += QChar(0x7000 + (b2 & 0xf));
                             len = ccbuf[mode].length();
                             col[mode]++;
                             break;
@@ -412,6 +433,7 @@ void CC608Decoder::FormatCCField(int tc, int field, int data)
                             {
                                 newrow[mode] = 1;
                                 newcol[mode] = 0;
+                                newattr[mode] = 0;
                             }
                             style[mode] = CC_STYLE_ROLLUP;
                             break;
@@ -474,6 +496,7 @@ void CC608Decoder::FormatCCField(int tc, int field, int data)
                             // TXT starts at row 1
                             newrow[mode] = 1;
                             newcol[mode] = 0;
+                            newattr[mode] = 0;
                             style[mode] = CC_STYLE_ROLLUP;
                             break;
 
@@ -651,7 +674,8 @@ void CC608Decoder::BufferCC(int mode, int len, int clr)
         int i = 0;
         while (i < dispbuf.length()) {
             QChar cp = dispbuf.at(i);
-            switch (cp.unicode())
+            int cpu = cp.unicode();
+            switch (cpu)
             {
                 case 0x2120 :  vbuf += "(SM)"; break;
                 case 0x2122 :  vbuf += "(TM)"; break;
@@ -665,7 +689,10 @@ void CC608Decoder::BufferCC(int mode, int len, int clr)
                 case 0x2588 :  vbuf += "[]"; break;
                 case 0x266A :  vbuf += "o/~"; break;
                 case '\b'   :  vbuf += "\\b"; break;
-                default     :  vbuf += QString(cp.toLatin1());
+                default     :
+                    if (cpu >= 0x7000 && cpu < 0x7000 + 0x30)
+                        vbuf += QString("[%1]").arg(cpu - 0x7000, 2, 16);
+                    else vbuf += QString(cp.toLatin1());
             }
             i++;
         }
@@ -771,13 +798,21 @@ int CC608Decoder::NewRowCC(int mode, int len)
     lastrow[mode] = newrow[mode];
     newrow[mode] = 0;
 
-    for (int x = 0; x < newcol[mode]; x++)
+    int limit = (newattr[mode] ? newcol[mode] - 1 : newcol[mode]);
+    for (int x = 0; x < limit; x++)
     {
         ccbuf[mode] += ' ';
         len++;
         col[mode]++;
     }
+    if (newattr[mode])
+    {
+        ccbuf[mode] += QChar(newattr[mode] + 0x7000);
+        len++;
+        col[mode]++;
+    }
     newcol[mode] = 0;
+    newattr[mode] = 0;
 
     return len;
 }
diff --git a/mythtv/libs/libmythtv/cc608decoder.h b/mythtv/libs/libmythtv/cc608decoder.h
index 1463144..b87bbf5 100644
--- a/mythtv/libs/libmythtv/cc608decoder.h
+++ b/mythtv/libs/libmythtv/cc608decoder.h
@@ -98,6 +98,7 @@ class CC608Decoder
     int lastrow[8];
     int newrow[8];
     int newcol[8];
+    int newattr[8]; // color+italic+underline
     int timecode[8];
     int row[8];
     int col[8];
diff --git a/mythtv/libs/libmythtv/cc608reader.cpp b/mythtv/libs/libmythtv/cc608reader.cpp
index f430c65..f5cc1c5 100644
--- a/mythtv/libs/libmythtv/cc608reader.cpp
+++ b/mythtv/libs/libmythtv/cc608reader.cpp
@@ -74,7 +74,7 @@ CC608Buffer* CC608Reader::GetOutputText(bool &changed)
                     inpos += sizeof(st);
 
                     CC608Text *cc = new CC608Text(QString((const char*) inpos),
-                                        st.row, st.col, st.fg, true);
+                                        st.row, st.col, true);
                     m_outputBuffers.lock.lock();
                     m_outputBuffers.buffers.push_back(cc);
                     m_outputBuffers.lock.unlock();
@@ -188,7 +188,7 @@ void CC608Reader::Update(unsigned char *inpos)
                 else
                     m_outputText = QString::fromUtf8((const char *)inpos, -1);
                 tmpcc = new CC608Text(m_outputText, m_outputCol, m_outputRow,
-                                      0, false);
+                                      false);
                 ccbuf->push_back(tmpcc);
 #if 0
                 if (ccbuf->size() > 4)
diff --git a/mythtv/libs/libmythtv/cc608reader.h b/mythtv/libs/libmythtv/cc608reader.h
index 5e020db..96a4507 100644
--- a/mythtv/libs/libmythtv/cc608reader.h
+++ b/mythtv/libs/libmythtv/cc608reader.h
@@ -14,12 +14,11 @@
 class CC608Text
 {
   public:
-    CC608Text(QString T, int X, int Y, int C, int TT)
-      : text(T), x(X), y(Y), color(C), teletextmode(TT) {}
+    CC608Text(QString T, int X, int Y, int TT)
+      : text(T), x(X), y(Y), teletextmode(TT) {}
     QString text;
     int x;
     int y;
-    int color;
     bool teletextmode;
 };
 
diff --git a/mythtv/libs/libmythtv/subtitlescreen.cpp b/mythtv/libs/libmythtv/subtitlescreen.cpp
index 7c949f8..05804dc 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,86 @@ void SubtitleScreen::DisplayDVDButton(AVSubtitle* dvdButton, QRect &buttonPos)
     AddScaledImage(bg_image, rect);
 }
 
+// Extract everything from the text buffer up until the next format
+// control character.  Return that substring, and remove it from the
+// input string.  Bogus control characters are left unchanged.  If the
+// buffer starts with a valid control character, the output parameters
+// are corresondingly updated (and the control character is stripped).
+static QString GetNextCC608Chunk(QString &text, bool teletextmode,
+                                 int &color, bool &isItalic, bool &isUnderline,
+                                 bool &showedNonControl)
+{
+    QString result;
+    QString orig(text);
+
+    if (teletextmode)
+    {
+        result = text;
+        text = QString::null;
+        showedNonControl = true;
+        return result;
+    }
+
+    // Handle an initial control sequence.
+    if (text.length() >= 1 && text[0] >= 0x7000)
+    {
+        int op = text[0].unicode() - 0x7000;
+        isUnderline = (op & 0x1);
+        switch (op & ~1)
+        {
+        case 0x0e:
+            // color unchanged
+            isItalic = true;
+            break;
+        case 0x1e:
+            color = op >> 1;
+            isItalic = true;
+            break;
+        case 0x20:
+            // color unchanged
+            // italics unchanged
+            break;
+        default:
+            color = (op & 0xf) >> 1;
+            isItalic = false;
+            break;
+        }
+        text = text.mid(1);
+    }
+
+    // Copy the string into the result, up to the next control
+    // character.
+    int nextControl = text.indexOf(QRegExp("[\\x7000-\\x7fff]"));
+    if (nextControl < 0)
+    {
+        result = text;
+        text = QString::null;
+        showedNonControl = true;
+    }
+    else
+    {
+        result = text.left(nextControl);
+        // Print the space character before handling the next control
+        // character, otherwise the space character will be lost due
+        // to the text.trimmed() operation in the MythUIText
+        // constructor, combined with the left-justification of
+        // captions.
+        if (text[nextControl] < (0x7000 + 0x10))
+            result += " ";
+        text = text.mid(nextControl);
+        if (nextControl > 0)
+            showedNonControl = true;
+    }
+
+    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,22 +699,51 @@ 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;
+        bool showedNonControl = false;
+        int x = 0, width = 0;
+        QString text(cc->text);
 
-        if (cc && (cc->text != QString::null))
+        for (int chunk = 0; 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(text, cc->teletextmode,
+                                  color, isItalic, isUnderline,
+                                  showedNonControl);
+            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());
+            // Sometimes a line of caption text begins with a mid-row
+            // format control like italics or a color change.  The
+            // spec says the mid-row control also includes a space
+            // character.  But this looks clumsy when using a
+            // background, so we suppress it after the placement is
+            // calculated.
+            if (!showedNonControl)
+                continue;
             QRect rect(x, y, width, height);
 
             if (!teletextmode && m_useBackground)
@@ -648,15 +755,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();
