Fortran · 4947 bytes Raw Blame History
1 module cell_mod
2 implicit none
3 private
4
5 public :: color_t, cell_t
6 public :: COLOR_DEFAULT, COLOR_INDEXED, COLOR_RGB
7 public :: ATTR_BOLD, ATTR_ITALIC, ATTR_UNDERLINE, ATTR_BLINK
8 public :: ATTR_INVERSE, ATTR_HIDDEN, ATTR_STRIKETHROUGH
9 public :: default_fg, default_bg, make_cell
10 public :: color_from_index, color_from_rgb
11 public :: set_palette_color, set_default_colors
12
13 ! Color modes
14 integer, parameter :: COLOR_DEFAULT = 0
15 integer, parameter :: COLOR_INDEXED = 1
16 integer, parameter :: COLOR_RGB = 2
17
18 ! Attribute flags (can be combined with IOR)
19 integer, parameter :: ATTR_BOLD = 1
20 integer, parameter :: ATTR_ITALIC = 2
21 integer, parameter :: ATTR_UNDERLINE = 4
22 integer, parameter :: ATTR_BLINK = 8
23 integer, parameter :: ATTR_INVERSE = 16
24 integer, parameter :: ATTR_HIDDEN = 32
25 integer, parameter :: ATTR_STRIKETHROUGH = 64
26
27 type :: color_t
28 integer :: mode = COLOR_DEFAULT
29 integer :: index = 7 ! Palette index (0-255)
30 integer :: r = 255, g = 255, b = 255 ! RGB values
31 end type color_t
32
33 type :: cell_t
34 integer :: codepoint = 32 ! Unicode codepoint (32 = space)
35 type(color_t) :: fg ! Foreground color
36 type(color_t) :: bg ! Background color
37 integer :: attrs = 0 ! Attribute flags
38 integer :: width = 1 ! Display width (1 or 2 for wide chars)
39 logical :: is_continuation = .false. ! True if 2nd half of wide char
40 end type cell_t
41
42 ! Default colors (can be overridden by config)
43 type(color_t) :: default_fg = color_t(COLOR_DEFAULT, 7, 255, 255, 255)
44 type(color_t) :: default_bg = color_t(COLOR_DEFAULT, 0, 0, 0, 0)
45
46 ! Configurable 16-color palette (indexed 0-15)
47 ! Can be overridden via set_palette_color
48 type(color_t), save :: custom_palette(0:15)
49 logical, save :: palette_initialized = .false.
50
51 contains
52
53 ! Create a cell with given codepoint and current style
54 function make_cell(codepoint, fg, bg, attrs) result(c)
55 integer, intent(in) :: codepoint
56 type(color_t), intent(in) :: fg, bg
57 integer, intent(in) :: attrs
58 type(cell_t) :: c
59
60 c%codepoint = codepoint
61 c%fg = fg
62 c%bg = bg
63 c%attrs = attrs
64 end function make_cell
65
66 ! Initialize custom palette with default VGA colors
67 subroutine init_default_palette()
68 integer :: i
69 ! VGA palette RGB values
70 integer, parameter :: vga_r(0:15) = [0, 128, 0, 128, 0, 128, 0, 192, 128, 255, 0, 255, 0, 255, 0, 255]
71 integer, parameter :: vga_g(0:15) = [0, 0, 128, 128, 0, 0, 128, 192, 128, 0, 255, 255, 0, 0, 255, 255]
72 integer, parameter :: vga_b(0:15) = [0, 0, 0, 0, 128, 128, 128, 192, 128, 0, 0, 0, 255, 255, 255, 255]
73
74 do i = 0, 15
75 custom_palette(i) = color_t(COLOR_RGB, i, vga_r(i), vga_g(i), vga_b(i))
76 end do
77 palette_initialized = .true.
78 end subroutine init_default_palette
79
80 ! Set a single palette color (index 0-15)
81 subroutine set_palette_color(idx, c)
82 integer, intent(in) :: idx
83 type(color_t), intent(in) :: c
84
85 if (.not. palette_initialized) call init_default_palette()
86 if (idx >= 0 .and. idx <= 15) then
87 custom_palette(idx) = c
88 end if
89 end subroutine set_palette_color
90
91 ! Set default foreground and background colors
92 subroutine set_default_colors(fg, bg)
93 type(color_t), intent(in) :: fg, bg
94
95 default_fg = fg
96 default_bg = bg
97 end subroutine set_default_colors
98
99 ! Create color from 256-color palette index
100 function color_from_index(idx) result(c)
101 integer, intent(in) :: idx
102 type(color_t) :: c
103 integer :: r, g, b, gray
104
105 ! Initialize palette on first use if needed
106 if (.not. palette_initialized) call init_default_palette()
107
108 c%mode = COLOR_RGB
109 c%index = idx
110
111 if (idx < 0 .or. idx > 255) then
112 ! Invalid index - return white
113 c%r = 255; c%g = 255; c%b = 255
114 else if (idx < 16) then
115 ! Use custom palette for standard 16 colors
116 c = custom_palette(idx)
117 else if (idx < 232) then
118 ! 6x6x6 color cube (indices 16-231)
119 ! index = 16 + 36*r + 6*g + b where r,g,b in 0-5
120 r = (idx - 16) / 36
121 g = mod((idx - 16) / 6, 6)
122 b = mod(idx - 16, 6)
123 ! Map 0-5 to 0,95,135,175,215,255
124 if (r == 0) then; c%r = 0; else; c%r = 55 + r * 40; end if
125 if (g == 0) then; c%g = 0; else; c%g = 55 + g * 40; end if
126 if (b == 0) then; c%b = 0; else; c%b = 55 + b * 40; end if
127 else
128 ! Grayscale ramp (indices 232-255)
129 ! 24 shades from 8 to 238
130 gray = 8 + (idx - 232) * 10
131 c%r = gray; c%g = gray; c%b = gray
132 end if
133 end function color_from_index
134
135 ! Create color from RGB values
136 function color_from_rgb(r, g, b) result(c)
137 integer, intent(in) :: r, g, b
138 type(color_t) :: c
139
140 c%mode = COLOR_RGB
141 c%index = 0
142 c%r = max(0, min(255, r))
143 c%g = max(0, min(255, g))
144 c%b = max(0, min(255, b))
145 end function color_from_rgb
146
147 end module cell_mod
148