3c19244a159f50fd65ed929ebb9f639cf321c4e2
[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         FcChar32        font_count[NUM_FONTS];
28         XftDraw*        draw;
29         XftColor        font_color;
30         XColor          bg_color;
31 };
32
33 static void *
34 unicode_init (Display *dpy, Window window)
35 {
36         struct unicode_state *state = malloc(sizeof(struct unicode_state));
37         Colormap cmap;
38         XWindowAttributes xgwa;
39         int i;
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, "DejaVu Sans",
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         for (i = 0; i < NUM_FONTS; i++) {
62                 state->font_count[i] = FcCharSetCount(state->fonts[i]->charset);
63                 // printf("Font count: %d\n",state->font_count[i]);
64         }
65
66         state->draw = XftDrawCreate(dpy, window, xgwa.visual, cmap); 
67         state->bg_color.pixel = get_pixel_resource(dpy, cmap, "background", "Background");
68         XQueryColor(dpy, cmap, &state->bg_color);
69
70         XColor color;
71         color.pixel = get_pixel_resource(dpy, cmap, "foreground", "Foreground");
72         XQueryColor(dpy, cmap, &color);
73
74         XRenderColor font_color;
75         font_color.red = color.red;
76         font_color.green = color.green;
77         font_color.blue = color.blue;
78         font_color.alpha = 0xFFFF;
79
80         XftColorAllocValue(dpy, xgwa.visual, cmap, &font_color, &state->font_color);
81         XSetWindowBackground(dpy, window, state->bg_color.pixel);
82         XClearWindow (dpy, window);
83
84         return state;
85 }
86
87 /* does a binary search on unicode_names */
88 /* (From gucharmap code) */
89 static const char *
90 get_unicode_data_name (FcChar32 uc)
91 {
92         unsigned long min = 0;
93         unsigned long mid;
94         unsigned long max = (sizeof(unicode_names)/sizeof(unicode_names[0])) - 1;
95
96         if (uc < unicode_names[0].index || uc > unicode_names[max].index)
97                 return "Out of range";
98
99         while (max >= min)
100         {
101                 mid = (min + max) / 2;
102                 if (uc > unicode_names[mid].index)
103                         min = mid + 1;
104                 else if (uc < unicode_names[mid].index)
105                         max = mid - 1;
106                 else
107                         return unicode_name_get_name(&unicode_names[mid]);
108         }
109
110         return "something is wrong";
111 }
112
113
114 static unsigned long
115 unicode_draw (Display *dpy, Window win, void *void_state) {
116         XGlyphInfo      extents;
117         FcChar32        ucs4;
118         FcChar32        map[FC_CHARSET_MAP_SIZE];
119         FcChar32        next;
120         FcChar32        pickn;
121         FcChar32        pickc;
122         FcChar32        pick;   
123         char            name[100];
124         int             font;
125         struct unicode_state *state = (struct unicode_state *)void_state;
126
127         if (state->blank) {
128                 XWindowAttributes xgwa;
129                 XGetWindowAttributes (dpy, win, &xgwa);
130
131                 font = random() % NUM_FONTS;
132
133                 pickn = random() % state->font_count[font];     
134
135                 pickc = 0;
136                 for (ucs4 = FcCharSetFirstPage (state->fonts[font]->charset, map, &next);
137                      ucs4 != FC_CHARSET_DONE;
138                      ucs4 = FcCharSetNextPage (state->fonts[font]->charset, map, &next))
139                 {
140                     int     i, j;
141                     for (i = 0; i < FC_CHARSET_MAP_SIZE; i++)
142                         if (map[i])
143                             for (j = 0; j < 32; j++)
144                                 if (map[i] & (1 << j))
145                                     if (pickc++ == pickn) 
146                                         pick = ucs4 + i * 32 + j;
147                 }
148                 
149
150                 // printf("Picked font %d, pickn %d, U+%04X\n", font, pickn, pick);
151                 sprintf(name,"U+%04X: ",pick);
152                 strcat(name, get_unicode_data_name(pick));
153
154                 XftTextExtents32(dpy,state->fonts[font],&pick,1,&extents); 
155                 XftDrawString32(state->draw,&state->font_color,state->fonts[font],
156                         xgwa.width/2  - extents.width/2  + extents.x,
157                         xgwa.height/2 - extents.height/2 + extents.y,
158                         &pick,1); 
159
160                 XftDrawStringUtf8(state->draw,&state->font_color,state->tfont,
161                         5,
162                         xgwa.height - 5,
163                         (unsigned char *)name,strlen(name)); 
164                 XSync (dpy, False);
165
166                 state->blank = False;
167                 return (7*1000*1000);
168         } else {
169                 XClearWindow (dpy, win);
170                 XSync (dpy, False);
171                 state->blank = True;
172                 return (1000*1000);
173         }
174
175 }
176
177 static void
178 unicode_reshape (Display *dpy, Window window, void *state,
179                  unsigned int width, unsigned int height) {
180 }               
181
182 static Bool
183 unicode_event (Display *dpy, Window window, void *state,
184                  XEvent *event) {
185                  return False;
186 }               
187
188 static void
189 unicode_free (Display *dpy, Window window, void *state) {
190 }               
191
192
193 char *progclass = "Unicode";
194
195 static char const *unicode_defaults [] = {
196   ".background: white",
197   ".foreground: black",
198   "*delay:      7",
199   0
200 };
201
202 static XrmOptionDescRec unicode_options [] = {
203   { "-delay",           ".delay",               XrmoptionSepArg, 0 },
204   { "-foreground",      ".foreground",          XrmoptionSepArg, 0 },
205   { "-background",      ".background",          XrmoptionSepArg, 0 },
206   { 0, 0, 0, 0 }
207 };
208
209 XSCREENSAVER_MODULE("Unicode",unicode)