WINGs buttons and labels now have text
[wmaker-crm.git] / WINGs / wmisc.c
blob041365480b9f09338139e9d12b79734d4de9d553
2 #include "WINGsP.h"
4 #include <ctype.h>
6 static void curve_rectangle(cairo_t *cr,
7 double x0, double y0, double rect_width, double rect_height,
8 double radius)
10 double x1,y1;
12 x1=x0+rect_width;
13 y1=y0+rect_height;
14 if (!rect_width || !rect_height)
15 return;
16 if (rect_width/2<radius) {
17 if (rect_height/2<radius) {
18 cairo_move_to (cr, x0, (y0 + y1)/2);
19 cairo_curve_to (cr, x0 ,y0, x0, y0, (x0 + x1)/2, y0);
20 cairo_curve_to (cr, x1, y0, x1, y0, x1, (y0 + y1)/2);
21 cairo_curve_to (cr, x1, y1, x1, y1, (x1 + x0)/2, y1);
22 cairo_curve_to (cr, x0, y1, x0, y1, x0, (y0 + y1)/2);
23 } else {
24 cairo_move_to (cr, x0, y0 + radius);
25 cairo_curve_to (cr, x0 ,y0, x0, y0, (x0 + x1)/2, y0);
26 cairo_curve_to (cr, x1, y0, x1, y0, x1, y0 + radius);
27 cairo_line_to (cr, x1 , y1 - radius);
28 cairo_curve_to (cr, x1, y1, x1, y1, (x1 + x0)/2, y1);
29 cairo_curve_to (cr, x0, y1, x0, y1, x0, y1- radius);
31 } else {
32 if (rect_height/2<radius) {
33 cairo_move_to (cr, x0, (y0 + y1)/2);
34 cairo_curve_to (cr, x0 , y0, x0 , y0, x0 + radius, y0);
35 cairo_line_to (cr, x1 - radius, y0);
36 cairo_curve_to (cr, x1, y0, x1, y0, x1, (y0 + y1)/2);
37 cairo_curve_to (cr, x1, y1, x1, y1, x1 - radius, y1);
38 cairo_line_to (cr, x0 + radius, y1);
39 cairo_curve_to (cr, x0, y1, x0, y1, x0, (y0 + y1)/2);
40 } else {
41 cairo_move_to (cr, x0, y0 + radius);
42 cairo_curve_to (cr, x0 , y0, x0 , y0, x0 + radius, y0);
43 cairo_line_to (cr, x1 - radius, y0);
44 cairo_curve_to (cr, x1, y0, x1, y0, x1, y0 + radius);
45 cairo_line_to (cr, x1 , y1 - radius);
46 cairo_curve_to (cr, x1, y1, x1, y1, x1 - radius, y1);
47 cairo_line_to (cr, x0 + radius, y1);
48 cairo_curve_to (cr, x0, y1, x0, y1, x0, y1- radius);
51 cairo_close_path (cr);
54 void W_DrawButtonRelief(W_Screen *scr, cairo_t *cairo, int x, int y, unsigned int width, unsigned int height,
55 WMReliefType relief)
57 unsigned char border[4]= {0x00, 0x00, 0x00, 0x70};
58 //unsigned char color1[4]= {0x8c, 0xb1, 0xbc, 0xff};
59 //unsigned char color2[4]= {0xcb, 0xf3, 0xff, 0xff};
60 unsigned char color1[4]= {0x0, 0x0, 0x0, 0xff};
61 unsigned char color2[4]= {0xcf, 0xcf, 0xcf, 0xff};
62 unsigned char scolor1[4]= {0xff, 0xff, 0xff, 0xe5};
63 unsigned char scolor2[4]= {0xff, 0xff, 0xff, 0x70};
64 cairo_pattern_t *shine;
65 cairo_pattern_t *base;
67 x+=1;
68 y+=1;
69 width-=2;
70 height-=2;
72 cairo_save(cairo);
74 shine= cairo_pattern_create_linear(0, 0, 0, height*2/5);
75 cairo_pattern_add_color_stop_rgba(shine, 0,
76 scolor1[0]/255.0, scolor1[1]/255.0, scolor1[2]/255.0,
77 scolor1[3]/255.0);
78 cairo_pattern_add_color_stop_rgba(shine, 1,
79 scolor2[0]/255.0, scolor2[1]/255.0, scolor2[2]/255.0,
80 scolor2[3]/255.0);
82 base= cairo_pattern_create_linear(0, 0, 0, height-1);
83 cairo_pattern_add_color_stop_rgba(base, 0,
84 color1[0]/255.0, color1[1]/255.0, color1[2]/255.0,
85 color1[3]/255.0);
86 cairo_pattern_add_color_stop_rgba(base, 1,
87 color2[0]/255.0, color2[1]/255.0, color2[2]/255.0,
88 color2[3]/255.0);
91 curve_rectangle(cairo, x, y, width-1, height-1, height*2/3);
92 cairo_set_source(cairo, base);
93 cairo_fill_preserve(cairo);
94 cairo_clip(cairo);
96 curve_rectangle(cairo, x, y, width-1, height*2/5, width);
97 cairo_set_source(cairo, shine);
98 cairo_fill(cairo);
100 curve_rectangle(cairo, x, y, width-1, height-1, height*2/3);
101 cairo_set_source_rgba(cairo, border[0]/255.0, border[1]/255.0, border[2]/255.0, border[3]/255.0);
102 cairo_set_line_width(cairo, 2.0);
103 cairo_stroke(cairo);
105 cairo_pattern_destroy(shine);
106 cairo_pattern_destroy(base);
108 cairo_restore(cairo);
111 void W_DrawRelief(W_Screen *scr, cairo_t *cairo, int x, int y, unsigned int width, unsigned int height,
112 WMReliefType relief)
114 WMColorSpec b;
115 WMColorSpec w;
116 WMColorSpec d;
117 WMColorSpec l;
119 switch (relief) {
120 case WRSimple:
121 WMColorSpecSet(cairo, &b);
122 cairo_rectangle(cairo, x, y, width-1, height-1);
123 cairo_stroke(cairo);
124 return;
126 case WRRaised:
127 b= WMBlackColorSpec();
128 w= WMWhiteColorSpec();
129 d= WMDarkGrayColorSpec();
130 l= WMGrayColorSpec();
131 break;
133 case WRSunken:
134 l= WMBlackColorSpec();
135 b= WMWhiteColorSpec();
136 w= WMDarkGrayColorSpec();
137 d= WMGrayColorSpec();
138 break;
140 case WRPushed:
141 l= w= WMBlackColorSpec();
142 d= b= WMWhiteColorSpec();
143 break;
145 case WRRidge:
146 l= b= WMDarkGrayColorSpec();
147 d= w= WMWhiteColorSpec();
148 break;
150 case WRGroove:
151 w= d= WMDarkGrayColorSpec();
152 l= b= WMWhiteColorSpec();
153 break;
155 default:
156 return;
158 /* top left */
159 WMColorSpecSet(cairo, &w);
160 cairo_move_to(cairo, x, y);
161 cairo_line_to(cairo, x+width-1, y);
162 cairo_stroke(cairo);
163 if (width > 2 && relief != WRRaised && relief!=WRPushed) {
164 WMColorSpecSet(cairo, &l);
165 cairo_move_to(cairo, x+1, y+1);
166 cairo_line_to(cairo, x+width-3, y+1);
167 cairo_stroke(cairo);
170 WMColorSpecSet(cairo, &w);
171 cairo_move_to(cairo, x, y);
172 cairo_line_to(cairo, x, y+height-1);
173 cairo_stroke(cairo);
174 if (height > 2 && relief != WRRaised && relief!=WRPushed) {
175 WMColorSpecSet(cairo, &l);
176 cairo_move_to(cairo, x+1, y+1);
177 cairo_line_to(cairo, x+1, y+height-3);
178 cairo_stroke(cairo);
181 /* bottom right */
182 WMColorSpecSet(cairo, &b);
183 cairo_move_to(cairo, x, y+height-1);
184 cairo_line_to(cairo, x+width-1, y+height-1);
185 cairo_stroke(cairo);
186 if (width > 2 && relief!=WRPushed) {
187 WMColorSpecSet(cairo, &d);
188 cairo_move_to(cairo, x+1, y+height-2);
189 cairo_line_to(cairo, x+width-2, y+height-2);
190 cairo_stroke(cairo);
193 WMColorSpecSet(cairo, &b);
194 cairo_move_to(cairo, x+width-1, y);
195 cairo_line_to(cairo, x+width-1, y+height-1);
196 cairo_stroke(cairo);
197 if (height > 2 && relief!=WRPushed) {
198 WMColorSpecSet(cairo, &d);
199 cairo_move_to(cairo, x+width-2, y+1);
200 cairo_line_to(cairo, x+width-2, y+height-2);
201 cairo_stroke(cairo);
205 static int findNextWord(const char *text, int limit)
207 int pos, len;
209 //XXX this is broken
210 len = strcspn(text, " \t\n\r");
211 pos = len + strspn(text + len, " \t\n\r");
212 if (pos > limit)
213 pos = limit;
215 return pos;
218 static int fitText(const char *text, WMFont * font, int width, int wrap)
220 int i, w, beforecrlf, word1, word2;
222 /* text length before first cr/lf */
223 beforecrlf = strcspn(text, "\n");
225 if (!wrap || beforecrlf == 0)
226 return beforecrlf;
228 //XXX w = WMWidthOfString(font, text, beforecrlf);
229 if (w <= width) {
230 /* text up to first crlf fits */
231 return beforecrlf;
234 word1 = 0;
235 while (1) {
236 word2 = word1 + findNextWord(text + word1, beforecrlf - word1);
237 if (word2 >= beforecrlf)
238 break;
239 //XXXw = WMWidthOfString(font, text, word2);
240 if (w > width)
241 break;
242 word1 = word2;
245 for (i = word1; i < word2; i++) {
246 //XXXw = WMWidthOfString(font, text, i);
247 if (w > width) {
248 break;
252 /* keep words complete if possible */
253 if (!isspace(text[i]) && word1 > 0) {
254 i = word1;
255 } else if (isspace(text[i]) && i < beforecrlf) {
256 /* keep space on current row, so new row has next word in column 1 */
257 i++;
260 return i;
263 #ifdef OLD_CODE
264 static int fitText(char *text, WMFont * font, int width, int wrap)
266 int i, j;
267 int w;
269 if (text[0] == 0)
270 return 0;
272 i = 0;
273 if (wrap) {
274 if (text[0] == '\n')
275 return 0;
277 do {
278 i++;
279 w = WMWidthOfString(font, text, i);
280 } while (w < width && text[i] != '\n' && text[i] != 0);
282 if (text[i] == '\n')
283 return i;
285 /* keep words complete */
286 if (!isspace(text[i])) {
287 j = i;
288 while (j > 1 && !isspace(text[j]) && text[j] != 0)
289 j--;
290 if (j > 1)
291 i = j;
293 } else {
294 i = strcspn(text, "\n");
296 return i;
298 #endif
300 int W_GetTextHeight(cairo_t *cairo, WMFont *font, const char *text, int width, int wrap)
302 const char *ptr = text;
303 int count;
304 int length = strlen(text);
305 int h;
306 int fheight = WMFontHeight(font);
308 h = 0;
309 while (length > 0) {
310 count = fitText(ptr, font, width, wrap);
312 h += fheight;
314 if (isspace(ptr[count]))
315 count++;
317 ptr += count;
318 length -= count;
320 return h;
323 void W_PaintText(cairo_t *cairo, WMFont *font, int x, int y,
324 int width, WMAlignment alignment, WMColorSpec *color,
325 int wrap, const char *text)
327 const char *ptr = text;
328 int length= strlen(ptr);
329 int line_width;
330 int line_x= 0;
331 int count;
332 int fheight = WMFontHeight(font);
334 //line_x= x + (width - WMWidthOfString(font, ptr))/2;
335 //WMDrawString(cairo, color, font, line_x, y, ptr);
336 //return;
338 while (length > 0) {
339 count = fitText(ptr, font, width, wrap);
341 line_width = WMWidthOfString(font, text);
343 if (alignment == WALeft)
344 line_x = x;
345 else if (alignment == WARight)
346 line_x = x + width - line_width;
347 else
348 line_x = x + (width - line_width) / 2;
350 WMDrawString(cairo, color, font, line_x, y, ptr);
352 if (wrap && ptr[count] != '\n')
353 y += fheight;
355 while (ptr[count] && ptr[count] == '\n') {
356 y += fheight;
357 count++;
360 ptr += count;
361 length -= count;
365 void W_PaintTextAndImage(W_Screen *screen, cairo_t *cairo, W_View *view, int wrap, WMColorSpec *textColor, W_Font *font,
366 WMReliefType relief, const char *text,
367 WMAlignment alignment, WMImage *image,
368 WMImagePosition position, WMColorSpec *backColor, int ofs)
370 int ix, iy;
371 int x, y, w, h;
373 cairo_save(cairo);
375 if (backColor)
377 cairo_rectangle(cairo, 0, 0, view->size.width, view->size.height);
378 WMColorSpecSet(cairo, backColor);
379 cairo_fill(cairo);
381 if (relief == WRFlat) {
382 x = 0;
383 y = 0;
384 w = view->size.width;
385 h = view->size.height;
386 } else {
387 x = 1;
388 y = 1;
389 w = view->size.width - 3;
390 h = view->size.height - 3;
393 /* calc. image alignment */
394 if (position != WIPNoImage && image != NULL) {
395 switch (position) {
396 case WIPOverlaps:
397 case WIPImageOnly:
398 ix = (view->size.width - WMGetImageWidth(image)) / 2;
399 iy = (view->size.height - WMGetImageHeight(image)) / 2;
401 x = 2;
402 y = 0;
404 break;
406 case WIPLeft:
407 ix = x;
408 iy = y + (h - WMGetImageHeight(image)) / 2;
409 x = x + WMGetImageWidth(image) + 5;
410 y = 0;
411 w -= WMGetImageWidth(image) + 5;
412 break;
414 case WIPRight:
415 ix = view->size.width - WMGetImageWidth(image) - x;
416 iy = y + (h - WMGetImageHeight(image)) / 2;
417 w -= WMGetImageWidth(image) + 5;
418 break;
420 case WIPBelow:
421 ix = (view->size.width - WMGetImageWidth(image)) / 2;
422 iy = h - WMGetImageHeight(image);
423 y = 0;
424 h -= WMGetImageHeight(image);
425 break;
427 default:
428 case WIPAbove:
429 ix = (view->size.width - WMGetImageWidth(image)) / 2;
430 iy = y;
431 y = WMGetImageHeight(image);
432 h -= WMGetImageHeight(image);
433 break;
436 ix += ofs;
437 iy += ofs;
439 //XXX XSetClipOrigin(screen->display, screen->clipGC, ix, iy);
440 //XXX XSetClipMask(screen->display, screen->clipGC, image->mask);
441 /*XXX
442 if (image->depth==1)
443 XCopyPlane(screen->display, image->pixmap, d, screen->clipGC,
444 0, 0, WMGetImageWidth(image), WMGetImageHeight(image), ix, iy, 1);
445 else
446 XCopyArea(screen->display, image->pixmap, d, screen->clipGC,
447 0, 0, WMGetImageWidth(image), WMGetImageHeight(image), ix, iy);
451 /* draw text */
452 if (position != WIPImageOnly && text!=NULL) {
453 int textHeight;
455 textHeight = W_GetTextHeight(cairo, font, text, w-8, wrap);
456 W_PaintText(cairo, font, x+ofs+4, y+ofs + (h-textHeight)/2, w-8,
457 alignment, textColor, wrap, text);
460 /* draw relief */
461 W_DrawRelief(screen, cairo, 0, 0, view->size.width, view->size.height, relief);
464 WMPoint wmkpoint(int x, int y)
466 WMPoint point;
468 point.x = x;
469 point.y = y;
471 return point;
474 WMSize wmksize(unsigned int width, unsigned int height)
476 WMSize size;
478 size.width = width;
479 size.height = height;
481 return size;
484 WMRect wmkrect(int x, int y, unsigned int width, unsigned int height)
486 WMRect rect;
488 rect.pos.x = x;
489 rect.pos.y = y;
490 rect.size.width = width;
491 rect.size.height = height;
493 return rect;