6be60a6269071d4cdc85465acb30ff4ab559ab4f
[unicode-screensaver.git] / unicode.c
1 /* unicode (c) 2006,2009
2  * Joachim Breitner <mail@joachim-breitner.de>
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation.  No representations are made about the suitability of this
9  * software for any purpose.  It is provided "as is" without express or 
10  * implied warranty.
11  *
12  */
13
14 #include <X11/Xft/Xft.h>
15
16 #include "unicode-names.h"
17 #include "screenhack.h"
18
19 #define NUM_FONTS 2
20
21
22 struct unicode_state {
23         Bool blank;
24
25         XftFont*        fonts[NUM_FONTS];
26         XftFont*        tfont;
27         XftDraw*        draw;
28         XftColor        font_color;
29         XColor          bg_color;
30 };
31
32 static void *
33 unicode_init (Display *dpy, Window window)
34 {
35         struct unicode_state *state = malloc(sizeof(struct unicode_state));
36         Colormap cmap;
37         XWindowAttributes xgwa;
38         XColor color;
39         XRenderColor font_color;
40
41         XGetWindowAttributes (dpy, window, &xgwa);
42         state->blank = True;
43
44         cmap = xgwa.colormap;
45
46         state->fonts[0] = XftFontOpen(dpy, 0,
47                 XFT_FAMILY,  XftTypeString, "Open Symbol",
48                 XFT_PIXEL_SIZE, XftTypeInteger, xgwa.height-100,
49                 NULL
50                 );
51         state->fonts[1] = XftFontOpen(dpy, 0,
52                 XFT_FAMILY,  XftTypeString, "FreeSans",
53                 XFT_PIXEL_SIZE, XftTypeInteger, xgwa.height-100,
54                 NULL
55                 );
56         state->tfont = XftFontOpen(dpy, 0,
57                 XFT_FAMILY,  XftTypeString, "FreeSans",
58                 XFT_PIXEL_SIZE, XftTypeInteger, 40,
59                 NULL
60                 );
61
62         state->draw = XftDrawCreate(dpy, window, xgwa.visual, cmap); 
63         state->bg_color.pixel = get_pixel_resource(dpy, cmap, "background", "Background");
64         XQueryColor(dpy, cmap, &state->bg_color);
65
66         color.pixel = get_pixel_resource(dpy, cmap, "foreground", "Foreground");
67         XQueryColor(dpy, cmap, &color);
68
69         font_color.red = color.red;
70         font_color.green = color.green;
71         font_color.blue = color.blue;
72         font_color.alpha = 0xFFFF;
73
74         XftColorAllocValue(dpy, xgwa.visual, cmap, &font_color, &state->font_color);
75         XSetWindowBackground(dpy, window, state->bg_color.pixel);
76         XClearWindow (dpy, window);
77
78         return state;
79 }
80
81 static unsigned long
82 unicode_draw (Display *dpy, Window win, void *void_state) {
83         XGlyphInfo      extents;
84         FcChar32        pick;
85         char            name[100];
86         int             font;
87         int             i;
88         struct unicode_state *state = (struct unicode_state *)void_state;
89         unsigned long unicode_names_length
90                 = (sizeof(unicode_names)/sizeof(unicode_names[0]));
91         const UnicodeName* nameEntry;
92
93         if (state->blank) {
94                 XWindowAttributes xgwa;
95                 XGetWindowAttributes (dpy, win, &xgwa);
96
97                 /* Find a unicode character that is contained in one of the fonts
98                    We try 100 random points before sleeping, to avoid an endless cycle */
99                 for (i = 0; i < 100; i++) {
100                         nameEntry = &unicode_names[random() % unicode_names_length];
101                         pick = nameEntry->index;
102                         /* printf("Trying U+%04X\n", pick); */
103
104                         for (font = 0; font < NUM_FONTS; font++) {
105                                 if (XftCharExists (dpy, state->fonts[font], pick)) break;
106                         }
107                         if (font < NUM_FONTS) break;
108                 }
109                 if (i == 100) return (1000*1000);
110
111                 /* printf("Picked font %d, U+%04X\n", font, pick); */
112                 sprintf(name,"U+%04X: ", pick);
113                 strcat(name, unicode_name_get_name(nameEntry));
114
115                 XftTextExtents32(dpy,state->fonts[font],&pick,1,&extents); 
116                 XftDrawString32(state->draw,&state->font_color,state->fonts[font],
117                         xgwa.width/2  - extents.width/2  + extents.x,
118                         xgwa.height/2 - extents.height/2 + extents.y,
119                         &pick,1); 
120
121                 XftDrawStringUtf8(state->draw,&state->font_color,state->tfont,
122                         5,
123                         xgwa.height - 5,
124                         (unsigned char *)name,strlen(name)); 
125                 XSync (dpy, False);
126
127                 state->blank = False;
128                 return (get_seconds_resource(dpy, "delay", "Delay")*1000*1000);
129         } else {
130                 XClearWindow (dpy, win);
131                 XSync (dpy, False);
132                 state->blank = True;
133                 return (1000*1000);
134         }
135
136 }
137
138 static void
139 unicode_reshape (Display *dpy, Window window, void *state,
140                  unsigned int width, unsigned int height) {
141 }               
142
143 static Bool
144 unicode_event (Display *dpy, Window window, void *state,
145                  XEvent *event) {
146                  return False;
147 }               
148
149 static void
150 unicode_free (Display *dpy, Window window, void *state) {
151 }               
152
153
154 char *progclass = "Unicode";
155
156 static char const *unicode_defaults [] = {
157   ".background: white",
158   ".foreground: black",
159   "*delay:      7",
160   0
161 };
162
163 static XrmOptionDescRec unicode_options [] = {
164   { "-delay",           ".delay",               XrmoptionSepArg, 0 },
165   { "-foreground",      ".foreground",          XrmoptionSepArg, 0 },
166   { "-background",      ".background",          XrmoptionSepArg, 0 },
167   { 0, 0, 0, 0 }
168 };
169
170 XSCREENSAVER_MODULE("Unicode",unicode)