aboutsummaryrefslogtreecommitdiff
path: root/src/misc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/misc.cc')
-rw-r--r--src/misc.cc478
1 files changed, 478 insertions, 0 deletions
diff --git a/src/misc.cc b/src/misc.cc
new file mode 100644
index 0000000..481705c
--- /dev/null
+++ b/src/misc.cc
@@ -0,0 +1,478 @@
1// misc.hh for fluxbox
2// Copyright (c) 2001 Henrik Kinnunen (fluxgen@linuxmail.org)
3//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22#include "misc.hh"
23#include "i18n.hh"
24
25#include <stdlib.h>
26#include <string.h>
27#include <stdio.h>
28
29// ----- start code stealing ----
30
31// ----------------------------------------------------------------------
32// xvertext, Copyright (c) 1992 Alan Richardson (mppa3@uk.ac.sussex.syma)
33// ----------------------------------------------------------------------
34
35int xv_errno; //TODO: ?
36
37static char *my_strdup(char *str);
38
39//------- getTabAlignmentString ----------
40//Routine to mimic `strdup()' (some machines don't have it)
41//----------------------------------------
42static char *my_strdup(char *str)
43{
44 char *s;
45
46 if (str == NULL) return NULL;
47
48 s = (char *)malloc((unsigned)(strlen(str)+1));
49 /* this error is highly unlikely ... */
50 if (s == NULL) {
51 fprintf(stderr, "Fatal error: my_strdup(): Couldn't do malloc!\n");
52 exit(1);
53 }
54
55 strcpy(s, str);
56 return s;
57}
58
59//------- XRotLoadFont -------------------
60// Load the rotated version of a given font
61//----------------------------------------
62XRotFontStruct *XRotLoadFont(Display *dpy, char *fontname, float angle)
63{
64 char val;
65 XImage *I1, *I2;
66 Pixmap canvas;
67 Window root;
68 int screen;
69 GC font_gc;
70 char text[3];/*, errstr[300];*/
71 XFontStruct *fontstruct;
72 XRotFontStruct *rotfont;
73 int ichar, i, j, index, boxlen = 60, dir;
74 int vert_w, vert_h, vert_len, bit_w, bit_h, bit_len;
75 int min_char, max_char;
76 unsigned char *vertdata, *bitdata;
77 int ascent, descent, lbearing, rbearing;
78 int on = 1, off = 0;
79
80 /* make angle positive ... */
81 if (angle < 0) do angle += 360; while (angle < 0);
82
83 /* get nearest vertical or horizontal direction ... */
84 dir = (int)((angle+45.)/90.)%4;
85
86 /* useful macros ... */
87 screen = DefaultScreen(dpy);
88 root = DefaultRootWindow(dpy);
89
90 /* create the depth 1 canvas bitmap ... */
91 canvas = XCreatePixmap(dpy, root, boxlen, boxlen, 1);
92
93 /* create a GC ... */
94 font_gc = XCreateGC(dpy, canvas, 0, 0);
95 XSetBackground(dpy, font_gc, off);
96
97 /* load the font ... */
98 fontstruct = XLoadQueryFont(dpy, fontname);
99 if (fontstruct == NULL) {
100 xv_errno = XV_NOFONT;
101 return NULL;
102 }
103
104 XSetFont(dpy, font_gc, fontstruct->fid);
105
106 /* allocate space for rotated font ... */
107 rotfont = (XRotFontStruct *)malloc((unsigned)sizeof(XRotFontStruct));
108 if (rotfont == NULL) {
109 xv_errno = XV_NOMEM;
110 return NULL;
111 }
112
113 /* determine which characters are defined in font ... */
114 min_char = fontstruct->min_char_or_byte2;
115 max_char = fontstruct->max_char_or_byte2;
116
117 /* we only want printing characters ... */
118 if (min_char<32) min_char = 32;
119 if (max_char>126) max_char = 126;
120
121 /* some overall font data ... */
122 rotfont->name = my_strdup(fontname);
123 rotfont->dir = dir;
124 rotfont->min_char = min_char;
125 rotfont->max_char = max_char;
126 rotfont->max_ascent = fontstruct->max_bounds.ascent;
127 rotfont->max_descent = fontstruct->max_bounds.descent;
128 rotfont->height = rotfont->max_ascent+rotfont->max_descent;
129
130 /* remember xfontstruct for `normal' text ... */
131 if (dir == 0)
132 rotfont->xfontstruct = fontstruct;
133 else {
134 /* font needs rotation ... */
135 /* loop through each character ... */
136 for (ichar = min_char; ichar <= max_char; ichar++) {
137 index = ichar-fontstruct->min_char_or_byte2;
138
139 /* per char dimensions ... */
140 ascent = rotfont->per_char[ichar-32].ascent =
141 fontstruct->per_char[index].ascent;
142 descent = rotfont->per_char[ichar-32].descent =
143 fontstruct->per_char[index].descent;
144 lbearing = rotfont->per_char[ichar-32].lbearing =
145 fontstruct->per_char[index].lbearing;
146 rbearing = rotfont->per_char[ichar-32].rbearing =
147 fontstruct->per_char[index].rbearing;
148 rotfont->per_char[ichar-32].width =
149 fontstruct->per_char[index].width;
150
151 /* some space chars have zero body, but a bitmap can't have ... */
152 if (!ascent && !descent)
153 ascent = rotfont->per_char[ichar-32].ascent = 1;
154 if (!lbearing && !rbearing)
155 rbearing = rotfont->per_char[ichar-32].rbearing = 1;
156
157 /* glyph width and height when vertical ... */
158 vert_w = rbearing-lbearing;
159 vert_h = ascent+descent;
160
161 /* width in bytes ... */
162 vert_len = (vert_w-1)/8+1;
163
164 XSetForeground(dpy, font_gc, off);
165 XFillRectangle(dpy, canvas, font_gc, 0, 0, boxlen, boxlen);
166
167 /* draw the character centre top right on canvas ... */
168 sprintf(text, "%c", ichar);
169 XSetForeground(dpy, font_gc, on);
170 XDrawImageString(dpy, canvas, font_gc, boxlen/2 - lbearing,
171 boxlen/2 - descent, text, 1);
172
173 /* reserve memory for first XImage ... */
174 vertdata = (unsigned char *) malloc((unsigned)(vert_len*vert_h));
175 if (vertdata == NULL) {
176 xv_errno = XV_NOMEM;
177 return NULL;
178 }
179
180 /* create the XImage ... */
181 I1 = XCreateImage(dpy, DefaultVisual(dpy, screen), 1, XYBitmap,
182 0, (char *)vertdata, vert_w, vert_h, 8, 0);
183
184 if (I1 == NULL) {
185 xv_errno = XV_NOXIMAGE;
186 return NULL;
187 }
188
189 I1->byte_order = I1->bitmap_bit_order = MSBFirst;
190
191 /* extract character from canvas ... */
192 XGetSubImage(dpy, canvas, boxlen/2, boxlen/2-vert_h,
193 vert_w, vert_h, 1, XYPixmap, I1, 0, 0);
194 I1->format = XYBitmap;
195
196 /* width, height of rotated character ... */
197 if (dir == 2) {
198 bit_w = vert_w;
199 bit_h = vert_h;
200 } else {
201 bit_w = vert_h;
202 bit_h = vert_w;
203 }
204
205 /* width in bytes ... */
206 bit_len = (bit_w-1)/8 + 1;
207
208 rotfont->per_char[ichar-32].glyph.bit_w = bit_w;
209 rotfont->per_char[ichar-32].glyph.bit_h = bit_h;
210
211 /* reserve memory for the rotated image ... */
212 bitdata = (unsigned char *)calloc((unsigned)(bit_h*bit_len), 1);
213 if (bitdata == NULL) {
214 xv_errno = XV_NOMEM;
215 return NULL;
216 }
217
218 /* create the image ... */
219 I2 = XCreateImage(dpy, DefaultVisual(dpy, screen), 1, XYBitmap, 0,
220 (char *)bitdata, bit_w, bit_h, 8, 0);
221
222 if (I2 == NULL) {
223 xv_errno = XV_NOXIMAGE;
224 return NULL;
225 }
226
227 I2->byte_order = I2->bitmap_bit_order = MSBFirst;
228
229 /* map vertical data to rotated character ... */
230 for (j = 0; j < bit_h; j++) {
231 for (i = 0; i < bit_w; i++) {
232 /* map bits ... */
233 if (dir == 1) {
234 val = vertdata[i*vert_len + (vert_w-j-1)/8] &
235 (128>>((vert_w-j-1)%8));
236 } else if (dir == 2) {
237 val = vertdata[(vert_h-j-1)*vert_len +
238 (vert_w-i-1)/8] & (128>>((vert_w-i-1)%8));
239 } else {
240 val = vertdata[(vert_h-i-1)*vert_len + j/8] &
241 (128>>(j%8));
242 }
243 if (val) {
244 bitdata[j*bit_len + i/8] = bitdata[j*bit_len + i/8] |
245 (128>>(i%8));
246 }
247 }
248 }
249
250 /* create this character's bitmap ... */
251 rotfont->per_char[ichar-32].glyph.bm =
252 XCreatePixmap(dpy, root, bit_w, bit_h, 1);
253
254 /* put the image into the bitmap ... */
255 XPutImage(dpy, rotfont->per_char[ichar-32].glyph.bm,
256 font_gc, I2, 0, 0, 0, 0, bit_w, bit_h);
257
258 /* free the image and data ... */
259 XDestroyImage(I1);
260 XDestroyImage(I2);
261 /* free((char *)bitdata); -- XDestroyImage does this
262 free((char *)vertdata);*/
263 }
264 XFreeFont(dpy, fontstruct);
265 }
266
267 /* free pixmap and GC ... */
268 XFreePixmap(dpy, canvas);
269 XFreeGC(dpy, font_gc);
270
271 return rotfont;
272}
273
274//------- XRotUnloadFont -----------------
275// Free the resources associated with a
276// rotated font
277//----------------------------------------
278void XRotUnloadFont(Display *dpy, XRotFontStruct *rotfont)
279{
280 int ichar;
281
282 if (rotfont->dir == 0)
283 XFreeFont(dpy, rotfont->xfontstruct);
284 else {
285 /* loop through each character, freeing its pixmap ... */
286 for (ichar = rotfont->min_char-32; ichar <= rotfont->max_char-32;
287 ichar++)
288 XFreePixmap(dpy, rotfont->per_char[ichar].glyph.bm);
289 }
290 /* rotfont should never be referenced again ... */
291 free((char *)rotfont->name);
292 free((char *)rotfont);
293}
294
295//------- XRotTextWidth ------------------
296// Returns the width of a rotated string
297//----------------------------------------
298unsigned int XRotTextWidth(XRotFontStruct *rotfont, char *str, int len)
299{
300 int i, width = 0, ichar;
301
302 if (str == NULL)
303 return 0;
304
305 if (rotfont->dir == 0)
306 width = XTextWidth(rotfont->xfontstruct, str, strlen(str));
307 else {
308 for (i = 0; i<len; i++) {
309 ichar = str[i]-32;
310
311 /* make sure it's a printing character ... */
312 if (ichar >= 0 && ichar<95)
313 width += rotfont->per_char[ichar].width;
314 }
315 }
316 return width;
317}
318
319
320//------- XRotDrawString -----------------
321// A front end to XRotDrawString : mimics XDrawString
322//----------------------------------------
323void XRotDrawString(Display *dpy, XRotFontStruct *rotfont, Drawable drawable,
324 GC gc, int x, int y, char *str, int len)
325{
326 static GC my_gc = 0;
327 int i, xp, yp, dir, ichar;
328
329 if (str == NULL || len<1)
330 return;
331
332 dir = rotfont->dir;
333 if (my_gc == 0)
334 my_gc = XCreateGC(dpy, drawable, 0, 0);
335
336 XCopyGC(dpy, gc, GCForeground|GCBackground, my_gc);
337
338 /* a horizontal string is easy ... */
339 if (dir == 0) {
340 XSetFillStyle(dpy, my_gc, FillSolid);
341 XSetFont(dpy, my_gc, rotfont->xfontstruct->fid);
342 XDrawString(dpy, drawable, my_gc, x, y, str, len);
343 return;
344 }
345
346 /* vertical or upside down ... */
347
348 XSetFillStyle(dpy, my_gc, FillStippled);
349
350 /* loop through each character in string ... */
351 for (i = 0; i<len; i++) {
352 ichar = str[i]-32;
353
354 /* make sure it's a printing character ... */
355 if (ichar >= 0 && ichar<95) {
356 /* suitable offset ... */
357 if (dir == 1) {
358 xp = x-rotfont->per_char[ichar].ascent;
359 yp = y-rotfont->per_char[ichar].rbearing;
360 } else if (dir == 2) {
361 xp = x-rotfont->per_char[ichar].rbearing;
362 yp = y-rotfont->per_char[ichar].descent+1;
363 } else {
364 xp = x-rotfont->per_char[ichar].descent+1;
365 yp = y+rotfont->per_char[ichar].lbearing;
366 }
367
368 /* draw the glyph ... */
369 XSetStipple(dpy, my_gc, rotfont->per_char[ichar].glyph.bm);
370
371 XSetTSOrigin(dpy, my_gc, xp, yp);
372
373 XFillRectangle(dpy, drawable, my_gc, xp, yp,
374 rotfont->per_char[ichar].glyph.bit_w,
375 rotfont->per_char[ichar].glyph.bit_h);
376
377 /* advance position ... */
378 if (dir == 1)
379 y -= rotfont->per_char[ichar].width;
380 else if (dir == 2)
381 x -= rotfont->per_char[ichar].width;
382 else
383 y += rotfont->per_char[ichar].width;
384 }
385 }
386}
387
388// ---- stop code stealing ----
389
390void DrawString(Display *display, Window w, GC gc, FFont *font,
391 unsigned int text_w, unsigned int size_w,
392 unsigned int bevel_w, char *text) {
393//Draw title string
394
395 unsigned int l = text_w;
396 int dlen=strlen(text);
397 int dx=bevel_w*2;
398
399 if (text_w > size_w) {
400 for (; dlen >= 0; dlen--) {
401 if (I18n::instance()->multibyte()) {
402 XRectangle ink, logical;
403 XmbTextExtents(font->set, text, dlen,
404 &ink, &logical);
405 l = logical.width;
406 } else
407 l = XTextWidth(font->fontstruct, text, dlen);
408
409 l += (dx * 4);
410
411 if (l < size_w)
412 break;
413 }
414 }
415
416 switch (font->justify) {
417 case FFont::Right:
418 dx += size_w - l;
419 break;
420
421 case FFont::Center:
422 dx += (size_w - l) / 2;
423 break;
424 default:
425 break;
426 }
427
428 //Draw title to m_tabwin
429
430 XClearWindow(display, w);
431
432 if (I18n::instance()->multibyte()) {
433 XmbDrawString(display, w,
434 font->set, gc, dx, 1 - font->set_extents->max_ink_extent.y,
435 text, dlen);
436 } else {
437 XDrawString(display, w,
438 gc, dx, font->fontstruct->ascent + 1,
439 text, dlen);
440 }
441
442}
443
444
445void DrawRotString(Display *display, Window w, GC gc, XRotFontStruct *font,
446 unsigned int align, unsigned int text_w,
447 unsigned int size_w, unsigned int size_h,
448 unsigned int bevel_w, char *text) {
449
450 unsigned int l = text_w;
451 int dlen = strlen(text);
452 int dx = bevel_w * 2;
453
454 if (text_w > size_w) {
455 for (; dlen >= 0; dlen--) {
456 l = XRotTextWidth(font, text, dlen);
457
458 l += (dx * 4);
459
460 if (l < size_h)
461 break;
462 }
463 }
464
465 if (align == FFont::Right)
466 size_h = l;
467 else if (align == FFont::Center)
468 size_h = (size_h + l) / 2;
469 else
470 size_h -= (dx * 4);
471
472 // To get it in the "center" of the tab
473 size_w = (size_w + XRotTextWidth(font, "/", 1)) / 2;
474
475 //Draw title to m_tabwin
476 XClearWindow(display, w);
477 XRotDrawString(display, font, w, gc, size_w, size_h, text, dlen);
478}