Fix periodic focus bug
[wmaker-crm.git] / WINGs / wmisc.c
blob861bd9f5210856c20aded13480d3ba9c2d53c04c
2 #include "WINGsP.h"
4 #include <wraster.h>
5 #include <ctype.h>
8 void
9 W_DrawRelief(W_Screen *scr, Drawable d, int x, int y, unsigned int width,
10 unsigned int height, WMReliefType relief)
12 W_DrawReliefWithGC(scr, d, x, y, width, height, relief,
13 WMColorGC(scr->black), WMColorGC(scr->darkGray),
14 WMColorGC(scr->gray), WMColorGC(scr->white));
18 void
19 W_DrawReliefWithGC(W_Screen *scr, Drawable d, int x, int y, unsigned int width,
20 unsigned int height, WMReliefType relief,
21 GC black, GC dark, GC light, GC white)
23 Display *dpy = scr->display;
24 GC bgc;
25 GC wgc;
26 GC lgc;
27 GC dgc;
29 switch (relief) {
30 case WRSimple:
31 XDrawRectangle(dpy, d, black, x, y, width-1, height-1);
32 return;
34 case WRRaised:
35 bgc = black;
36 dgc = dark;
37 wgc = white;
38 lgc = light;
39 break;
41 case WRSunken:
42 wgc = dark;
43 lgc = black;
44 bgc = white;
45 dgc = light;
46 break;
48 case WRPushed:
49 lgc = wgc = black;
50 dgc = bgc = white;
51 break;
53 case WRRidge:
54 lgc = bgc = dark;
55 dgc = wgc = white;
56 break;
58 case WRGroove:
59 wgc = dgc = dark;
60 lgc = bgc = white;
61 break;
63 default:
64 return;
66 /* top left */
67 XDrawLine(dpy, d, wgc, x, y, x+width-1, y);
68 if (width > 2 && relief != WRRaised && relief!=WRPushed) {
69 XDrawLine(dpy, d, lgc, x+1, y+1, x+width-3, y+1);
72 XDrawLine(dpy, d, wgc, x, y, x, y+height-1);
73 if (height > 2 && relief != WRRaised && relief!=WRPushed) {
74 XDrawLine(dpy, d, lgc, x+1, y+1, x+1, y+height-3);
77 /* bottom right */
78 XDrawLine(dpy, d, bgc, x, y+height-1, x+width-1, y+height-1);
79 if (width > 2 && relief!=WRPushed) {
80 XDrawLine(dpy, d, dgc, x+1, y+height-2, x+width-2, y+height-2);
83 XDrawLine(dpy, d, bgc, x+width-1, y, x+width-1, y+height-1);
84 if (height > 2 && relief!=WRPushed) {
85 XDrawLine(dpy, d, dgc, x+width-2, y+1, x+width-2, y+height-2);
90 static int
91 findNextWord(char *text, int limit)
93 int pos, len;
95 len = strcspn(text, " \t\n\r");
96 pos = len + strspn(text+len, " \t\n\r");
97 if (pos > limit)
98 pos = limit;
100 return pos;
104 static int
105 fitText(char *text, WMFont *font, int width, int wrap)
107 int i, w, beforecrlf, word1, word2;
109 /* text length before first cr/lf */
110 beforecrlf = strcspn(text, "\n");
112 if (!wrap || beforecrlf==0)
113 return beforecrlf;
115 w = WMWidthOfString(font, text, beforecrlf);
116 if (w <= width) {
117 /* text up to first crlf fits */
118 return beforecrlf;
121 word1 = 0;
122 while (1) {
123 word2 = word1 + findNextWord(text+word1, beforecrlf-word1);
124 if (word2 >= beforecrlf)
125 break;
126 w = WMWidthOfString(font, text, word2);
127 if (w > width)
128 break;
129 word1 = word2;
132 for (i=word1; i<word2; i++) {
133 w = WMWidthOfString(font, text, i);
134 if (w > width) {
135 break;
139 /* keep words complete if possible */
140 if (!isspace(text[i]) && word1>0) {
141 i = word1;
142 } else if (isspace(text[i]) && i<beforecrlf) {
143 /* keep space on current row, so new row has next word in column 1 */
144 i++;
147 return i;
151 #ifdef OLD_CODE
152 static int
153 fitText(char *text, WMFont *font, int width, int wrap)
155 int i, j;
156 int w;
158 if (text[0]==0)
159 return 0;
161 i = 0;
162 if (wrap) {
163 if (text[0]=='\n')
164 return 0;
166 do {
167 i++;
168 w = WMWidthOfString(font, text, i);
169 } while (w < width && text[i]!='\n' && text[i]!=0);
171 if (text[i]=='\n')
172 return i;
174 /* keep words complete */
175 if (!isspace(text[i])) {
176 j = i;
177 while (j>1 && !isspace(text[j]) && text[j]!=0)
178 j--;
179 if (j>1)
180 i = j;
182 } else {
183 i = strcspn(text, "\n");
185 return i;
187 #endif
191 W_GetTextHeight(WMFont *font, char *text, int width, int wrap)
193 char *ptr = text;
194 int count;
195 int length = strlen(text);
196 int h;
197 int fheight = WMFontHeight(font);
199 h = 0;
200 while (length > 0) {
201 count = fitText(ptr, font, width, wrap);
203 h += fheight;
205 if (isspace(ptr[count]))
206 count++;
208 ptr += count;
209 length -= count;
211 return h;
215 void
216 W_PaintText(W_View *view, Drawable d, WMFont *font, int x, int y,
217 int width, WMAlignment alignment, WMColor *color,
218 int wrap, char *text, int length)
220 char *ptr = text;
221 int line_width;
222 int line_x;
223 int count;
224 int fheight = WMFontHeight(font);
226 while (length > 0) {
227 count = fitText(ptr, font, width, wrap);
229 line_width = WMWidthOfString(font, ptr, count);
230 if (alignment==WALeft)
231 line_x = x;
232 else if (alignment==WARight)
233 line_x = x + width - line_width;
234 else
235 line_x = x + (width - line_width) / 2;
237 WMDrawString(view->screen, d, color, font, line_x, y, ptr, count);
239 if (wrap && ptr[count]!='\n')
240 y += fheight;
242 while (ptr[count] && ptr[count]=='\n') {
243 y += fheight;
244 count++;
247 ptr += count;
248 length -= count;
253 void
254 W_PaintTextAndImage(W_View *view, int wrap, WMColor *textColor, W_Font *font,
255 WMReliefType relief, char *text,
256 WMAlignment alignment, W_Pixmap *image,
257 WMImagePosition position, WMColor *backColor, int ofs)
259 W_Screen *screen = view->screen;
260 int ix, iy;
261 int x, y, w, h;
262 Drawable d = view->window;
265 #ifdef DOUBLE_BUFFER
266 d = XCreatePixmap(screen->display, view->window,
267 view->size.width, view->size.height, screen->depth);
268 #endif
270 /* background */
271 if (backColor) {
272 XFillRectangle(screen->display, d, WMColorGC(backColor),
273 0, 0, view->size.width, view->size.height);
274 } else {
275 #ifndef DOUBLE_BUFFER
276 XClearWindow(screen->display, d);
277 #else
278 XSetForeground(screen->display, screen->copyGC,
279 view->attribs.background_pixel);
280 XFillRectangle(screen->display, d, screen->copyGC, 0, 0,
281 view->size.width, view->size.height);
282 #endif
286 if (relief == WRFlat) {
287 x = 0;
288 y = 0;
289 w = view->size.width;
290 h = view->size.height;
291 } else {
292 x = 1;
293 y = 1;
294 w = view->size.width - 3;
295 h = view->size.height - 3;
298 /* calc. image alignment */
299 if (position!=WIPNoImage && image!=NULL) {
300 switch (position) {
301 case WIPOverlaps:
302 case WIPImageOnly:
303 ix = (view->size.width - image->width) / 2;
304 iy = (view->size.height - image->height) / 2;
306 x = 2;
307 y = 0;
309 break;
311 case WIPLeft:
312 ix = x;
313 iy = y + (h - image->height) / 2;
314 x = x + image->width + 5;
315 y = 0;
316 w -= image->width + 5;
317 break;
319 case WIPRight:
320 ix = view->size.width - image->width - x;
321 iy = y + (h - image->height) / 2;
322 w -= image->width + 5;
323 break;
325 case WIPBelow:
326 ix = (view->size.width - image->width) / 2;
327 iy = h - image->height;
328 y = 0;
329 h -= image->height;
330 break;
332 default:
333 case WIPAbove:
334 ix = (view->size.width - image->width) / 2;
335 iy = y;
336 y = image->height;
337 h -= image->height;
338 break;
341 ix += ofs;
342 iy += ofs;
344 XSetClipOrigin(screen->display, screen->clipGC, ix, iy);
345 XSetClipMask(screen->display, screen->clipGC, image->mask);
347 if (image->depth==1)
348 XCopyPlane(screen->display, image->pixmap, d, screen->clipGC,
349 0, 0, image->width, image->height, ix, iy, 1);
350 else
351 XCopyArea(screen->display, image->pixmap, d, screen->clipGC,
352 0, 0, image->width, image->height, ix, iy);
355 /* draw text */
356 if (position != WIPImageOnly && text!=NULL) {
357 int textHeight;
359 textHeight = W_GetTextHeight(font, text, w-8, wrap);
360 W_PaintText(view, d, font, x+ofs+4, y+ofs + (h-textHeight)/2, w-8,
361 alignment, textColor, wrap, text, strlen(text));
365 /* draw relief */
366 W_DrawRelief(screen, d, 0, 0, view->size.width, view->size.height, relief);
368 #ifdef DOUBLE_BUFFER
369 XCopyArea(screen->display, d, view->window, screen->copyGC, 0, 0,
370 view->size.width, view->size.height, 0, 0);
371 XFreePixmap(screen->display, d);
372 #endif
377 WMPoint
378 wmkpoint(int x, int y)
380 WMPoint point;
382 point.x = x;
383 point.y = y;
385 return point;
389 WMSize
390 wmksize(unsigned int width, unsigned int height)
392 WMSize size;
394 size.width = width;
395 size.height = height;
397 return size;
401 WMRect
402 wmkrect(int x, int y, unsigned int width, unsigned int height)
404 WMRect rect;
406 rect.pos.x = x;
407 rect.pos.y = y;
408 rect.size.width = width;
409 rect.size.height = height;
411 return rect;