14 #include <pango/pango.h>
15 #include <pango/pangoft2.h>
20 #define MAXTEXT (1 << 20)
21 #define MAXLINE ((MAXTEXT) >> 4)
24 #define CTRLKEY(x) ((x) - 96)
26 #define CR(a) (((a) >> 16) & 0xff)
27 #define CG(a) (((a) >> 8) & 0xff)
28 #define CB(a) ((a) & 0xff)
29 #define COLORMERGE(f, b, c) ((b) + (((f) - (b)) * (c) >> 8u))
31 static PangoContext
*context
;
32 static PangoFontMap
*fontmap
;
33 static FT_Bitmap
*bitmap
;
34 static char name
[128]; /* sura name */
35 static int pcols
= 1; /* bitmap width */
36 static int prows
= 1; /* bitmap height */
38 static char text
[MAXTEXT
];
39 static char *pos
= text
;
43 static int lnpos
[MAXLINE
]; /* line offsets as reported by txtwin_line() */
44 static int lnrow
[MAXLINE
]; /* line row in the layout */
47 static void draw(int sr
)
51 int nr
= MIN(prows
- sr
, fb_rows());
52 int nc
= MIN(pcols
, fb_cols());
53 for (r
= 0; r
< nr
; r
++) {
54 for (c
= 0; c
< nc
; c
++) {
55 int v
= bitmap
->buffer
[(sr
+ r
) * bitmap
->pitch
+ c
];
56 int r
= COLORMERGE(CR(COLOR_FG
), CR(COLOR_BG
), v
);
57 int g
= COLORMERGE(CG(COLOR_FG
), CG(COLOR_BG
), v
);
58 int b
= COLORMERGE(CB(COLOR_FG
), CB(COLOR_BG
), v
);
59 buf
[c
] = FB_VAL(r
, g
, b
);
61 fb_set(r
, 0, buf
, pcols
);
65 static FT_Bitmap
*create_bitmap(int pcols
, int prows
)
67 FT_Bitmap
*bitmap
= g_slice_new(FT_Bitmap
);
68 bitmap
->width
= pcols
;
69 bitmap
->pitch
= (bitmap
->width
+ 3) & ~3;
71 bitmap
->buffer
= g_malloc(bitmap
->pitch
* bitmap
->rows
);
72 bitmap
->num_grays
= 256;
73 bitmap
->pixel_mode
= ft_pixel_mode_grays
;
74 memset(bitmap
->buffer
, 0, bitmap
->pitch
* bitmap
->rows
);
78 static void destroy_bitmap(FT_Bitmap
*bitmap
)
80 g_free(bitmap
->buffer
);
81 g_slice_free(FT_Bitmap
, bitmap
);
84 static PangoLayout
*make_layout(PangoContext
*context
, char *text
, double size
)
86 static PangoFontDescription
*font_description
;
87 PangoLayout
*layout
= pango_layout_new(context
);
88 pango_layout_set_markup(layout
, text
, -1);
89 pango_layout_set_wrap(layout
, PANGO_WRAP_WORD_CHAR
);
90 pango_layout_set_width(layout
, fb_cols() << 10);
91 pango_layout_set_height(layout
, -1);
92 pango_layout_set_alignment(layout
, PANGO_ALIGN_RIGHT
);
93 pango_layout_set_font_description(layout
, font_description
);
94 pango_font_description_free(font_description
);
98 static void do_output(PangoContext
*context
, char *text
)
103 pango_context_set_language(context
, pango_language_get_default());
104 pango_context_set_base_dir(context
, PANGO_DIRECTION_RTL
);
105 layout
= make_layout(context
, text
, -1);
106 pango_layout_get_pixel_extents(layout
, NULL
, &rect
);
107 pango_ft2_render_layout(bitmap
, layout
, 0, 0);
108 pcols
= MAX(pcols
, MAX(rect
.x
+ rect
.width
,
109 PANGO_PIXELS(pango_layout_get_width(layout
))));
110 prows
= MAX(rect
.y
+ rect
.height
,
111 PANGO_PIXELS(pango_layout_get_height(layout
)));
112 for (i
= 0; i
< nlnpos
; i
++) {
113 pango_layout_index_to_pos(layout
, lnpos
[i
], &rect
);
114 lnrow
[i
] = PANGO_PIXELS(rect
.y
);
116 g_object_unref(layout
);
119 static int readkey(void)
122 if (read(0, &b
, 1) <= 0)
124 return (unsigned char) b
;
127 void txtwin_append(char *s
, char *font
)
129 snprintf(pos
, MAXTEXT
- (pos
- text
),
130 "<span font=\"%s\">%s</span>", font
, s
);
131 pos
= strchr(pos
, '\0');
132 pos_off
+= strlen(s
);
135 void txtwin_line(void)
137 lnpos
[nlnpos
++] = pos_off
;
140 static int getcount(int def
)
142 int result
= count
? count
: def
;
147 static void printinfo(void)
150 printf("CNOOR \t\t\t %d%% \t\t\t %s \x1b[K", head
* 100 / prows
, name
);
154 static void scroll(int h
)
157 head
= MAX(0, MIN(h
, prows
- fb_rows()));
160 static void scroll_rel(int diff
)
162 head
= MAX(0, MIN(head
+ diff
, prows
- fb_rows()));
165 void txtwin_loop(void)
167 int step
= fb_rows() / PAGESTEPS
;
168 struct termios oldtermios
, termios
;
170 tcgetattr(0, &termios
);
171 oldtermios
= termios
;
173 tcsetattr(0, TCSAFLUSH
, &termios
);
174 bitmap
= create_bitmap(pcols
, prows
);
175 do_output(context
, text
);
176 destroy_bitmap(bitmap
);
177 bitmap
= create_bitmap(pcols
, prows
);
178 do_output(context
, text
);
180 while ((c
= readkey()) >= 0) {
186 tcsetattr(0, 0, &oldtermios
);
190 count
= count
* 10 + c
- '0';
194 scroll_rel(+step
* getcount(1));
197 scroll_rel(-step
* getcount(1));
201 scroll_rel(+fb_rows() * getcount(1) - step
);
205 scroll_rel(-fb_rows() * getcount(1) + step
);
211 if (i
> 0 && i
< nlnpos
)
212 scroll(MIN(lnrow
[i
- 1], prows
- fb_rows()));
214 scroll(prows
- fb_rows());
218 scroll(prows
* getcount(0) / 100);
224 mark
[readkey()] = head
;
232 /* no need to redraw */
239 void txtwin_init(char *sura
)
241 setlocale(LC_ALL
, "");
242 g_set_prgname("cnoor");
243 fontmap
= pango_ft2_font_map_new();
244 pango_ft2_font_map_set_resolution(PANGO_FT2_FONT_MAP(fontmap
), DPI
, DPI
);
245 context
= pango_font_map_create_context(PANGO_FONT_MAP(fontmap
));
249 if (FBM_BPP(fb_mode()) != sizeof(fbval_t
)) {
250 fprintf(stderr
, "cnoor: fbval_t doesn't match fb depth\n");
253 printf("\x1b[2J\x1b[H\x1b[?25l");
255 memset(mark
, 0xff, sizeof(mark
));
258 void txtwin_free(void)
261 destroy_bitmap(bitmap
);
262 g_object_unref(context
);
263 g_object_unref(fontmap
);
264 printf("\x1b[?25h\n");