static const char *get_ansi_color(THEME_REC *theme, const char *str,
				  int *fg_ret, int *bg_ret, int *flags_ret)
{
	static char ansitab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
	const char *start;
	int fg, bg, flags, num, i;
	unsigned int num2;

	if (*str != '[')
		return str;
	start = str++;

	fg = fg_ret == NULL || *fg_ret < 0 ? theme->default_color : *fg_ret;
	bg = bg_ret == NULL || *bg_ret < 0 ? -1 : *bg_ret;
	flags = flags_ret == NULL ? 0 : *flags_ret;

	num = 0;
	for (;; str++) {
		if (*str == '\0') return start;

		if (i_isdigit(*str)) {
			num = num*10 + (*str-'0');
			continue;
		}

		if (*str != ';' && *str != 'm')
			return start;

		switch (num) {
		case 0:
			/* reset colors and attributes back to default */
			fg = theme->default_color;
			bg = -1;
			flags &= ~(GUI_PRINT_FLAG_INDENT |
				   GUI_PRINT_FLAG_BOLD | GUI_PRINT_FLAG_ITALIC | GUI_PRINT_FLAG_UNDERLINE |
				   GUI_PRINT_FLAG_BLINK | GUI_PRINT_FLAG_REVERSE |
				   GUI_PRINT_FLAG_COLOR_24_FG | GUI_PRINT_FLAG_COLOR_24_BG);
			break;
		case 1:
			/* hilight */
			flags |= GUI_PRINT_FLAG_BOLD;
			break;
		case 22:
			/* normal */
			flags &= ~GUI_PRINT_FLAG_BOLD;
			break;
		case 3:
			/* italic */
			flags |= GUI_PRINT_FLAG_ITALIC;
			break;
		case 23:
			/* not italic */
			flags &= ~GUI_PRINT_FLAG_ITALIC;
			break;
		case 4:
			/* underline */
			flags |= GUI_PRINT_FLAG_UNDERLINE;
			break;
		case 24:
			/* not underline */
			flags &= ~GUI_PRINT_FLAG_UNDERLINE;
			break;
		case 5:
			/* blink */
			flags |= GUI_PRINT_FLAG_BLINK;
			break;
		case 25:
			/* steady */
			flags &= ~GUI_PRINT_FLAG_BLINK;
			break;
		case 7:
			/* reverse */
			flags |= GUI_PRINT_FLAG_REVERSE;
			break;
		case 27:
			/* positive */
			flags &= ~GUI_PRINT_FLAG_REVERSE;
			break;
		case 39:
			/* reset fg */
			flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
			fg = theme->default_color;
			break;
		case 49:
			/* reset bg */
			bg = -1;
			flags &= ~(GUI_PRINT_FLAG_COLOR_24_BG | GUI_PRINT_FLAG_INDENT);
			break;
		case 38:
		case 48:
			/* ANSI indexed color or RGB color */
			if (*str != ';') break;
			str++;
			for (num2 = 0; i_isdigit(*str); str++)
				num2 = num2*10 + (*str-'0');
			if (*str == '\0') return start;

			switch (num2) {
			case 2:
				/* RGB */
				num2 = 0;

				for (i = 0; i < 3; ++i) {
					num2 <<= 8;

					if (*str != ';' && *str != ':') {
						i = -1;
						break;
					}
					str++;
					for (; i_isdigit(*str); str++)
						num2 = (num2&~0xff) |
							(((num2&0xff) * 10 + (*str-'0'))&0xff);

					if (*str == '\0') return start;
				}

				if (i == -1) break;
#ifdef TERM_TRUECOLOR
				if (num == 38) {
					flags |= GUI_PRINT_FLAG_COLOR_24_FG;
					fg = num2;
				} else if (num == 48) {
					flags |= GUI_PRINT_FLAG_COLOR_24_BG;
					bg = num2;
				}
#else /* !TERM_TRUECOLOR */
				if (num == 38) {
					flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
					fg = color_24bit_256_int(num2);
				} else if (num == 48) {
					flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
					bg = color_24bit_256_int(num2);
				}
#endif

				break;
			case 5:
				/* indexed */
				if (*str != ';') break;
				str++;
				for (num2 = 0; i_isdigit(*str); str++)
					num2 = num2*10 + (*str-'0');
				if (*str == '\0') return start;

				if (num == 38) {
					flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
					fg = num2;
				} else if (num == 48) {
					flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
					bg = num2;
				}

				break;
			}
			break;
		default:
			if (num >= 30 && num <= 37) {
				flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
				fg = ansitab[num-30];
			} else if (num >= 40 && num <= 47) {
				flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
				bg = ansitab[num-40];
			} else if (num >= 90 && num <= 97) {
				flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
				fg = 8 + ansitab[num-90];
			} else if (num >= 100 && num <= 107) {
				flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
				bg = 8 + ansitab[num-100];
			}
			break;
		}
		num = 0;

		if (*str == 'm') {
			if (fg_ret != NULL) *fg_ret = fg;
			if (bg_ret != NULL) *bg_ret = bg;
			if (flags_ret != NULL) *flags_ret = flags;

			str++;
			break;
		}
	}

	return str;
}