@@ -7,7 +7,8 @@ program fortty |
| 7 | 7 | use terminal_mod |
| 8 | 8 | use parser_mod |
| 9 | 9 | use screen_mod |
| 10 | | - use cell_mod |
| 10 | + use cell_mod, only: cell_t, set_palette_color, set_default_colors |
| 11 | + use config_mod |
| 11 | 12 | implicit none |
| 12 | 13 | |
| 13 | 14 | type(window_t) :: win |
@@ -17,40 +18,56 @@ program fortty |
| 17 | 18 | type(parser_t) :: parser |
| 18 | 19 | type(screen_t), pointer :: scr |
| 19 | 20 | type(cell_t) :: cell |
| 21 | + type(config_t) :: cfg |
| 20 | 22 | integer :: win_width, win_height |
| 21 | 23 | integer :: prev_width, prev_height |
| 22 | 24 | integer :: term_rows, term_cols |
| 23 | 25 | integer :: new_rows, new_cols |
| 24 | 26 | character(len=256) :: font_path, fallback_path |
| 25 | 27 | character(len=4096) :: pty_buffer |
| 28 | + character(len=256) :: response_buf |
| 26 | 29 | integer :: nbytes, i, row, col, scroll_offset, sb_offset, screen_row |
| 27 | | - real :: x, y, r, g, b |
| 30 | + integer :: response_len |
| 31 | + real :: x, y, r, g, b, bg_r, bg_g, bg_b |
| 28 | 32 | type(cell_t), allocatable :: sb_line(:) |
| 29 | | - integer, parameter :: CELL_WIDTH = 10 ! Approximate char width |
| 30 | | - integer, parameter :: CELL_HEIGHT = 18 ! Approximate line height |
| 33 | + integer :: cell_width, cell_height ! From font metrics |
| 31 | 34 | |
| 32 | | - ! Window dimensions |
| 33 | | - win_width = 800 |
| 34 | | - win_height = 600 |
| 35 | + ! Load configuration (uses defaults if no config file found) |
| 36 | + cfg = config_load('') |
| 37 | + |
| 38 | + ! Apply color palette from config |
| 39 | + call set_default_colors(cfg%fg_color, cfg%bg_color) |
| 40 | + do i = 0, 15 |
| 41 | + call set_palette_color(i, cfg%palette(i)) |
| 42 | + end do |
| 43 | + |
| 44 | + ! Window dimensions from config |
| 45 | + win_width = cfg%window_width |
| 46 | + win_height = cfg%window_height |
| 35 | 47 | |
| 36 | 48 | ! Create window with OpenGL context |
| 37 | 49 | win = window_create(win_width, win_height, "fortty") |
| 38 | 50 | |
| 39 | | - ! Font path - use fontconfig for portable discovery, with fallbacks |
| 40 | | - font_path = font_find_monospace() |
| 41 | | - if (len_trim(font_path) == 0) then |
| 42 | | - ! Fontconfig not available or failed - try common system locations |
| 43 | | - font_path = "/usr/share/fonts/TTF/DejaVuSansMono.ttf" |
| 51 | + ! Font path - use config if specified, otherwise fontconfig, then fallbacks |
| 52 | + if (len_trim(cfg%font_path) > 0) then |
| 53 | + font_path = cfg%font_path |
| 54 | + print *, "Using configured font: ", trim(font_path) |
| 44 | 55 | else |
| 45 | | - print *, "Using system monospace font: ", trim(font_path) |
| 56 | + font_path = font_find_monospace() |
| 57 | + if (len_trim(font_path) == 0) then |
| 58 | + ! Fontconfig not available or failed - try common system locations |
| 59 | + font_path = "/usr/share/fonts/TTF/DejaVuSansMono.ttf" |
| 60 | + else |
| 61 | + print *, "Using system monospace font: ", trim(font_path) |
| 62 | + end if |
| 46 | 63 | end if |
| 47 | 64 | |
| 48 | | - ! Create renderer with font |
| 49 | | - ren = renderer_create(trim(font_path), 16) |
| 65 | + ! Create renderer with font (using font size from config) |
| 66 | + ren = renderer_create(trim(font_path), cfg%font_size) |
| 50 | 67 | if (.not. ren%initialized) then |
| 51 | 68 | print *, "Warning: Could not load font, trying alternate path..." |
| 52 | 69 | font_path = "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf" |
| 53 | | - ren = renderer_create(trim(font_path), 16) |
| 70 | + ren = renderer_create(trim(font_path), cfg%font_size) |
| 54 | 71 | end if |
| 55 | 72 | |
| 56 | 73 | if (.not. ren%initialized) then |
@@ -65,11 +82,21 @@ program fortty |
| 65 | 82 | ren%atlas%font => ren%font |
| 66 | 83 | |
| 67 | 84 | ! Load fallback font for missing glyphs (icons, symbols, etc.) |
| 68 | | - ! First try fontconfig to find a font with Nerd Font icons (e.g., eza uses these) |
| 69 | | - ! Try Nerd Font-specific devicons first (U+E5FF), then common icons (U+F07B) |
| 70 | | - fallback_path = font_find_for_codepoint(int(z'E5FF')) ! Nerd Font devicon |
| 71 | | - if (len_trim(fallback_path) > 0) then |
| 72 | | - call renderer_load_fallback_font(ren, trim(fallback_path)) |
| 85 | + ! Use config fallback if specified, otherwise auto-detect via fontconfig |
| 86 | + if (len_trim(cfg%font_fallback) > 0) then |
| 87 | + call renderer_load_fallback_font(ren, trim(cfg%font_fallback)) |
| 88 | + if (ren%font%has_fallback) then |
| 89 | + print *, "Using configured fallback font: ", trim(cfg%font_fallback) |
| 90 | + end if |
| 91 | + end if |
| 92 | + |
| 93 | + ! If no configured fallback or it failed, try fontconfig auto-detection |
| 94 | + if (.not. ren%font%has_fallback) then |
| 95 | + ! Try Nerd Font-specific devicons first (U+E5FF), then common icons (U+F07B) |
| 96 | + fallback_path = font_find_for_codepoint(int(z'E5FF')) ! Nerd Font devicon |
| 97 | + if (len_trim(fallback_path) > 0) then |
| 98 | + call renderer_load_fallback_font(ren, trim(fallback_path)) |
| 99 | + end if |
| 73 | 100 | end if |
| 74 | 101 | if (.not. ren%font%has_fallback) then |
| 75 | 102 | fallback_path = font_find_for_codepoint(int(z'E0A0')) ! Powerline branch symbol |
@@ -112,9 +139,16 @@ program fortty |
| 112 | 139 | ! Set up projection matrix |
| 113 | 140 | call renderer_set_projection(ren, win_width, win_height) |
| 114 | 141 | |
| 142 | + ! Get cell dimensions from font metrics |
| 143 | + cell_width = ren%font%cell_width |
| 144 | + cell_height = ren%font%cell_height |
| 145 | + if (cell_width < 1) cell_width = 10 ! Fallback |
| 146 | + if (cell_height < 1) cell_height = 18 ! Fallback |
| 147 | + print *, "Font cell size:", cell_width, "x", cell_height |
| 148 | + |
| 115 | 149 | ! Calculate terminal dimensions based on font metrics |
| 116 | | - term_cols = win_width / CELL_WIDTH |
| 117 | | - term_rows = win_height / CELL_HEIGHT |
| 150 | + term_cols = win_width / cell_width |
| 151 | + term_rows = win_height / cell_height |
| 118 | 152 | prev_width = win_width |
| 119 | 153 | prev_height = win_height |
| 120 | 154 | |
@@ -149,8 +183,8 @@ program fortty |
| 149 | 183 | call renderer_set_projection(ren, win_width, win_height) |
| 150 | 184 | |
| 151 | 185 | ! Calculate new terminal size and notify PTY and terminal |
| 152 | | - new_cols = win_width / CELL_WIDTH |
| 153 | | - new_rows = win_height / CELL_HEIGHT |
| 186 | + new_cols = win_width / cell_width |
| 187 | + new_rows = win_height / cell_height |
| 154 | 188 | if (new_cols /= term_cols .or. new_rows /= term_rows) then |
| 155 | 189 | term_cols = new_cols |
| 156 | 190 | term_rows = new_rows |
@@ -168,8 +202,19 @@ program fortty |
| 168 | 202 | end do |
| 169 | 203 | end if |
| 170 | 204 | |
| 171 | | - ! Clear screen with dark gray background |
| 172 | | - call glClearColor(0.1, 0.1, 0.12, 1.0) |
| 205 | + ! Check for terminal responses (DA1, DSR, etc.) and send to PTY |
| 206 | + if (terminal_has_response(term)) then |
| 207 | + call terminal_get_response(term, response_buf, response_len) |
| 208 | + if (response_len > 0) then |
| 209 | + call pty_write(pty, response_buf, response_len) |
| 210 | + end if |
| 211 | + end if |
| 212 | + |
| 213 | + ! Clear screen with background color from config |
| 214 | + bg_r = real(cfg%bg_color%r) / 255.0 |
| 215 | + bg_g = real(cfg%bg_color%g) / 255.0 |
| 216 | + bg_b = real(cfg%bg_color%b) / 255.0 |
| 217 | + call glClearColor(bg_r, bg_g, bg_b, 1.0) |
| 173 | 218 | call glClear(GL_COLOR_BUFFER_BIT) |
| 174 | 219 | |
| 175 | 220 | ! Render terminal buffer |
@@ -187,7 +232,7 @@ program fortty |
| 187 | 232 | end if |
| 188 | 233 | |
| 189 | 234 | do row = 1, scr%rows |
| 190 | | - y = real(row) * CELL_HEIGHT |
| 235 | + y = real(row) * cell_height |
| 191 | 236 | |
| 192 | 237 | ! Determine if this row shows scrollback or screen content |
| 193 | 238 | sb_offset = scroll_offset - row + 1 |
@@ -198,7 +243,7 @@ program fortty |
| 198 | 243 | do col = 1, min(term_cols, scr%cols) |
| 199 | 244 | cell = sb_line(col) |
| 200 | 245 | if (cell%codepoint /= 32) then |
| 201 | | - x = real(col - 1) * CELL_WIDTH |
| 246 | + x = real(col - 1) * cell_width |
| 202 | 247 | r = real(cell%fg%r) / 255.0 |
| 203 | 248 | g = real(cell%fg%g) / 255.0 |
| 204 | 249 | b = real(cell%fg%b) / 255.0 |
@@ -212,7 +257,7 @@ program fortty |
| 212 | 257 | do col = 1, scr%cols |
| 213 | 258 | cell = screen_get_cell(scr, screen_row, col) |
| 214 | 259 | if (cell%codepoint /= 32) then |
| 215 | | - x = real(col - 1) * CELL_WIDTH |
| 260 | + x = real(col - 1) * cell_width |
| 216 | 261 | r = real(cell%fg%r) / 255.0 |
| 217 | 262 | g = real(cell%fg%g) / 255.0 |
| 218 | 263 | b = real(cell%fg%b) / 255.0 |
@@ -225,8 +270,8 @@ program fortty |
| 225 | 270 | |
| 226 | 271 | ! Draw cursor if visible (only when not scrolled back) |
| 227 | 272 | if (term%cursor%visible .and. scroll_offset == 0) then |
| 228 | | - x = real(term%cursor%col - 1) * CELL_WIDTH |
| 229 | | - y = real(term%cursor%row) * CELL_HEIGHT |
| 273 | + x = real(term%cursor%col - 1) * cell_width |
| 274 | + y = real(term%cursor%row) * cell_height |
| 230 | 275 | ! Draw cursor as underscore character for visibility |
| 231 | 276 | call renderer_draw_char(ren, x, y, 95, 0.7, 0.7, 0.7, 1.0) ! '_' |
| 232 | 277 | end if |