Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / wmisc.c
1
2 #include "WINGsP.h"
3
4 #include <wraster.h>
5 #include <ctype.h>
6
7 void
8 W_DrawRelief(W_Screen * scr, Drawable d, int x, int y, unsigned int width,
9              unsigned int height, WMReliefType relief)
10 {
11         W_DrawReliefWithGC(scr, d, x, y, width, height, relief,
12                            WMColorGC(scr->black), WMColorGC(scr->darkGray),
13                            WMColorGC(scr->gray), WMColorGC(scr->white));
14 }
15
16 void
17 W_DrawReliefWithGC(W_Screen * scr, Drawable d, int x, int y, unsigned int width,
18                    unsigned int height, WMReliefType relief, GC black, GC dark, GC light, GC white)
19 {
20         Display *dpy = scr->display;
21         GC bgc;
22         GC wgc;
23         GC lgc;
24         GC dgc;
25
26         switch (relief) {
27         case WRSimple:
28                 XDrawRectangle(dpy, d, black, x, y, width - 1, height - 1);
29                 return;
30
31         case WRRaised:
32                 bgc = black;
33                 dgc = dark;
34                 wgc = white;
35                 lgc = light;
36                 break;
37
38         case WRSunken:
39                 wgc = dark;
40                 lgc = black;
41                 bgc = white;
42                 dgc = light;
43                 break;
44
45         case WRPushed:
46                 lgc = wgc = black;
47                 dgc = bgc = white;
48                 break;
49
50         case WRRidge:
51                 lgc = bgc = dark;
52                 dgc = wgc = white;
53                 break;
54
55         case WRGroove:
56                 wgc = dgc = dark;
57                 lgc = bgc = white;
58                 break;
59
60         default:
61                 return;
62         }
63         /* top left */
64         XDrawLine(dpy, d, wgc, x, y, x + width - 1, y);
65         if (width > 2 && relief != WRRaised && relief != WRPushed) {
66                 XDrawLine(dpy, d, lgc, x + 1, y + 1, x + width - 3, y + 1);
67         }
68
69         XDrawLine(dpy, d, wgc, x, y, x, y + height - 1);
70         if (height > 2 && relief != WRRaised && relief != WRPushed) {
71                 XDrawLine(dpy, d, lgc, x + 1, y + 1, x + 1, y + height - 3);
72         }
73
74         /* bottom right */
75         XDrawLine(dpy, d, bgc, x, y + height - 1, x + width - 1, y + height - 1);
76         if (width > 2 && relief != WRPushed) {
77                 XDrawLine(dpy, d, dgc, x + 1, y + height - 2, x + width - 2, y + height - 2);
78         }
79
80         XDrawLine(dpy, d, bgc, x + width - 1, y, x + width - 1, y + height - 1);
81         if (height > 2 && relief != WRPushed) {
82                 XDrawLine(dpy, d, dgc, x + width - 2, y + 1, x + width - 2, y + height - 2);
83         }
84 }
85
86 static int findNextWord(char *text, int limit)
87 {
88         int pos, len;
89
90         len = strcspn(text, " \t\n\r");
91         pos = len + strspn(text + len, " \t\n\r");
92         if (pos > limit)
93                 pos = limit;
94
95         return pos;
96 }
97
98 static int fitText(char *text, WMFont * font, int width, int wrap)
99 {
100         int i, w, beforecrlf, word1, word2;
101
102         /* text length before first cr/lf */
103         beforecrlf = strcspn(text, "\n");
104
105         if (!wrap || beforecrlf == 0)
106                 return beforecrlf;
107
108         w = WMWidthOfString(font, text, beforecrlf);
109         if (w <= width) {
110                 /* text up to first crlf fits */
111                 return beforecrlf;
112         }
113
114         word1 = 0;
115         while (1) {
116                 word2 = word1 + findNextWord(text + word1, beforecrlf - word1);
117                 if (word2 >= beforecrlf)
118                         break;
119                 w = WMWidthOfString(font, text, word2);
120                 if (w > width)
121                         break;
122                 word1 = word2;
123         }
124
125         for (i = word1; i < word2; i++) {
126                 w = WMWidthOfString(font, text, i);
127                 if (w > width) {
128                         break;
129                 }
130         }
131
132         /* keep words complete if possible */
133         if (!isspace(text[i]) && word1 > 0) {
134                 i = word1;
135         } else if (isspace(text[i]) && i < beforecrlf) {
136                 /* keep space on current row, so new row has next word in column 1 */
137                 i++;
138         }
139
140         return i;
141 }
142
143 #ifdef OLD_CODE
144 static int fitText(char *text, WMFont * font, int width, int wrap)
145 {
146         int i, j;
147         int w;
148
149         if (text[0] == 0)
150                 return 0;
151
152         i = 0;
153         if (wrap) {
154                 if (text[0] == '\n')
155                         return 0;
156
157                 do {
158                         i++;
159                         w = WMWidthOfString(font, text, i);
160                 } while (w < width && text[i] != '\n' && text[i] != 0);
161
162                 if (text[i] == '\n')
163                         return i;
164
165                 /* keep words complete */
166                 if (!isspace(text[i])) {
167                         j = i;
168                         while (j > 1 && !isspace(text[j]) && text[j] != 0)
169                                 j--;
170                         if (j > 1)
171                                 i = j;
172                 }
173         } else {
174                 i = strcspn(text, "\n");
175         }
176         return i;
177 }
178 #endif
179
180 int W_GetTextHeight(WMFont * font, char *text, int width, int wrap)
181 {
182         char *ptr = text;
183         int count;
184         int length = strlen(text);
185         int h;
186         int fheight = WMFontHeight(font);
187
188         h = 0;
189         while (length > 0) {
190                 count = fitText(ptr, font, width, wrap);
191
192                 h += fheight;
193
194                 if (isspace(ptr[count]))
195                         count++;
196
197                 ptr += count;
198                 length -= count;
199         }
200         return h;
201 }
202
203 void
204 W_PaintText(W_View * view, Drawable d, WMFont * font, int x, int y,
205             int width, WMAlignment alignment, WMColor * color, int wrap, char *text, int length)
206 {
207         char *ptr = text;
208         int line_width;
209         int line_x;
210         int count;
211         int fheight = WMFontHeight(font);
212
213         while (length > 0) {
214                 count = fitText(ptr, font, width, wrap);
215
216                 line_width = WMWidthOfString(font, ptr, count);
217                 if (alignment == WALeft)
218                         line_x = x;
219                 else if (alignment == WARight)
220                         line_x = x + width - line_width;
221                 else
222                         line_x = x + (width - line_width) / 2;
223
224                 WMDrawString(view->screen, d, color, font, line_x, y, ptr, count);
225
226                 if (wrap && ptr[count] != '\n')
227                         y += fheight;
228
229                 while (ptr[count] && ptr[count] == '\n') {
230                         y += fheight;
231                         count++;
232                 }
233
234                 ptr += count;
235                 length -= count;
236         }
237 }
238
239 void
240 W_PaintTextAndImage(W_View * view, int wrap, WMColor * textColor, W_Font * font,
241                     WMReliefType relief, char *text,
242                     WMAlignment alignment, W_Pixmap * image,
243                     WMImagePosition position, WMColor * backColor, int ofs)
244 {
245         W_Screen *screen = view->screen;
246         int ix, iy;
247         int x, y, w, h;
248         Drawable d = view->window;
249
250 #ifdef DOUBLE_BUFFER
251         d = XCreatePixmap(screen->display, view->window, view->size.width, view->size.height, screen->depth);
252 #endif
253
254         /* background */
255         if (backColor) {
256                 XFillRectangle(screen->display, d, WMColorGC(backColor),
257                                0, 0, view->size.width, view->size.height);
258         } else {
259 #ifndef DOUBLE_BUFFER
260                 XClearWindow(screen->display, d);
261 #else
262                 XSetForeground(screen->display, screen->copyGC, view->attribs.background_pixel);
263                 XFillRectangle(screen->display, d, screen->copyGC, 0, 0, view->size.width, view->size.height);
264 #endif
265         }
266
267         if (relief == WRFlat) {
268                 x = 0;
269                 y = 0;
270                 w = view->size.width;
271                 h = view->size.height;
272         } else {
273                 x = 1;
274                 y = 1;
275                 w = view->size.width - 3;
276                 h = view->size.height - 3;
277         }
278
279         /* calc. image alignment */
280         if (position != WIPNoImage && image != NULL) {
281                 switch (position) {
282                 case WIPOverlaps:
283                 case WIPImageOnly:
284                         ix = (view->size.width - image->width) / 2;
285                         iy = (view->size.height - image->height) / 2;
286                         /*
287                            x = 2;
288                            y = 0;
289                          */
290                         break;
291
292                 case WIPLeft:
293                         ix = x;
294                         iy = y + (h - image->height) / 2;
295                         x = x + image->width + 5;
296                         y = 0;
297                         w -= image->width + 5;
298                         break;
299
300                 case WIPRight:
301                         ix = view->size.width - image->width - x;
302                         iy = y + (h - image->height) / 2;
303                         w -= image->width + 5;
304                         break;
305
306                 case WIPBelow:
307                         ix = (view->size.width - image->width) / 2;
308                         iy = h - image->height;
309                         y = 0;
310                         h -= image->height;
311                         break;
312
313                 default:
314                 case WIPAbove:
315                         ix = (view->size.width - image->width) / 2;
316                         iy = y;
317                         y = image->height;
318                         h -= image->height;
319                         break;
320                 }
321
322                 ix += ofs;
323                 iy += ofs;
324
325                 XSetClipOrigin(screen->display, screen->clipGC, ix, iy);
326                 XSetClipMask(screen->display, screen->clipGC, image->mask);
327
328                 if (image->depth == 1)
329                         XCopyPlane(screen->display, image->pixmap, d, screen->clipGC,
330                                    0, 0, image->width, image->height, ix, iy, 1);
331                 else
332                         XCopyArea(screen->display, image->pixmap, d, screen->clipGC,
333                                   0, 0, image->width, image->height, ix, iy);
334         }
335
336         /* draw text */
337         if (position != WIPImageOnly && text != NULL) {
338                 int textHeight;
339
340                 textHeight = W_GetTextHeight(font, text, w - 8, wrap);
341                 W_PaintText(view, d, font, x + ofs + 4, y + ofs + (h - textHeight) / 2, w - 8,
342                             alignment, textColor, wrap, text, strlen(text));
343         }
344
345         /* draw relief */
346         W_DrawRelief(screen, d, 0, 0, view->size.width, view->size.height, relief);
347
348 #ifdef DOUBLE_BUFFER
349         XCopyArea(screen->display, d, view->window, screen->copyGC, 0, 0,
350                   view->size.width, view->size.height, 0, 0);
351         XFreePixmap(screen->display, d);
352 #endif
353 }
354
355 WMPoint wmkpoint(int x, int y)
356 {
357         WMPoint point;
358
359         point.x = x;
360         point.y = y;
361
362         return point;
363 }
364
365 WMSize wmksize(unsigned int width, unsigned int height)
366 {
367         WMSize size;
368
369         size.width = width;
370         size.height = height;
371
372         return size;
373 }
374
375 WMRect wmkrect(int x, int y, unsigned int width, unsigned int height)
376 {
377         WMRect rect;
378
379         rect.pos.x = x;
380         rect.pos.y = y;
381         rect.size.width = width;
382         rect.size.height = height;
383
384         return rect;
385 }