private int handleSGRAttribute(String[] bits, int pos) throws NumberFormatException {
			int code = Integer.parseInt(bits[pos]);
			if (code >= 30 && code < 50) {
				/* Color codes */
				Object attributeName =
					(code < 40) ? StyleConstants.Foreground : StyleConstants.Background;
				int colorCode = code % 10;
				if (colorCode < 8) {
					/* 30-37, 40-47 - basic color */
					attributes.addAttribute(attributeName, BASIC_COLORS[colorCode]);
					return 1;
				}
				else if (colorCode == 8) {
					/* 38, 48 - extended color */
					if (pos + 1 >= bits.length) {
						/* Not enough extra parameters */
						return 1;
					}

					int colorType = Integer.parseInt(bits[pos + 1]);
					if (colorType == 5 && pos + 2 < bits.length) {
						int color = Integer.parseInt(bits[pos + 2]);
						attributes.addAttribute(attributeName, get256Color(color));
						return 3;
					}
					else if (colorType == 2 && pos + 4 < bits.length) {
						int r = Integer.parseInt(bits[pos + 2]);
						int g = Integer.parseInt(bits[pos + 3]);
						int b = Integer.parseInt(bits[pos + 4]);
						attributes.addAttribute(attributeName, ColorUtils.getColor(r, g, b));
						return 5;
					}
					return 1;
				}
				else if (colorCode == 9) {
					/* 39, 49 - default color */
					attributes.removeAttribute(attributeName);
					return 1;
				}
			}

			switch (code) {
				case 0:
					/* Reset parameters to default */
					attributes.removeAttributes(attributes);
					attributes.addAttributes(defaultAttributes);
					break;
				case 1:
					/* Bold or strong colour */
					StyleConstants.setBold(attributes, true);
					break;
				case 2:
					/* Faint or dim colour */
					StyleConstants.setBold(attributes, false);
					break;
				case 3:
					/* Italic */
					StyleConstants.setItalic(attributes, true);
					break;
				case 4:
					/* Underline */
					StyleConstants.setUnderline(attributes, true);
					break;
				case 5:
					/* Slow blink */
					break;
				case 6:
					/* Fast blink */
					break;
				case 7:
					/* Inverse video */
					// The default fg/bg may be different, and we don't have a way to know them.
					// Therefore, simply swapping the fg/bg won't work because if either of them
					// is unset, the result will not be predictable.
					// Instead, just ignore this directive.
					break;
				case 8:
					/* Conceal/hide */
					break;
				case 9:
					/* Strikethrough */
					StyleConstants.setStrikeThrough(attributes, true);
					break;
				/* 10-19: Various fonts, unsupported */
				case 20:
					/* Blackletter font */
					break;
				case 21:
					/* Double underline/not bold */
					StyleConstants.setUnderline(attributes, true);
					break;
				case 22:
					/* Normal intensity */
					StyleConstants.setBold(attributes, false);
					break;
				case 23:
					/* Not italic nor blackletter */
					StyleConstants.setItalic(attributes, false);
					break;
				case 24:
					/* Not underlined */
					StyleConstants.setUnderline(attributes, false);
					break;
				case 25:
					/* Not blinking */
					break;
				case 26:
					/* Proportional spacing */
					break;
				case 27:
					/* Not reversed video */
					break;
				case 28:
					/* Not hidden nor concealed */
					break;
				case 29:
					/* Not strikethrough */
					StyleConstants.setStrikeThrough(attributes, false);
					break;
			}
			return 1;
		}
Handler for a Select Graphic Rendition attribute (for CSI final byte {@code m})

<p>
See <a href=
"https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters">ANSI
escape codes</a> on Wikipedia.

@param bits the semicolon-separated pieces, named {@code n} in the Wikipedia page.
@param pos the index in {@code bits} to process next
@return the number of {@code bits} processed (to advance before the next invocation)
@throws NumberFormatException if a bit to process was not an integer (in decimal).
Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/AnsiRenderer.java