diff --git a/src/vte-private.h b/src/vte-private.h
index 9192fb3..fbbf3a0 100644
--- a/src/vte-private.h
+++ b/src/vte-private.h
@@ -56,11 +56,34 @@ G_BEGIN_DECLS
 #define VTE_LINE_WIDTH			1
 #define VTE_ROWS			24
 #define VTE_COLUMNS			80
+
+/*
+ * Colors are encoded in 25 bits as follows:
+ *
+ * 0 .. 255:
+ *   Colors set by SGR 256-color extension (38/48;5;index).
+ *   These are direct indices into the color palette.
+ *
+ * 256 .. VTE_PALETTE_SIZE - 1 (261):
+ *   Special values, such as default colors.
+ *   These are direct indices into the color palette.
+ *
+ * VTE_LEGACY_COLORS_OFFSET (512) .. VTE_LEGACY_COLORS_OFFSET + VTE_LEGACY_FULL_COLOR_SET_SIZE - 1 (527):
+ *   Colors set by legacy escapes (30..37/40..47, 90..97/100..107).
+ *   These are translated to 0 .. 15 before looking up in the palette, taking bold into account.
+ *
+ * VTE_RGB_COLOR (2^24) .. VTE_RGB_COLOR + 16Mi - 1 (2^25 - 1):
+ *   Colors set by SGR truecolor extension (38/48;2;red;green;blue)
+ *   These are direct RGB values.
+ */
+#define VTE_LEGACY_COLORS_OFFSET	512
 #define VTE_LEGACY_COLOR_SET_SIZE	8
+#define VTE_LEGACY_FULL_COLOR_SET_SIZE	16
 #define VTE_COLOR_PLAIN_OFFSET		0
 #define VTE_COLOR_BRIGHT_OFFSET		8
 #define VTE_COLOR_DIM_OFFSET		16
-/* More color defines in ring.h */
+#define VTE_RGB_COLOR			(1 << 24)
+/* More color defines in vterowdata.h */
 
 #define VTE_SCROLLBACK_INIT		512
 #define VTE_SATURATION_MAX		10000
@@ -223,19 +246,14 @@ struct _VteTerminalPrivate {
 		long insert_delta;	/* insertion offset */
 		VteCell defaults;	/* default characteristics
 					   for insertion of any new
-					   characters; colors not yet
-					   adjusted for bold/dim/standout */
+					   characters */
 		VteCell color_defaults;	/* original defaults
 					   plus the current
-					   fore/back already adjusted for
-					   bold/dim/standout */
+					   fore/back */
 		VteCell fill_defaults;	/* original defaults
 					   plus the current
-					   fore/back already adjusted for
-					   bold/dim/standout with no
+					   fore/back with no
 					   character data */
-		gboolean fg_sgr_extended, bg_sgr_extended;	/* whether fg/bg were set by
-								   256 color sequences */
 		gboolean alternate_charset;
 		gboolean status_line;
 		GString *status_line_contents;
diff --git a/src/vte.c b/src/vte.c
index 63bae83..27a9fa7 100644
--- a/src/vte.c
+++ b/src/vte.c
@@ -319,6 +319,10 @@ G_DEFINE_TYPE(VteTerminal, vte_terminal, GTK_TYPE_WIDGET)
 #endif
 #endif /* GTK 3.0 */
 
+/* Indexes in the "palette" color array for the dim colors.
+ * Only the first %VTE_LEGACY_COLOR_SET_SIZE colors have dim versions.  */
+static const guchar corresponding_dim_index[] = {16,88,28,100,18,90,30,102};
+
 static void
 vte_g_array_fill(GArray *array, gconstpointer item, guint final_size)
 {
@@ -371,8 +375,6 @@ _vte_terminal_set_default_attributes(VteTerminal *terminal)
 	screen->defaults = basic_cell.cell;
 	screen->color_defaults = screen->defaults;
 	screen->fill_defaults = screen->defaults;
-	screen->fg_sgr_extended = FALSE;
-	screen->bg_sgr_extended = FALSE;
 }
 
 /* Cause certain cells to be repainted. */
@@ -6294,6 +6296,23 @@ vte_terminal_copy_cb(GtkClipboard *clipboard, GtkSelectionData *data,
 	}
 }
 
+/* Convert the internal color code (either index or RGB, see vte-private.h) into RGB. */
+static void
+vte_terminal_get_rgb_from_index(const VteTerminal *terminal, guint index, PangoColor *color)
+{
+	if (index >= VTE_LEGACY_COLORS_OFFSET && index < VTE_LEGACY_COLORS_OFFSET + VTE_LEGACY_FULL_COLOR_SET_SIZE)
+		index -= VTE_LEGACY_COLORS_OFFSET;
+	if (index < VTE_PALETTE_SIZE) {
+		memcpy(color, &terminal->pvt->palette[index], sizeof(PangoColor));
+	} else if (index & VTE_RGB_COLOR) {
+		color->red = ((index >> 16) & 0xFF) * 257;
+		color->green = ((index >> 8) & 0xFF) * 257;
+		color->blue = (index & 0xFF) * 257;
+	} else {
+		g_assert_not_reached();
+	}
+}
+
 /**
  * VteSelectionFunc:
  * @terminal: terminal in which the cell is.
@@ -6362,7 +6381,7 @@ vte_terminal_get_text_range_maybe_wrapped(VteTerminal *terminal,
 	const VteCell *pcell = NULL;
 	GString *string;
 	struct _VteCharAttributes attr;
-	PangoColor fore, back, *palette;
+	PangoColor fore, back;
 
 	if (!is_selected)
 		is_selected = always_selected;
@@ -6375,7 +6394,6 @@ vte_terminal_get_text_range_maybe_wrapped(VteTerminal *terminal,
 	string = g_string_new(NULL);
 	memset(&attr, 0, sizeof(attr));
 
-	palette = terminal->pvt->palette;
 	col = start_col;
 	for (row = start_row; row < end_row + 1; row++, col = 0) {
 		const VteRowData *row_data = _vte_terminal_find_row_data (terminal, row);
@@ -6395,8 +6413,8 @@ vte_terminal_get_text_range_maybe_wrapped(VteTerminal *terminal,
 				 * the selection. */
 				if (!pcell->attr.fragment && is_selected(terminal, col, row, data)) {
 					/* Store the attributes of this character. */
-					fore = palette[pcell->attr.fore];
-					back = palette[pcell->attr.back];
+					vte_terminal_get_rgb_from_index(terminal, pcell->attr.fore, &fore);
+					vte_terminal_get_rgb_from_index(terminal, pcell->attr.back, &back);
 					attr.fore.red = fore.red;
 					attr.fore.green = fore.green;
 					attr.fore.blue = fore.blue;
@@ -9401,6 +9419,29 @@ vte_terminal_determine_colors_internal(VteTerminal *terminal,
 			back = VTE_DEF_FG;
 	}
 
+	/* Handle bold by using set bold color or brightening */
+	if (cell->attr.bold) {
+		if (fore == VTE_DEF_FG)
+			fore = VTE_BOLD_FG;
+		else if (fore >= VTE_LEGACY_COLORS_OFFSET && fore < VTE_LEGACY_COLORS_OFFSET + VTE_LEGACY_COLOR_SET_SIZE) {
+			fore += VTE_COLOR_BRIGHT_OFFSET;
+		}
+	}
+
+	/* Handle half similarly */
+	if (cell->attr.half) {
+		if (fore == VTE_DEF_FG)
+			fore = VTE_DIM_FG;
+		else if (fore >= VTE_LEGACY_COLORS_OFFSET && fore < VTE_LEGACY_COLORS_OFFSET + VTE_LEGACY_COLOR_SET_SIZE)
+			fore = corresponding_dim_index[fore - VTE_LEGACY_COLORS_OFFSET];
+	}
+
+	/* And standout */
+	if (cell->attr.standout) {
+		if (fore >= VTE_LEGACY_COLORS_OFFSET && back < VTE_LEGACY_COLORS_OFFSET + VTE_LEGACY_COLOR_SET_SIZE)
+			back += VTE_COLOR_BRIGHT_OFFSET;
+	}
+
 	/* Reverse cell? */
 	if (cell->attr.reverse) {
 		swap (&fore, &back);
@@ -9521,18 +9562,22 @@ vte_terminal_draw_graphic(VteTerminal *terminal, vteunistr c,
         double adjust;
         cairo_t *cr = _vte_draw_get_context (terminal->pvt->draw);
 
+        PangoColor fg, bg;
+        vte_terminal_get_rgb_from_index(terminal, fore, &fg);
+        vte_terminal_get_rgb_from_index(terminal, back, &bg);
+
         width = column_width * columns;
 
 	if ((back != VTE_DEF_BG) || draw_default_bg) {
 		vte_terminal_fill_rectangle(terminal,
-					    &terminal->pvt->palette[back],
+					    &bg,
 					    x, y, width, row_height);
 	}
 
         cairo_save (cr);
 
         cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
-        _vte_draw_set_source_color_alpha (terminal->pvt->draw, &terminal->pvt->palette[fore], VTE_DRAW_OPAQUE);
+        _vte_draw_set_source_color_alpha (terminal->pvt->draw, &fg, VTE_DRAW_OPAQUE);
 
         // FIXME wtf!?
         x += terminal->pvt->inner_border.left;
@@ -10014,9 +10059,9 @@ vte_terminal_draw_graphic(VteTerminal *terminal, vteunistr c,
 
                 /* Now take the inside out */
                 cairo_set_source_rgba (cr,
-                                       terminal->pvt->palette[back].red / 65535.,
-                                       terminal->pvt->palette[back].green / 65535.,
-                                       terminal->pvt->palette[back].blue / 65535.,
+                                       bg.red / 65535.,
+                                       bg.green / 65535.,
+                                       bg.blue / 65535.,
                                        1.);
                 cairo_set_line_width(cr, inner_line_width);
                 cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER);
@@ -10171,9 +10216,9 @@ vte_terminal_draw_graphic(VteTerminal *terminal, vteunistr c,
         case 0x2592: /* medium shade */
         case 0x2593: /* dark shade */
                 cairo_set_source_rgba (cr,
-                                       terminal->pvt->palette[fore].red / 65535.,
-                                       terminal->pvt->palette[fore].green / 65535.,
-                                       terminal->pvt->palette[fore].blue / 65535.,
+                                       fg.red / 65535.,
+                                       fg.green / 65535.,
+                                       fg.blue / 65535.,
                                        (c - 0x2590) / 4.);
                 cairo_rectangle(cr, x, y, width, row_height);
                 cairo_fill (cr);
@@ -10278,7 +10323,7 @@ vte_terminal_draw_cells(VteTerminal *terminal,
 {
 	int i, x, y, ascent;
 	gint columns = 0;
-	PangoColor *fg, *bg, *defbg;
+	PangoColor fg, bg, *defbg;
 
 	g_assert(n > 0);
 	_VTE_DEBUG_IF(VTE_DEBUG_CELLS) {
@@ -10296,8 +10341,8 @@ vte_terminal_draw_cells(VteTerminal *terminal,
 	}
 
 	bold = bold && terminal->pvt->allow_bold;
-	fg = &terminal->pvt->palette[fore];
-	bg = &terminal->pvt->palette[back];
+	vte_terminal_get_rgb_from_index(terminal, fore, &fg);
+	vte_terminal_get_rgb_from_index(terminal, back, &bg);
 	defbg = &terminal->pvt->palette[VTE_DEF_BG];
 	ascent = terminal->char_ascent;
 
@@ -10312,20 +10357,20 @@ vte_terminal_draw_cells(VteTerminal *terminal,
 			items[i].y += terminal->pvt->inner_border.top;
 			columns += items[i].columns;
 		}
-		if (clear && (draw_default_bg || bg != defbg)) {
+		if (clear && (draw_default_bg || back != VTE_DEF_BG)) {
 			gint bold_offset = _vte_draw_has_bold(terminal->pvt->draw,
 									VTE_DRAW_BOLD) ? 0 : bold;
 			_vte_draw_fill_rectangle(terminal->pvt->draw,
 					x + terminal->pvt->inner_border.left,
                                         y + terminal->pvt->inner_border.top,
 					columns * column_width + bold_offset, row_height,
-					bg, VTE_DRAW_OPAQUE);
+					&bg, VTE_DRAW_OPAQUE);
 		}
 	} while (i < n);
 
 	_vte_draw_text(terminal->pvt->draw,
 			items, n,
-			fg, VTE_DRAW_OPAQUE,
+			&fg, VTE_DRAW_OPAQUE,
 			_vte_draw_get_style(bold, italic));
 
 	for (i = 0; i < n; i++) {
@@ -10345,7 +10390,7 @@ vte_terminal_draw_cells(VteTerminal *terminal,
 			}
 			if (underline) {
 				vte_terminal_draw_line(terminal,
-						&terminal->pvt->palette[fore],
+						&fg,
 						x,
 						y + terminal->pvt->underline_position,
 						x + (columns * column_width) - 1,
@@ -10353,7 +10398,7 @@ vte_terminal_draw_cells(VteTerminal *terminal,
 			}
 			if (strikethrough) {
 				vte_terminal_draw_line(terminal,
-						&terminal->pvt->palette[fore],
+						&fg,
 						x,
 						y + terminal->pvt->strikethrough_position,
 						x + (columns * column_width) - 1,
@@ -10361,7 +10406,7 @@ vte_terminal_draw_cells(VteTerminal *terminal,
 			}
 			if (hilite) {
 				vte_terminal_draw_line(terminal,
-						&terminal->pvt->palette[fore],
+						&fg,
 						x,
 						y + row_height - 1,
 						x + (columns * column_width) - 1,
@@ -10369,7 +10414,7 @@ vte_terminal_draw_cells(VteTerminal *terminal,
 			}
 			if (boxed) {
 				vte_terminal_draw_rectangle(terminal,
-						&terminal->pvt->palette[fore],
+						&fg,
 						x, y,
 						MAX(0, (columns * column_width)),
 						MAX(0, row_height));
@@ -10378,44 +10423,6 @@ vte_terminal_draw_cells(VteTerminal *terminal,
 	}
 }
 
-/* Try to map a PangoColor to a palette entry and return its index. */
-static guint
-_vte_terminal_map_pango_color(VteTerminal *terminal, PangoColor *color)
-{
-	long distance[G_N_ELEMENTS(terminal->pvt->palette)];
-	guint i, ret;
-
-	/* Calculate a "distance" value.  Could stand to be improved a bit. */
-	for (i = 0; i < G_N_ELEMENTS(distance); i++) {
-		const PangoColor *entry = &terminal->pvt->palette[i];
-		distance[i] = 0;
-		distance[i] += ((entry->red >> 8) - (color->red >> 8)) *
-			       ((entry->red >> 8) - (color->red >> 8));
-		distance[i] += ((entry->blue >> 8) - (color->blue >> 8)) *
-			       ((entry->blue >> 8) - (color->blue >> 8));
-		distance[i] += ((entry->green >> 8) - (color->green >> 8)) *
-			       ((entry->green >> 8) - (color->green >> 8));
-	}
-
-	/* Find the index of the minimum value. */
-	ret = 0;
-	for (i = 1; i < G_N_ELEMENTS(distance); i++) {
-		if (distance[i] < distance[ret]) {
-			ret = i;
-		}
-	}
-
-	_vte_debug_print(VTE_DEBUG_UPDATES,
-			"mapped PangoColor(%04x,%04x,%04x) to "
-			"palette entry (%04x,%04x,%04x)\n",
-			color->red, color->green, color->blue,
-			terminal->pvt->palette[ret].red,
-			terminal->pvt->palette[ret].green,
-			terminal->pvt->palette[ret].blue);
-
-	return ret;
-}
-
 /* FIXME: we don't have a way to tell GTK+ what the default text attributes
  * should be, so for now at least it's assuming white-on-black is the norm and
  * is using "black-on-white" to signify "inverse".  Pick up on that state and
@@ -10504,8 +10511,10 @@ _vte_terminal_apply_pango_attr(VteTerminal *terminal, PangoAttribute *attr,
 	case PANGO_ATTR_FOREGROUND:
 	case PANGO_ATTR_BACKGROUND:
 		attrcolor = (PangoAttrColor*) attr;
-		ival = _vte_terminal_map_pango_color(terminal,
-						     &attrcolor->color);
+		ival = VTE_RGB_COLOR |
+		       ((attrcolor->color.red & 0xFF00) << 8) |
+		       ((attrcolor->color.green & 0xFF00)) |
+		       ((attrcolor->color.blue & 0xFF00) >> 8);
 		for (i = attr->start_index;
 		     i < attr->end_index && i < n_cells;
 		     i++) {
@@ -10720,15 +10729,17 @@ vte_terminal_draw_rows(VteTerminal *terminal,
 					j += cell ? cell->attr.columns : 1;
 				}
 				if (back != VTE_DEF_BG) {
+					PangoColor bg;
 					gint bold_offset = _vte_draw_has_bold(terminal->pvt->draw,
 											VTE_DRAW_BOLD) ? 0 : bold;
+					vte_terminal_get_rgb_from_index(terminal, back, &bg);
 					_vte_draw_fill_rectangle (
 							terminal->pvt->draw,
 							x + i * column_width,
 							y,
 							(j - i) * column_width + bold_offset,
 							row_height,
-							&terminal->pvt->palette[back], VTE_DRAW_OPAQUE);
+							&bg, VTE_DRAW_OPAQUE);
 				}
 				/* We'll need to continue at the first cell which didn't
 				 * match the first one in this set. */
@@ -10747,12 +10758,14 @@ vte_terminal_draw_rows(VteTerminal *terminal,
 				}
 				vte_terminal_determine_colors(terminal, NULL, selected, &fore, &back);
 				if (back != VTE_DEF_BG) {
+					PangoColor bg;
+					vte_terminal_get_rgb_from_index(terminal, back, &bg);
 					_vte_draw_fill_rectangle (terminal->pvt->draw,
 								  x + i *column_width,
 								  y,
 								  (j - i)  * column_width,
 								  row_height,
-								  &terminal->pvt->palette[back], VTE_DRAW_OPAQUE);
+								  &bg, VTE_DRAW_OPAQUE);
 				}
 				i = j;
 			} while (i < end_column);
@@ -11078,6 +11091,7 @@ vte_terminal_paint_cursor(VteTerminal *terminal)
 	int row, drow, col;
 	long width, height, delta, cursor_width;
 	guint fore, back;
+	PangoColor bg;
 	int x, y;
 	gboolean blink, selected, focus;
 
@@ -11127,6 +11141,7 @@ vte_terminal_paint_cursor(VteTerminal *terminal)
 	selected = vte_cell_is_selected(terminal, col, drow, NULL);
 
 	vte_terminal_determine_cursor_colors(terminal, cell, selected, &fore, &back);
+	vte_terminal_get_rgb_from_index(terminal, back, &bg);
 
 	x = item.x;
 	y = item.y;
@@ -11139,7 +11154,7 @@ vte_terminal_paint_cursor(VteTerminal *terminal)
                         stem_width = (int) (((float) height) * terminal->pvt->cursor_aspect_ratio + 0.5);
                         stem_width = CLAMP (stem_width, VTE_LINE_WIDTH, cursor_width);
 		 	
-			vte_terminal_fill_rectangle(terminal, &terminal->pvt->palette[back],
+			vte_terminal_fill_rectangle(terminal, &bg,
 						     x, y, stem_width, height);
 			break;
                 }
@@ -11152,7 +11167,7 @@ vte_terminal_paint_cursor(VteTerminal *terminal)
                         line_height = (int) (((float) height) * terminal->pvt->cursor_aspect_ratio + 0.5);
                         line_height = CLAMP (line_height, VTE_LINE_WIDTH, height);
 
-			vte_terminal_fill_rectangle(terminal, &terminal->pvt->palette[back],
+			vte_terminal_fill_rectangle(terminal, &bg,
 						     x, y + height - line_height,
 						     cursor_width, line_height);
 			break;
@@ -11163,7 +11178,7 @@ vte_terminal_paint_cursor(VteTerminal *terminal)
 			if (focus) {
 				/* just reverse the character under the cursor */
 				vte_terminal_fill_rectangle (terminal,
-							     &terminal->pvt->palette[back],
+							     &bg,
 							     x, y,
 							     cursor_width, height);
 
@@ -11205,7 +11220,7 @@ vte_terminal_paint_cursor(VteTerminal *terminal)
 				/* draw a box around the character */
 
 				vte_terminal_draw_rectangle (terminal,
-							    &terminal->pvt->palette[back],
+							    &bg,
 							     x - VTE_LINE_WIDTH,
 							     y - VTE_LINE_WIDTH,
 							     cursor_width + 2*VTE_LINE_WIDTH,
diff --git a/src/vterowdata.h b/src/vterowdata.h
index 4150095..95e7463 100644
--- a/src/vterowdata.h
+++ b/src/vterowdata.h
@@ -45,32 +45,32 @@ G_BEGIN_DECLS
  */
 
 typedef struct _VteCellAttr {
-	guint32 fragment: 1;	/* A continuation cell. */
-	guint32 columns: 4;	/* Number of visible columns
+	guint64 fragment: 1;	/* A continuation cell. */
+	guint64 columns: 4;	/* Number of visible columns
 				   (as determined by g_unicode_iswide(c)).
 				   Also abused for tabs; bug 353610
 				   Keep at least 4 for tabs to work
 				   */
-	guint32 bold: 1;
-	guint32 italic: 1;
-	guint32 fore: 9;	/* Index into color palette */
-	guint32 back: 9;	/* Index into color palette. */
+	guint64 bold: 1;
+	guint64 italic: 1;
+	guint64 fore: 25;	/* Index into color palette, or direct RGB, */
+	guint64 back: 25;	/* see vte-private.h */
 
-	guint32 standout: 1;
-	guint32 underline: 1;
-	guint32 strikethrough: 1;
+	guint64 standout: 1;
+	guint64 underline: 1;
+	guint64 strikethrough: 1;
 
-	guint32 reverse: 1;
-	guint32 blink: 1;
-	guint32 half: 1;
+	guint64 reverse: 1;
+	guint64 blink: 1;
+	guint64 half: 1;
 
-	guint32 invisible: 1;
+	guint64 invisible: 1;
 } VteCellAttr;
-G_STATIC_ASSERT (sizeof (VteCellAttr) == 4);
+G_STATIC_ASSERT (sizeof (VteCellAttr) == 8);
 
 typedef union _VteIntCellAttr {
 	VteCellAttr s;
-	guint32 i;
+	guint64 i;
 } VteIntCellAttr;
 G_STATIC_ASSERT (sizeof (VteCellAttr) == sizeof (VteIntCellAttr));
 
@@ -78,17 +78,17 @@ G_STATIC_ASSERT (sizeof (VteCellAttr) == sizeof (VteIntCellAttr));
  * VteCell: A single cell's data
  */
 
-typedef struct _VteCell {
+typedef struct __attribute__((__packed__)) _VteCell {
 	vteunistr c;
 	VteCellAttr attr;
 } VteCell;
-G_STATIC_ASSERT (sizeof (VteCell) == 8);
+G_STATIC_ASSERT (sizeof (VteCell) == 12);
 
 typedef union _VteIntCell {
 	VteCell cell;
-	struct {
+	struct __attribute__((__packed__)) {
 		guint32 c;
-		guint32 attr;
+		guint64 attr;
 	} i;
 } VteIntCell;
 G_STATIC_ASSERT (sizeof (VteCell) == sizeof (VteIntCell));
diff --git a/src/vteseq.c b/src/vteseq.c
index 38f9ba1..eae386a 100644
--- a/src/vteseq.c
+++ b/src/vteseq.c
@@ -493,53 +493,6 @@ vte_sequence_handler_set_mode_internal(VteTerminal *terminal,
 }
 
 
-/* Indexes in the "palette" color array for the dim colors.
- * Only the first %VTE_LEGACY_COLOR_SET_SIZE colors have dim versions.  */
-static const guchar corresponding_dim_index[] = {16,88,28,100,18,90,30,102};
-
-static void
-vte_adjust_colors(VteTerminal *terminal)
-{
-	guint fore, back;
-
-	fore = terminal->pvt->screen->defaults.attr.fore;
-	back = terminal->pvt->screen->defaults.attr.back;
-
-	/* Handle bold by using set bold color or brightening */
-	if (terminal->pvt->screen->defaults.attr.bold) {
-		if (fore == VTE_DEF_FG) {
-			fore = VTE_BOLD_FG;
-		} else if (!terminal->pvt->screen->fg_sgr_extended
-			  && fore < VTE_LEGACY_COLOR_SET_SIZE) {
-				fore += VTE_COLOR_BRIGHT_OFFSET;
-		}
-	}
-
-	/* Handle half similarly */
-	if (terminal->pvt->screen->defaults.attr.half) {
-		if (fore == VTE_DEF_FG) {
-			fore = VTE_DIM_FG;
-		} else if (!terminal->pvt->screen->fg_sgr_extended
-			  && fore < VTE_LEGACY_COLOR_SET_SIZE) {
-			fore = corresponding_dim_index[fore];
-		}
-	}
-
-	/* And standout */
-	if (terminal->pvt->screen->defaults.attr.standout) {
-		if (!terminal->pvt->screen->bg_sgr_extended
-		  && back < VTE_LEGACY_COLOR_SET_SIZE) {
-			back += VTE_COLOR_BRIGHT_OFFSET;
-		}
-	}
-
-	/* Save the adjusted colors. */
-	terminal->pvt->screen->color_defaults.attr.fore = fore;
-	terminal->pvt->screen->color_defaults.attr.back = back;
-	terminal->pvt->screen->fill_defaults.attr.fore = fore;
-	terminal->pvt->screen->fill_defaults.attr.back = back;
-}
-
 /*
  * Sequence handling boilerplate
  */
@@ -2456,33 +2409,66 @@ vte_sequence_handler_character_attributes (VteTerminal *terminal, GValueArray *p
 		case 35:
 		case 36:
 		case 37:
-			terminal->pvt->screen->fg_sgr_extended = FALSE;
-			terminal->pvt->screen->defaults.attr.fore = param - 30;
+			terminal->pvt->screen->defaults.attr.fore = VTE_LEGACY_COLORS_OFFSET + param - 30;
 			break;
 		case 38:
+		case 48:
 		{
-			/* The format looks like: ^[[38;5;COLORNUMBERm,
-			   so look for COLORNUMBER here. */
-			if ((i + 2) < params->n_values){
-				GValue *value1, *value2;
-				long param1, param2;
+			/* The format looks like: ^[[38;5;COLORNUMBERm or ^[[38;2;RED;GREEN;BLUEm
+			   so look for the parameters here. */
+			if ((i + 1) < params->n_values) {
+				GValue *value1, *value2, *value3, *value4;
+				long param1, param2, param3, param4;
 				value1 = g_value_array_get_nth(params, i + 1);
-				value2 = g_value_array_get_nth(params, i + 2);
-				if (G_UNLIKELY (!(G_VALUE_HOLDS_LONG(value1) && G_VALUE_HOLDS_LONG(value2))))
+				if (G_UNLIKELY (!G_VALUE_HOLDS_LONG(value1)))
 					break;
 				param1 = g_value_get_long(value1);
-				param2 = g_value_get_long(value2);
-				if (G_LIKELY (param1 == 5 && param2 >= 0 && param2 < 256)) {
-					terminal->pvt->screen->fg_sgr_extended = TRUE;
-					terminal->pvt->screen->defaults.attr.fore = param2;
+				switch (param1) {
+				case 2:
+					if (G_UNLIKELY ((i + 4) >= params->n_values))
+						break;
+					value2 = g_value_array_get_nth(params, i + 2);
+					value3 = g_value_array_get_nth(params, i + 3);
+					value4 = g_value_array_get_nth(params, i + 4);
+					if (G_UNLIKELY (!(G_VALUE_HOLDS_LONG(value2) && G_VALUE_HOLDS_LONG(value3) && G_VALUE_HOLDS_LONG(value4))))
+						break;
+					param2 = g_value_get_long(value2);
+					param3 = g_value_get_long(value3);
+					param4 = g_value_get_long(value4);
+					if (G_LIKELY (param2 >= 0 && param2 < 256 && param3 >= 0 && param3 < 256 && param4 >= 0 && param4 < 256)) {
+						long value = (1 << 24) | (param2 << 16) | (param3 << 8) | param4;
+						if (param == 38) {
+							terminal->pvt->screen->defaults.attr.fore = value;
+						} else {
+							terminal->pvt->screen->defaults.attr.back = value;
+						}
+					}
+					i += 4;
+					break;
+				case 5:
+					if (G_UNLIKELY ((i + 2) >= params->n_values))
+						break;
+					value2 = g_value_array_get_nth(params, i + 2);
+					if (G_UNLIKELY (!G_VALUE_HOLDS_LONG(value2)))
+						break;
+					param2 = g_value_get_long(value2);
+					if (G_LIKELY (param2 >= 0 && param2 < 256)) {
+						if (param == 38) {
+							terminal->pvt->screen->defaults.attr.fore = param2;
+						} else {
+							terminal->pvt->screen->defaults.attr.back = param2;
+						}
+					}
+					i += 2;
+					break;
+				default:
+					break;
 				}
-				i += 2;
 			}
 			break;
 		}
 		case 39:
 			/* default foreground */
-			terminal->pvt->screen->fg_sgr_extended = FALSE;
 			terminal->pvt->screen->defaults.attr.fore = VTE_DEF_FG;
 			break;
 		case 40:
@@ -2493,33 +2479,11 @@ vte_sequence_handler_character_attributes (VteTerminal *terminal, GValueArray *p
 		case 45:
 		case 46:
 		case 47:
-			terminal->pvt->screen->bg_sgr_extended = FALSE;
-			terminal->pvt->screen->defaults.attr.back = param - 40;
-			break;
-		case 48:
-		{
-			/* The format looks like: ^[[48;5;COLORNUMBERm,
-			   so look for COLORNUMBER here. */
-			if ((i + 2) < params->n_values){
-				GValue *value1, *value2;
-				long param1, param2;
-				value1 = g_value_array_get_nth(params, i + 1);
-				value2 = g_value_array_get_nth(params, i + 2);
-				if (G_UNLIKELY (!(G_VALUE_HOLDS_LONG(value1) && G_VALUE_HOLDS_LONG(value2))))
-					break;
-				param1 = g_value_get_long(value1);
-				param2 = g_value_get_long(value2);
-				if (G_LIKELY (param1 == 5 && param2 >= 0 && param2 < 256)) {
-					terminal->pvt->screen->bg_sgr_extended = TRUE;
-					terminal->pvt->screen->defaults.attr.back = param2;
-				}
-				i += 2;
-			}
+			terminal->pvt->screen->defaults.attr.back = VTE_LEGACY_COLORS_OFFSET + param - 40;
 			break;
-		}
+	     /* case 48: was handled above at 38 to avoid code duplication */
 		case 49:
 			/* default background */
-			terminal->pvt->screen->bg_sgr_extended = FALSE;
 			terminal->pvt->screen->defaults.attr.back = VTE_DEF_BG;
 			break;
 		case 90:
@@ -2530,8 +2494,7 @@ vte_sequence_handler_character_attributes (VteTerminal *terminal, GValueArray *p
 		case 95:
 		case 96:
 		case 97:
-			terminal->pvt->screen->fg_sgr_extended = FALSE;
-			terminal->pvt->screen->defaults.attr.fore = param - 90 + VTE_COLOR_BRIGHT_OFFSET;
+			terminal->pvt->screen->defaults.attr.fore = VTE_LEGACY_COLORS_OFFSET + param - 90 + VTE_COLOR_BRIGHT_OFFSET;
 			break;
 		case 100:
 		case 101:
@@ -2541,8 +2504,7 @@ vte_sequence_handler_character_attributes (VteTerminal *terminal, GValueArray *p
 		case 105:
 		case 106:
 		case 107:
-			terminal->pvt->screen->bg_sgr_extended = FALSE;
-			terminal->pvt->screen->defaults.attr.back = param - 100 + VTE_COLOR_BRIGHT_OFFSET;
+			terminal->pvt->screen->defaults.attr.back = VTE_LEGACY_COLORS_OFFSET + param - 100 + VTE_COLOR_BRIGHT_OFFSET;
 			break;
 		}
 	}
@@ -2551,7 +2513,14 @@ vte_sequence_handler_character_attributes (VteTerminal *terminal, GValueArray *p
 		_vte_terminal_set_default_attributes(terminal);
 	}
 	/* Save the new colors. */
-	vte_adjust_colors(terminal);
+	terminal->pvt->screen->color_defaults.attr.fore =
+		terminal->pvt->screen->defaults.attr.fore;
+	terminal->pvt->screen->color_defaults.attr.back =
+		terminal->pvt->screen->defaults.attr.back;
+	terminal->pvt->screen->fill_defaults.attr.fore =
+		terminal->pvt->screen->defaults.attr.fore;
+	terminal->pvt->screen->fill_defaults.attr.back =
+		terminal->pvt->screen->defaults.attr.back;
 }
 
 /* Move the cursor to the given column, 1-based. */
