comparison foosdk/sdk/foobar2000/shared/text_drawing.cpp @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
comparison
equal deleted inserted replaced
0:e9bb126753e7 1:20d02a178406
1 #include "shared.h"
2
3
4 static bool is_rect_null(const RECT * r)
5 {
6 return r->right <= r->left || r->bottom <= r->top;
7 }
8
9 UINT SHARED_EXPORT uGetTextHeight(HDC dc)
10 {
11 TEXTMETRIC tm;
12 POINT pt[2];
13 GetTextMetrics(dc,&tm);
14 pt[0].x = 0;
15 pt[0].y = tm.tmHeight;
16 pt[1].x = 0;
17 pt[1].y = 0;
18 LPtoDP(dc,pt,2);
19
20 int ret = pt[0].y - pt[1].y;
21 return ret > 1 ? (unsigned)ret : 1;
22 }
23
24 static int get_text_width(HDC dc,const TCHAR * src,int len)
25 {
26 if (len<=0) return 0;
27 else
28 {
29 SIZE goatse;
30 GetTextExtentPoint32(dc,src,len,&goatse);
31 return goatse.cx;
32 }
33 }
34
35 //GetTextExtentPoint32 wrapper, removes color marks
36 static int get_text_width_color(HDC dc,const TCHAR * src,int len)
37 {
38 int ptr = 0;
39 int start = 0;
40 int rv = 0;
41 if (len<0) len = (int) _tcslen(src);
42 while(ptr<len)
43 {
44 if (src[ptr]==3)
45 {
46 rv += get_text_width(dc,src+start,ptr-start);
47 ptr++;
48 while(ptr<len && src[ptr]!=3) ptr++;
49 if (ptr<len) ptr++;
50 start = ptr;
51 }
52 else ptr++;
53 }
54 rv += get_text_width(dc,src+start,ptr-start);
55 return rv;
56 }
57
58
59 static BOOL text_out_colors(HDC dc,const TCHAR * src,int len,int pos_x,int pos_y,const RECT * clip,bool selected,DWORD default_color)
60 {
61 if (clip)
62 {
63 if (is_rect_null(clip) || clip->right<=pos_x || clip->bottom<=pos_y) return TRUE;
64 }
65 SetTextAlign(dc,TA_LEFT);
66 SetBkMode(dc,TRANSPARENT);
67 SetTextColor(dc,selected ? 0xFFFFFF - default_color : default_color);
68
69 int title_ptr = 0;
70 int textout_start = 0;
71 int position = pos_x;//item.left+BORDER;
72
73 for(;;)
74 {
75 if (title_ptr>=len || src[title_ptr]==3)
76 {
77 if (title_ptr>textout_start)
78 {
79 int width = get_text_width(dc,src+textout_start,title_ptr-textout_start);
80 ExtTextOut(dc,position,pos_y,clip ? ETO_CLIPPED : 0,clip,src+textout_start,title_ptr-textout_start,0);
81 position += width;
82 textout_start = title_ptr;
83 }
84 if (title_ptr>=len) break;
85 }
86 if (src[title_ptr]==3)
87 {
88 DWORD new_color;
89 DWORD new_inverted;
90 bool have_inverted = false;
91
92 if (src[title_ptr+1]==3) {new_color=default_color;title_ptr+=2;}
93 else
94 {
95 title_ptr++;
96 new_color = _tcstoul(src+title_ptr,0,16);
97 while(title_ptr<len && src[title_ptr]!=3)
98 {
99 if (!have_inverted && src[title_ptr-1]=='|')
100 {
101 new_inverted = _tcstoul(src+title_ptr,0,16);
102 have_inverted = true;
103 }
104 title_ptr++;
105 }
106 if (title_ptr<len) title_ptr++;
107 }
108 if (selected) new_color = have_inverted ? new_inverted : 0xFFFFFF - new_color;
109 SetTextColor(dc,new_color);
110 textout_start = title_ptr;
111 }
112 else
113 {
114 title_ptr = (int)( CharNext(src+title_ptr)-src );
115 }
116 }
117 return TRUE;
118 }
119
120 static BOOL text_out_colors_tab(HDC dc,const TCHAR * display,int display_len,const RECT * item,int border,const RECT * base_clip,bool selected,DWORD default_color,bool columns)
121 {
122 RECT clip;
123 if (base_clip)
124 IntersectRect(&clip,base_clip,item);
125 else clip = *item;
126
127 if (is_rect_null(&clip)) return TRUE;
128
129 int pos_y = item->top + (item->bottom-item->top - (int)uGetTextHeight(dc)) / 2;
130
131 int n_tabs = 0;
132 int total_width = 0;
133 {
134 int start = 0;
135 int n;
136 for(n=0;n<display_len;n++)
137 {
138 if (display[n]=='\t')
139 {
140 if (start<n) total_width += get_text_width_color(dc,display+start,n-start) + 2*border;
141 start = n+1;
142 n_tabs++;
143 }
144 }
145 if (start<display_len)
146 {
147 total_width += get_text_width_color(dc,display+start,display_len-start) + 2*border;
148 }
149 }
150
151 int tab_total = item->right - item->left;
152 if (!columns) tab_total -= total_width;
153 int ptr = display_len;
154 int tab_ptr = 0;
155 int written = 0;
156 int clip_x = item->right;
157 do
158 {
159 int ptr_end = ptr;
160 while(ptr>0 && display[ptr-1]!='\t') ptr--;
161 const TCHAR * t_string = display + ptr;
162 int t_length = ptr_end - ptr;
163 if (t_length>0)
164 {
165 int t_width = get_text_width_color(dc,t_string,t_length) + border*2;
166
167 int pos_x;
168 int pos_x_right;
169
170 if (!columns)
171 {
172 pos_x_right = item->right - MulDiv(tab_ptr,tab_total,n_tabs) - written;
173 }
174 else
175 {
176 if (tab_ptr==0) pos_x_right = item->right;
177 else pos_x_right = item->right - MulDiv(tab_ptr,tab_total,n_tabs) + t_width;
178 }
179
180 if (ptr==0)
181 {
182 pos_x = item->left;
183 }
184 else
185 {
186 pos_x = pos_x_right - t_width ;
187 if (pos_x<item->left) pos_x = item->left;
188 }
189
190 RECT t_clip = clip;
191
192 if (t_clip.right > clip_x) t_clip.right = clip_x;
193
194 text_out_colors(dc,t_string,t_length,pos_x+border,pos_y,&t_clip,selected,default_color);
195
196 if (clip_x>pos_x) clip_x = pos_x;
197
198 written += t_width;
199 }
200
201 if (ptr>0)
202 {
203 ptr--;//tab char
204 tab_ptr++;
205 }
206 }
207 while(ptr>0);
208
209 return TRUE;
210 }
211
212 extern "C" {
213
214 BOOL SHARED_EXPORT uTextOutColors(HDC dc,const char * p_text,UINT len,int x,int y,const RECT * clip,BOOL is_selected,DWORD default_color)
215 {
216 try {
217 pfc::stringcvt::string_os_from_utf8 temp(p_text);
218 return text_out_colors(dc,temp,pfc::downcast_guarded<int>(temp.length()),x,y,clip,!!is_selected,default_color);
219 } catch(...) {return FALSE;}
220 }
221
222 BOOL SHARED_EXPORT uTextOutColorsTabbed(HDC dc,const char * p_text,UINT len,const RECT * item,int border,const RECT * clip,BOOL selected,DWORD default_color,BOOL use_columns)
223 {
224 try {
225 pfc::stringcvt::string_os_from_utf8 temp(p_text);
226 return text_out_colors_tab(dc,temp,pfc::downcast_guarded<int>(temp.length()),item,border,clip,!!selected,default_color,!!use_columns);
227 } catch(...) {return FALSE;}
228 }
229
230 }