ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/rxvttoolkit.C
(Generate patch)

Comparing rxvt-unicode/src/rxvttoolkit.C (file contents):
Revision 1.20 by root, Fri Jan 6 02:11:15 2006 UTC vs.
Revision 1.39 by root, Tue Jan 31 00:25:16 2006 UTC

25#include <rxvttoolkit.h> 25#include <rxvttoolkit.h>
26 26
27#include <unistd.h> 27#include <unistd.h>
28#include <fcntl.h> 28#include <fcntl.h>
29 29
30#include <sys/utsname.h>
31
30#ifndef NO_SLOW_LINK_SUPPORT 32#ifndef NO_SLOW_LINK_SUPPORT
31# include <sys/socket.h> 33# include <sys/socket.h>
32# include <sys/un.h> 34# include <sys/un.h>
33#endif 35#endif
34 36
37#if XFT
38# include <X11/extensions/Xrender.h>
39#endif
40
41const char *const xa_names[] =
42{
43 "TEXT",
44 "COMPOUND_TEXT",
45 "UTF8_STRING",
46 "MULTIPLE",
47 "TARGETS",
48 "TIMESTAMP",
49 "VT_SELECTION",
50 "INCR",
51 "WM_PROTOCOLS",
52 "WM_DELETE_WINDOW",
53 "CLIPBOARD",
54 "AVERAGE_WIDTH",
55 "WEIGHT_NAME",
56 "SLANT",
57 "CHARSET_REGISTRY",
58 "CHARSET_ENCODING",
59#if ENABLE_FRILLS
60 "_MOTIF_WM_HINTS",
61#endif
62#if ENABLE_EWMH
63 "_NET_WM_PID",
64 "_NET_WM_NAME",
65 "_NET_WM_ICON_NAME",
66 "_NET_WM_PING",
67#endif
68#if USE_XIM
69 "WM_LOCALE_NAME",
70 "XIM_SERVERS",
71#endif
72#ifdef TRANSPARENT
73 "_XROOTPMAP_ID",
74 "ESETROOT_PMAP_ID",
75#endif
76#if ENABLE_XEMBED
77 "_XEMBED",
78 "_XEMBED_INFO",
79#endif
80#if !ENABLE_MINIMAL
81 "SCREEN_RESOURCES",
82 "XDCCC_LINEAR_RGB_CORRECTION",
83 "XDCCC_LINEAR_RGB_MATRICES",
84 "WM_COLORMAP_WINDOWS",
85 "WM_STATE",
86 "cursor",
87# if USE_XIM
88 "TRANSPORT",
89 "LOCALES",
90 "_XIM_PROTOCOL",
91 "_XIM_XCONNECT",
92 "_XIM_MOREDATA",
93# endif
94#endif
95};
96
97/////////////////////////////////////////////////////////////////////////////
98
35refcounted::refcounted (const char *id) 99refcounted::refcounted (const char *id)
36{ 100{
37 this->id = strdup (id); 101 this->id = strdup (id);
38} 102}
39 103
47{ 111{
48 for (T **i = this->begin (); i < this->end (); ++i) 112 for (T **i = this->begin (); i < this->end (); ++i)
49 { 113 {
50 if (!strcmp (id, (*i)->id)) 114 if (!strcmp (id, (*i)->id))
51 { 115 {
52 (*i)->referenced++; 116 ++(*i)->referenced;
117 (*i)->ref_next ();
53 return *i; 118 return *i;
54 } 119 }
55 } 120 }
56 121
57 T *obj = new T (id); 122 T *obj = new T (id);
58 123
59 obj->referenced = 1;
60
61 if (obj && obj->init ()) 124 if (obj && obj->ref_init ())
62 { 125 {
126 obj->referenced = 1;
63 this->push_back (obj); 127 this->push_back (obj);
64 return obj; 128 return obj;
65 } 129 }
66 else 130 else
67 { 131 {
91} 155}
92 156
93///////////////////////////////////////////////////////////////////////////// 157/////////////////////////////////////////////////////////////////////////////
94 158
95#ifdef USE_XIM 159#ifdef USE_XIM
160
96static void 161static void
97#if XIMCB_PROTO_BROKEN 162#if XIMCB_PROTO_BROKEN
98im_destroy_cb (XIC unused1, XPointer client_data, XPointer unused3) 163im_destroy_cb (XIC unused1, XPointer client_data, XPointer unused3)
99#else 164#else
100im_destroy_cb (XIM unused1, XPointer client_data, XPointer unused3) 165im_destroy_cb (XIM unused1, XPointer client_data, XPointer unused3)
107 172
108 display->xims.erase (find (display->xims.begin (), display->xims.end (), xim)); 173 display->xims.erase (find (display->xims.begin (), display->xims.end (), xim));
109 display->im_change_cb (); 174 display->im_change_cb ();
110} 175}
111 176
177bool
112bool rxvt_xim::init () 178rxvt_xim::ref_init ()
113{ 179{
114 display = GET_R->display; //HACK: TODO 180 display = GET_R->display; //HACK: TODO
115 181
116 xim = XOpenIM (display->display, NULL, NULL, NULL); 182 xim = XOpenIM (display->display, NULL, NULL, NULL);
117 183
130rxvt_xim::~rxvt_xim () 196rxvt_xim::~rxvt_xim ()
131{ 197{
132 if (xim) 198 if (xim)
133 XCloseIM (xim); 199 XCloseIM (xim);
134} 200}
201
135#endif 202#endif
203
204/////////////////////////////////////////////////////////////////////////////
205
206void
207rxvt_screen::set (rxvt_display *disp)
208{
209 display = disp;
210 xdisp = disp->display;
211
212 Screen *screen = ScreenOfDisplay (xdisp, disp->screen);
213
214 depth = DefaultDepthOfScreen (screen);
215 visual = DefaultVisualOfScreen (screen);
216 cmap = DefaultColormapOfScreen (screen);
217}
218
219void
220rxvt_screen::set (rxvt_display *disp, int bitdepth)
221{
222 set (disp);
223
224#if XFT
225 XVisualInfo vinfo;
226
227 if (XMatchVisualInfo (xdisp, display->screen, bitdepth, TrueColor, &vinfo))
228 {
229 depth = bitdepth;
230 visual = vinfo.visual;
231 cmap = XCreateColormap (xdisp, disp->root, visual, AllocNone);
232 }
233#endif
234}
235
236void
237rxvt_screen::clear ()
238{
239 if (cmap != DefaultColormapOfScreen (ScreenOfDisplay (xdisp, display->screen)))
240 XFreeColormap (xdisp, cmap);
241}
136 242
137///////////////////////////////////////////////////////////////////////////// 243/////////////////////////////////////////////////////////////////////////////
138 244
139rxvt_display::rxvt_display (const char *id) 245rxvt_display::rxvt_display (const char *id)
140: refcounted (id) 246: refcounted (id)
141, x_ev (this, &rxvt_display::x_cb) 247, x_ev (this, &rxvt_display::x_cb)
142, selection_owner (0) 248, selection_owner (0)
143{ 249{
144} 250}
145 251
252XrmDatabase
253rxvt_display::get_resources ()
254{
255 char *homedir = (char *)getenv ("HOME");
256 char fname[1024];
257
258 /*
259 * get resources using the X library function
260 */
261 char *displayResource, *xe;
262 XrmDatabase database, rdb1;
263
264 database = NULL;
265
266 // for ordering, see for example http://www.faqs.org/faqs/Xt-FAQ/ Subject: 20
267
268 // 6. System wide per application default file.
269
270 /* Add in $XAPPLRESDIR/Rxvt only; not bothering with XUSERFILESEARCHPATH */
271 if ((xe = (char *)getenv ("XAPPLRESDIR")))
272 {
273 snprintf (fname, sizeof (fname), "%s/%s", xe, RESCLASS);
274
275 if ((rdb1 = XrmGetFileDatabase (fname)))
276 XrmMergeDatabases (rdb1, &database);
277 }
278
279 // 5. User's per application default file.
280 // none
281
282 // 4. User's defaults file.
283 /* Get any Xserver defaults */
284 displayResource = XResourceManagerString (display);
285
286 if (displayResource != NULL)
287 {
288 if ((rdb1 = XrmGetStringDatabase (displayResource)))
289 XrmMergeDatabases (rdb1, &database);
290 }
291 else if (homedir)
292 {
293 snprintf (fname, sizeof (fname), "%s/.Xdefaults", homedir);
294
295 if ((rdb1 = XrmGetFileDatabase (fname)))
296 XrmMergeDatabases (rdb1, &database);
297 }
298
299 /* Get screen specific resources */
300 displayResource = XScreenResourceString (ScreenOfDisplay (display, screen));
301
302 if (displayResource != NULL)
303 {
304 if ((rdb1 = XrmGetStringDatabase (displayResource)))
305 /* Merge with screen-independent resources */
306 XrmMergeDatabases (rdb1, &database);
307
308 XFree (displayResource);
309 }
310
311 // 3. User's per host defaults file
312 /* Add in XENVIRONMENT file */
313 if ((xe = (char *)getenv ("XENVIRONMENT"))
314 && (rdb1 = XrmGetFileDatabase (xe)))
315 XrmMergeDatabases (rdb1, &database);
316 else if (homedir)
317 {
318 struct utsname un;
319
320 if (!uname (&un))
321 {
322 snprintf (fname, sizeof (fname), "%s/.Xdefaults-%s", homedir, un.nodename);
323
324 if ((rdb1 = XrmGetFileDatabase (fname)))
325 XrmMergeDatabases (rdb1, &database);
326 }
327 }
328
329 return database;
330}
331
146bool rxvt_display::init () 332bool rxvt_display::ref_init ()
147{ 333{
148#ifdef LOCAL_X_IS_UNIX 334#ifdef LOCAL_X_IS_UNIX
149 if (id[0] == ':') 335 if (id[0] == ':')
150 { 336 {
151 val = rxvt_malloc (5 + strlen (id) + 1); 337 val = rxvt_malloc (5 + strlen (id) + 1);
164 if (!display) 350 if (!display)
165 return false; 351 return false;
166 352
167 screen = DefaultScreen (display); 353 screen = DefaultScreen (display);
168 root = DefaultRootWindow (display); 354 root = DefaultRootWindow (display);
169 visual = DefaultVisual (display, screen);
170 cmap = DefaultColormap (display, screen);
171 depth = DefaultDepth (display, screen);
172 355
173 int fd = XConnectionNumber (display); 356 assert (sizeof (xa_names) / sizeof (char *) == NUM_XA);
357 XInternAtoms (display, (char **)xa_names, NUM_XA, False, xa);
174 358
175#ifndef NO_SLOW_LINK_SUPPORT 359 XrmSetDatabase (display, get_resources ());
176 // try to detect wether we have a local connection.
177 // assume unix domains socket == local, everything else not
178 // TODO: might want to check for inet/127.0.0.1
179 is_local = 0;
180 sockaddr_un sa;
181 socklen_t sl = sizeof (sa);
182
183 if (!getsockname (fd, (sockaddr *)&sa, &sl))
184 is_local = sa.sun_family == AF_LOCAL;
185#endif
186 360
187#ifdef POINTER_BLANK 361#ifdef POINTER_BLANK
188 XColor blackcolour; 362 XColor blackcolour;
189 blackcolour.red = 0; 363 blackcolour.red = 0;
190 blackcolour.green = 0; 364 blackcolour.green = 0;
193 blank_cursor = XCreateGlyphCursor (display, f, f, ' ', ' ', 367 blank_cursor = XCreateGlyphCursor (display, f, f, ' ', ' ',
194 &blackcolour, &blackcolour); 368 &blackcolour, &blackcolour);
195 XUnloadFont (display, f); 369 XUnloadFont (display, f);
196#endif 370#endif
197 371
198#ifdef PREFER_24BIT 372 int fd = XConnectionNumber (display);
199 /*
200 * If depth is not 24, look for a 24bit visual.
201 */
202 if (depth != 24)
203 {
204 XVisualInfo vinfo;
205 373
206 if (XMatchVisualInfo (display, screen, 24, TrueColor, &vinfo)) 374#ifndef NO_SLOW_LINK_SUPPORT
207 { 375 // try to detect wether we have a local connection.
208 depth = 24; 376 // assume unix domains socket == local, everything else not
209 visual = vinfo.visual; 377 // TODO: might want to check for inet/127.0.0.1
210 cmap = XCreateColormap (display, 378 is_local = 0;
211 RootWindow (display, screen), 379 sockaddr_un sa;
212 visual, AllocNone); 380 socklen_t sl = sizeof (sa);
213 } 381
214 } 382 if (!getsockname (fd, (sockaddr *)&sa, &sl))
383 is_local = sa.sun_family == AF_LOCAL;
215#endif 384#endif
216 385
217 x_ev.start (fd, EVENT_READ); 386 x_ev.start (fd, EVENT_READ);
218 fcntl (fd, F_SETFD, FD_CLOEXEC); 387 fcntl (fd, F_SETFD, FD_CLOEXEC);
219 388
220 XSelectInput (display, root, PropertyChangeMask); 389 XSelectInput (display, root, PropertyChangeMask);
221#ifdef USE_XIM
222 xa_xim_servers = XInternAtom (display, "XIM_SERVERS", 0);
223#endif
224 390
225 flush (); 391 flush ();
226 392
227 return true; 393 return true;
228} 394}
229 395
396void
397rxvt_display::ref_next ()
398{
399 // TODO: somehow check wether the database files/resources changed
400 // before re-loading/parsing
401 XrmDestroyDatabase (XrmGetDatabase (display));
402 XrmSetDatabase (display, get_resources ());
403}
404
230rxvt_display::~rxvt_display () 405rxvt_display::~rxvt_display ()
231{ 406{
407 if (!display)
408 return;
409
410#ifdef POINTER_BLANK
411 XFreeCursor (display, blank_cursor);
412#endif
232 x_ev.stop (); 413 x_ev.stop ();
233#ifdef USE_XIM 414#ifdef USE_XIM
234 xims.clear (); 415 xims.clear ();
235#endif 416#endif
236
237 if (display)
238 XCloseDisplay (display); 417 XCloseDisplay (display);
239} 418}
240 419
241#ifdef USE_XIM 420#ifdef USE_XIM
242void rxvt_display::im_change_cb () 421void rxvt_display::im_change_cb ()
243{ 422{
251 // registers, as xlib crashes due to a race otherwise. 430 // registers, as xlib crashes due to a race otherwise.
252 Atom actual_type, *atoms; 431 Atom actual_type, *atoms;
253 int actual_format; 432 int actual_format;
254 unsigned long nitems, bytes_after; 433 unsigned long nitems, bytes_after;
255 434
256 if (XGetWindowProperty (display, root, xa_xim_servers, 0L, 1000000L, 435 if (XGetWindowProperty (display, root, xa[XA_XIM_SERVERS], 0L, 1000000L,
257 False, XA_ATOM, &actual_type, &actual_format, 436 False, XA_ATOM, &actual_type, &actual_format,
258 &nitems, &bytes_after, (unsigned char **)&atoms) 437 &nitems, &bytes_after, (unsigned char **)&atoms)
259 != Success ) 438 != Success )
260 return; 439 return;
261 440
281#ifdef USE_XIM 460#ifdef USE_XIM
282 if (!XFilterEvent (&xev, None)) 461 if (!XFilterEvent (&xev, None))
283 { 462 {
284 if (xev.type == PropertyNotify 463 if (xev.type == PropertyNotify
285 && xev.xany.window == root 464 && xev.xany.window == root
286 && xev.xproperty.atom == xa_xim_servers) 465 && xev.xproperty.atom == xa[XA_XIM_SERVERS])
287 im_change_check (); 466 im_change_check ();
288#endif 467#endif
289 for (int i = xw.size (); i--; ) 468 for (int i = xw.size (); i--; )
290 { 469 {
291 if (!xw[i]) 470 if (!xw[i])
379 558
380template class refcache<rxvt_display>; 559template class refcache<rxvt_display>;
381refcache<rxvt_display> displays; 560refcache<rxvt_display> displays;
382 561
383///////////////////////////////////////////////////////////////////////////// 562/////////////////////////////////////////////////////////////////////////////
384 563
385bool 564bool
386rxvt_color::set (rxvt_display *display, Pixel p) 565rxvt_color::alloc (rxvt_screen *screen, rxvt_rgba rgba)
387{ 566{
388#if XFT 567#if XFT
389 XColor xc; 568 XRenderPictFormat *format;
390 569
391 xc.pixel = p; 570 // FUCKING Xft gets it wrong, of course, so work around it
392 if (!XQueryColor (display->display, display->cmap, &xc)) 571 // transparency users should eat shit and die, and then
393 return false; 572 // XRenderQueryPictIndexValues themselves plenty.
573 if ((screen->visual->c_class == TrueColor || screen->visual->c_class == DirectColor)
574 && (format = XRenderFindVisualFormat (screen->xdisp, screen->visual)))
575 {
576 // the fun lies in doing everything manually...
577 c.color.red = rgba.r;
578 c.color.green = rgba.g;
579 c.color.blue = rgba.b;
580 c.color.alpha = rgba.a;
394 581
582 c.pixel = ((rgba.r * format->direct.redMask / rxvt_rgba::MAX_CC) << format->direct.red )
583 | ((rgba.g * format->direct.greenMask / rxvt_rgba::MAX_CC) << format->direct.green)
584 | ((rgba.b * format->direct.blueMask / rxvt_rgba::MAX_CC) << format->direct.blue )
585 | ((rgba.a * format->direct.alphaMask / rxvt_rgba::MAX_CC) << format->direct.alpha);
586
587 return true;
588 }
589 else
590 {
395 XRenderColor d; 591 XRenderColor d;
396 592
397 d.red = xc.red; 593 d.red = rgba.r;
398 d.green = xc.green; 594 d.green = rgba.g;
399 d.blue = xc.blue; 595 d.blue = rgba.b;
400 d.alpha = 0xffff; 596 d.alpha = rgba.a;
401 597
402 return 598 return XftColorAllocValue (screen->xdisp, screen->visual, screen->cmap, &d, &c);
403 XftColorAllocValue (display->display, 599 }
404 display->visual,
405 display->cmap,
406 &d, &c);
407#else 600#else
408 this->p = p; 601 if (screen->visual->c_class == TrueColor || screen->visual->c_class == DirectColor)
409#endif 602 {
603 p = (rgba.r * (screen->visual->red_mask >> ctz (screen->visual->red_mask ))
604 / rxvt_rgba::MAX_CC) << ctz (screen->visual->red_mask )
605 | (rgba.g * (screen->visual->green_mask >> ctz (screen->visual->green_mask))
606 / rxvt_rgba::MAX_CC) << ctz (screen->visual->green_mask)
607 | (rgba.b * (screen->visual->blue_mask >> ctz (screen->visual->blue_mask ))
608 / rxvt_rgba::MAX_CC) << ctz (screen->visual->blue_mask );
410 609
610 return true;
611 }
612 else
613 {
614 XColor xc;
615
616 xc.red = rgba.r;
617 xc.green = rgba.g;
618 xc.blue = rgba.b;
619
620 if (XAllocColor (screen->xdisp, screen->cmap, &xc))
621 {
622 p = xc.pixel;
411 return true; 623 return true;
624 }
625 else
626 p = (rgba.r + rgba.g + rgba.b) > 128*3
627 ? WhitePixelOfScreen (DefaultScreenOfDisplay (screen->xdisp))
628 : BlackPixelOfScreen (DefaultScreenOfDisplay (screen->xdisp));
629 }
630#endif
631
632 return false;
412} 633}
413 634
414bool 635bool
415rxvt_color::set (rxvt_display *display, const char *name) 636rxvt_color::set (rxvt_screen *screen, const char *name)
637{
638 rxvt_rgba c;
639 char eos;
640 int skip;
641
642 if (1 <= sscanf (name, "[%hx]%n", &c.a, &skip))
643 {
644 switch (skip)
645 {
646 case 2 + 1: c.a *= rxvt_rgba::MAX_CC / 0x000f; break;
647 case 2 + 2: c.a *= rxvt_rgba::MAX_CC / 0x00ff; break;
648 case 2 + 3: c.a *= rxvt_rgba::MAX_CC / 0x0fff; break;
649 case 2 + 4: c.a *= rxvt_rgba::MAX_CC / 0xffff; break;
650 }
651
652 name += skip;
653 }
654 else
655 c.a = rxvt_rgba::MAX_CC;
656
657 // parse the non-standard rgba format
658 if (strlen (name) != 4+5*4 || 4 != sscanf (name, "rgba:%hx/%hx/%hx/%hx%c", &c.r, &c.g, &c.b, &c.a, &eos))
659 {
660 XColor xc, xc_exact;
661
662 if (XParseColor (screen->xdisp, screen->cmap, name, &xc))
663 {
664 c.r = xc.red;
665 c.g = xc.green;
666 c.b = xc.blue;
667 }
668 else
669 {
670 c.r = 0xffff;
671 c.g = 0x6969;
672 c.b = 0xb4b4;
673
674 rxvt_warn ("unable to parse color '%s', using pink instead.\n", name);
675 }
676 }
677
678 return set (screen, c);
679}
680
681bool
682rxvt_color::set (rxvt_screen *screen, rxvt_rgba rgba)
683{
684 bool got = alloc (screen, rgba);
685
686#if !ENABLE_MINIMAL
687 int cmap_size = screen->visual->map_entries;
688
689 if (!got
690 && screen->visual->c_class == PseudoColor
691 && cmap_size < 4096)
692 {
693 XColor *colors = new XColor [screen->visual->map_entries];
694
695 for (int i = 0; i < cmap_size; i++)
696 colors [i].pixel = i;
697
698 XQueryColors (screen->xdisp, screen->cmap, colors, cmap_size);
699
700 int diff = 0x7fffffffUL;
701 XColor *best = colors;
702
703 for (int i = 0; i < cmap_size; i++)
704 {
705 int d = (squared_diff<int> (rgba.r >> 2, colors [i].red >> 2))
706 + (squared_diff<int> (rgba.g >> 2, colors [i].green >> 2))
707 + (squared_diff<int> (rgba.b >> 2, colors [i].blue >> 2));
708
709 if (d < diff)
710 {
711 diff = d;
712 best = colors + i;
713 }
714 }
715
716 //rxvt_warn ("could not allocate %04x %04x %04x, getting %04x %04x %04x instead (%d)\n",
717 // rgba.r, rgba.g, rgba.b, best->red, best->green, best->blue, diff);
718
719 got = alloc (screen, rxvt_rgba (best->red, best->green, best->blue));
720
721 delete colors;
722 }
723#endif
724
725 return got;
726}
727
728void
729rxvt_color::get (rxvt_screen *screen, rxvt_rgba &rgba)
416{ 730{
417#if XFT 731#if XFT
418 return XftColorAllocName (display->display, display->visual, display->cmap,
419 name, &c);
420#else
421 XColor xc;
422
423 if (XParseColor (display->display, display->cmap, name, &xc))
424 return set (display, xc.red, xc.green, xc.blue);
425
426 return false;
427#endif
428}
429
430bool
431rxvt_color::set (rxvt_display *display, unsigned short cr, unsigned short cg, unsigned short cb)
432{
433 XColor xc;
434
435 xc.red = cr;
436 xc.green = cg;
437 xc.blue = cb;
438 xc.flags = DoRed | DoGreen | DoBlue;
439
440 if (XAllocColor (display->display, display->cmap, &xc))
441 return set (display, xc.pixel);
442
443 return false;
444}
445
446void
447rxvt_color::get (rxvt_display *display, unsigned short &cr, unsigned short &cg, unsigned short &cb)
448{
449#if XFT
450 cr = c.color.red; 732 rgba.r = c.color.red;
451 cg = c.color.green; 733 rgba.g = c.color.green;
452 cb = c.color.blue; 734 rgba.b = c.color.blue;
735 rgba.a = c.color.alpha;
453#else 736#else
454 XColor c; 737 XColor c;
455 738
456 c.pixel = p; 739 c.pixel = p;
457 XQueryColor (display->display, display->cmap, &c); 740 XQueryColor (screen->xdisp, screen->cmap, &c);
458 741
459 cr = c.red; 742 rgba.r = c.red;
460 cg = c.green; 743 rgba.g = c.green;
461 cb = c.blue; 744 rgba.b = c.blue;
745 rgba.a = rxvt_rgba::MAX_CC;
462#endif 746#endif
463} 747}
464 748
465void 749void
466rxvt_color::free (rxvt_display *display) 750rxvt_color::free (rxvt_screen *screen)
467{ 751{
468#if XFT 752#if XFT
469 XftColorFree (display->display, display->visual, display->cmap, &c); 753 XftColorFree (screen->xdisp, screen->visual, screen->cmap, &c);
470#else 754#else
471 XFreeColors (display->display, display->cmap, &p, 1, AllPlanes); 755 XFreeColors (screen->xdisp, screen->cmap, &p, 1, AllPlanes);
472#endif 756#endif
473} 757}
474 758
475rxvt_color 759rxvt_color
476rxvt_color::fade (rxvt_display *display, int percent) 760rxvt_color::fade (rxvt_screen *screen, int percent)
477{ 761{
478 percent = 100 - percent;
479
480 unsigned short cr, cg, cb;
481 rxvt_color faded; 762 rxvt_color faded;
482 763
483 get (display, cr, cg, cb); 764 rxvt_rgba c;
765 get (screen, c);
484 766
485 faded.set ( 767 c.r = lerp (0, c.r, percent);
486 display, 768 c.g = lerp (0, c.g, percent);
487 cr * percent / 100, 769 c.b = lerp (0, c.b, percent);
488 cg * percent / 100, 770
489 cb * percent / 100 771 faded.set (screen, c);
490 );
491 772
492 return faded; 773 return faded;
493} 774}
494 775
495#define LERP(a,b,p) (a * p + b * (100 - p)) / 100
496
497rxvt_color 776rxvt_color
498rxvt_color::fade (rxvt_display *display, int percent, rxvt_color &fadeto) 777rxvt_color::fade (rxvt_screen *screen, int percent, rxvt_color &fadeto)
499{ 778{
500 percent = 100 - percent; 779 rxvt_rgba c, fc;
501
502 unsigned short cr, cg, cb;
503 unsigned short fcr, fcg, fcb;
504 rxvt_color faded; 780 rxvt_color faded;
505 781
506 get (display, cr, cg, cb); 782 get (screen, c);
507 fadeto.get(display, fcr, fcg, fcb); 783 fadeto.get (screen, fc);
508 784
509 faded.set ( 785 faded.set (
510 display, 786 screen,
787 rxvt_rgba (
511 LERP (cr, fcr, percent), 788 lerp (fc.r, c.r, percent),
512 LERP (cg, fcg, percent), 789 lerp (fc.g, c.g, percent),
513 LERP (cb, fcb, percent) 790 lerp (fc.b, c.b, percent),
791 lerp (fc.a, c.a, percent)
792 )
514 ); 793 );
515 794
516 return faded; 795 return faded;
517} 796}
518 797

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines