1 /* unicrud, Copyright (c) 2016-2017 Jamie Zawinski <jwz@jwz.org>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
12 #define DEFAULTS "*delay: 20000 \n" \
13 "*showFPS: False \n" \
14 "*suppressRotationAnimation: True\n" \
15 "*titleFont: -*-helvetica-bold-r-normal-*-*-180-*-*-*-*-*-*\n" \
16 "*font: -*-helvetica-bold-r-normal-*-*-2400-*-*-*-*-iso10646-1\n" \
18 # define free_unicrud 0
19 # define release_unicrud 0
21 #define countof(x) (sizeof((x))/sizeof((*x)))
23 #include "xlockmore.h"
25 #include "gltrackball.h"
30 #ifdef USE_GL /* whole file */
32 #define DEF_SPIN "True"
33 #define DEF_WANDER "True"
34 #define DEF_SPEED "1.0"
35 #define DEF_BLOCK "ALL"
36 #define DEF_TITLES "True"
39 GLXContext *glx_context;
41 trackball_state *trackball;
45 texture_font_data *title_font, *char_font;
46 unsigned long unichar;
47 const char *charplane, *charblock, *charname;
48 enum { IN, LINGER, OUT } state;
52 } unicrud_configuration;
54 static unicrud_configuration *bps = NULL;
58 static Bool do_wander;
59 static char *do_block;
60 static Bool do_titles;
62 static XrmOptionDescRec opts[] = {
63 { "-spin", ".spin", XrmoptionNoArg, "True" },
64 { "+spin", ".spin", XrmoptionNoArg, "False" },
65 { "-wander", ".wander", XrmoptionNoArg, "True" },
66 { "+wander", ".wander", XrmoptionNoArg, "False" },
67 { "-speed", ".speed", XrmoptionSepArg, 0 },
68 { "-block", ".block", XrmoptionSepArg, 0 },
69 { "-titles", ".titles", XrmoptionNoArg, "True" },
70 { "+titles", ".titles", XrmoptionNoArg, "False" },
73 static argtype vars[] = {
74 {&do_spin, "spin", "Spin", DEF_SPIN, t_Bool},
75 {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool},
76 {&speed, "speed", "Speed", DEF_SPEED, t_Float},
77 {&do_block, "block", "Block", DEF_BLOCK, t_String},
78 {&do_titles, "titles", "Titles", DEF_TITLES, t_Bool},
81 ENTRYPOINT ModeSpecOpt unicrud_opts = {countof(opts), opts, countof(vars), vars, NULL};
85 const char * const name;
86 } unicode_block_names[] = {
88 /* Through Unicode 8.0, early 2016. */
90 { 0x0000, "*Basic Multilingual" },
91 { 0x0000, "Unassigned" },
93 { 0x0080, "Unassigned" },
95 { 0x0100, "Latin Extended-A" },
96 { 0x0180, "Latin Extended-B" },
97 { 0x0250, "IPA Extensions" },
98 { 0x02B0, "Spacing Modifier Letters" },
99 { 0x0300, "Combining Diacritical Marks" },
100 { 0x0370, "Greek and Coptic" },
101 { 0x0400, "Cyrillic" },
102 { 0x0500, "Cyrillic Supplement" },
103 { 0x0530, "Armenian" },
104 { 0x058B, "Unassigned" },
105 { 0x0590, "Hebrew" },
106 { 0x05F5, "Unassigned" },
107 { 0x0600, "Arabic" },
108 { 0x0700, "Syriac" },
109 { 0x0750, "Arabic Supplement" },
110 { 0x0780, "Thaana" },
112 { 0x0800, "Samaritan" },
113 { 0x0840, "Mandaic" },
114 { 0x0860, "Unassigned" },
115 { 0x08A0, "Arabic Extended-A" },
116 { 0x0900, "Devanagari" },
117 { 0x0980, "Bengali" },
118 { 0x09FC, "Unassigned" },
119 { 0x0A00, "Gurmukhi" },
120 { 0x0A76, "Unassigned" },
121 { 0x0A80, "Gujarati" },
122 { 0x0AF2, "Unassigned" },
125 { 0x0BFB, "Unassigned" },
126 { 0x0C00, "Telugu" },
127 { 0x0C80, "Kannada" },
128 { 0x0CF0, "Unassigned" },
129 { 0x0D00, "Malayalam" },
130 { 0x0D80, "Sinhala" },
131 { 0x0DF5, "Unassigned" },
133 { 0x0E5C, "Unassigned" },
135 { 0x0EE0, "Unassigned" },
136 { 0x0F00, "Tibetan" },
137 { 0x0FDB, "Unassigned" },
138 { 0x1000, "Myanmar" },
139 { 0x10A0, "Georgian" },
140 { 0x1100, "Hangul Jamo" },
141 { 0x1200, "Ethiopic" },
142 { 0x1380, "Ethiopic Supplement" },
143 { 0x13A0, "Cherokee" },
144 { 0x1400, "Unified Canadian Aboriginal Syllabics" },
145 { 0x1677, "Unassigned" },
148 { 0x16F1, "Unassigned" },
149 { 0x1700, "Tagalog" },
150 { 0x1715, "Unassigned" },
151 { 0x1720, "Hanunoo" },
152 { 0x1737, "Unassigned" },
154 { 0x1754, "Unassigned" },
155 { 0x1760, "Tagbanwa" },
156 { 0x1774, "Unassigned" },
158 { 0x17FA, "Unassigned" },
159 { 0x1800, "Mongolian" },
160 { 0x18AB, "Unassigned" },
161 { 0x18B0, "Unified Canadian Aboriginal Syllabics Extended" },
162 { 0x18F6, "Unassigned" },
164 { 0x1950, "Tai Le" },
165 { 0x1975, "Unassigned" },
166 { 0x1980, "Tai Lue" },
167 { 0x19E0, "Khmer Symbols" },
168 { 0x1A00, "Buginese" },
169 { 0x1A20, "Tai Tham" },
170 { 0x1AAE, "Unassigned" },
171 { 0x1AB0, "Combining Diacritical Marks Extended" },
172 { 0x1ABF, "Unassigned" },
173 { 0x1B00, "Balinese" },
174 { 0x1B80, "Sundanese" },
176 { 0x1C00, "Lepcha" },
177 { 0x1C50, "Ol Chiki" },
178 { 0x1C80, "Unassigned" },
179 { 0x1CC0, "Sundanese Supplement" },
180 { 0x1CC8, "Unassigned" },
181 { 0x1CD0, "Vedic Extensions" },
182 { 0x1CFA, "Unassigned" },
183 { 0x1D00, "Phonetic Extensions" },
184 { 0x1D80, "Phonetic Extensions Supplement" },
185 { 0x1DC0, "Combining Diacritical Marks Supplement" },
186 { 0x1E00, "Latin Extended Additional" },
187 { 0x1F00, "Greek Extended" },
188 { 0x2000, "General Punctuation" },
189 { 0x2070, "Superscripts and Subscripts" },
190 { 0x2095, "Unassigned" },
191 { 0x20A0, "Currency Symbols" },
192 { 0x20BE, "Unassigned" },
193 { 0x20D0, "Combining Diacritical Marks for Symbols" },
194 { 0x20F1, "Unassigned" },
195 { 0x2100, "Letterlike Symbols" },
196 { 0x2150, "Number Forms" },
197 { 0x2190, "Arrows" },
198 { 0x2200, "Mathematical Operators" },
199 { 0x2300, "Miscellaneous Technical" },
200 { 0x2400, "Control Pictures" },
201 { 0x2437, "Unassigned" },
202 { 0x2440, "Optical Character Recognition" },
203 { 0x244B, "Unassigned" },
204 { 0x2460, "Enclosed Alphanumerics" },
205 { 0x2500, "Box Drawing" },
206 { 0x2580, "Block Elements" },
207 { 0x25A0, "Geometric Shapes" },
208 { 0x2600, "Miscellaneous Symbols" },
209 { 0x2700, "Dingbats" },
210 { 0x27C0, "Miscellaneous Mathematical Symbols-A" },
211 { 0x27F0, "Supplemental Arrows-A" },
212 { 0x2800, "Braille Patterns" },
213 { 0x2900, "Supplemental Arrows-B" },
214 { 0x2980, "Miscellaneous Mathematical Symbols-B" },
215 { 0x2A00, "Supplemental Mathematical Operators" },
216 { 0x2B00, "Miscellaneous Symbols and Arrows" },
217 { 0x2B56, "Unassigned" }, /* Unicode 5.1 */
218 { 0x2BF0, "Unassigned" },
219 { 0x2C00, "Glagolitic" },
220 { 0x2C60, "Latin Extended-C" },
221 { 0x2C80, "Coptic" },
222 { 0x2D00, "Georgian Supplement" },
223 { 0x2D26, "Unassigned" },
224 { 0x2D30, "Tifinagh" },
225 { 0x2D80, "Ethiopic Extended" },
226 { 0x2DE0, "Cyrillic Extended-A" },
227 { 0x2E00, "Supplemental Punctuation" },
228 { 0x2E43, "Unassigned" },
229 { 0x2E80, "CJK Radicals Supplement" },
230 { 0x2EF5, "Unassigned" },
231 { 0x2F00, "Kangxi Radicals" },
232 { 0x2FD6, "Unassigned" },
233 { 0x2FE0, "Unassigned" },
234 { 0x2FF0, "Ideographic Description Characters" },
235 { 0x2FFC, "Unassigned" },
236 { 0x3000, "CJK Symbols and Punctuation" },
237 { 0x3040, "Hiragana" },
238 { 0x30A0, "Katakana" },
239 { 0x3100, "Bopomofo" },
240 { 0x3130, "Hangul Compatibility Jamo" },
241 { 0x3190, "Kanbun" },
242 { 0x31A0, "Bopomofo Extended" },
243 { 0x31BB, "Unassigned" },
244 { 0x31C0, "CJK Strokes" },
245 { 0x31E4, "Unassigned" },
246 { 0x31F0, "Katakana Phonetic Extensions" },
247 { 0x3200, "Enclosed CJK Letters and Months" },
248 { 0x3300, "CJK Compatibility" },
249 { 0x3400, "CJK Unified Ideographs Extension A" },
250 { 0x4DB6, "Unassigned" },
251 { 0x4DC0, "Yijing Hexagram Symbols" },
252 { 0x4E00, "CJK Unified Ideographs" },
253 { 0x9FD6, "Unassigned" },
254 { 0xA000, "Yi Syllables" },
255 { 0xA48D, "Unassigned" },
256 { 0xA490, "Yi Radicals" },
257 { 0xA4C7, "Unassigned" },
260 { 0xA62C, "Unassigned" },
261 { 0xA640, "Cyrillic Extended-B" },
263 { 0xA700, "Modifier Tone Letters" },
264 { 0xA720, "Latin Extended-D" },
265 { 0xA800, "Syloti Nagri" },
266 { 0xA82C, "Unassigned" },
267 { 0xA830, "Common Indic Number Forms" },
268 { 0xA83A, "Unassigned" },
269 { 0xA840, "Phags-pa" },
270 { 0xA878, "Unassigned" },
271 { 0xA880, "Saurashtra" },
272 { 0xA8DA, "Unassigned" },
273 { 0xA8E0, "Devanagari Extended" },
274 { 0xA8FE, "Unassigned" },
275 { 0xA900, "Kayah Li" },
276 { 0xA930, "Rejang" },
277 { 0xA960, "Hangul Jamo Extended-A" },
278 { 0xA97D, "Unassigned" },
279 { 0xA980, "Javanese" },
280 { 0xA9E0, "Myanmar Extended-B" },
282 { 0xAA60, "Myanmar Extended-A" },
283 { 0xAA80, "Tai Viet" },
284 { 0xAAE0, "Meetei Mayek Extensions" },
285 { 0xAB00, "Ethiopic Extended-A" },
286 { 0xAB30, "Latin Extended-E" },
287 { 0xAB66, "Unassigned" },
288 { 0xAB70, "Cherokee Supplement" },
289 { 0xABC0, "Meetei Mayek" },
290 { 0xABFA, "Unassigned" },
291 { 0xAC00, "Hangul Syllables" },
292 { 0xD7B0, "Hangul Jamo Extended-B" },
293 { 0xD7FC, "Unassigned" },
294 /*{ 0xD800, "High Surrogates" }, */ /* UTF-16 compatibility */
295 /*{ 0xDC00, "Low Surrogates" }, */ /* UTF-16 compatibility */
296 { 0xE000, "Private Use Area" },
297 { 0xF900, "CJK Compatibility Ideographs" },
298 { 0xFAEA, "Unassigned" },
299 { 0xFB00, "Alphabetic Presentation Forms" },
300 { 0xFB50, "Arabic Presentation Forms-A" },
301 { 0xFE00, "Variation Selectors" },
302 { 0xFE10, "Vertical Forms" },
303 { 0xFE1A, "Unassigned" },
304 { 0xFE20, "Combining Half Marks" },
305 { 0xFE30, "CJK Compatibility Forms" },
306 { 0xFE50, "Small Form Variants" },
307 { 0xFE6C, "Unassigned" },
308 { 0xFE70, "Arabic Presentation Forms-B" },
309 { 0xFF00, "Halfwidth and Fullwidth Forms" },
310 { 0xFFF0, "Unassigned" },
311 { 0xFFF9, "Specials" },
312 { 0xFFFE, "Unassigned" },
314 { 0x10000, "*Supplementary Multilingual" },
315 { 0x10000, "Linear B Syllabary" },
316 { 0x1007E, "Unassigned" },
317 { 0x10080, "Linear B Ideograms" },
318 { 0x100FB, "Unassigned" },
319 { 0x10100, "Aegean Numbers" },
320 { 0x10140, "Ancient Greek Numbers" },
321 { 0x1018D, "Unassigned" },
322 { 0x10190, "Ancient Symbols" },
323 { 0x1019C, "Unassigned" },
324 { 0x101D0, "Phaistos Disc" },
325 { 0x10200, "Unassigned" },
326 { 0x10280, "Lycian" },
327 { 0x1029D, "Unassigned" },
328 { 0x102A0, "Carian" },
329 { 0x102D1, "Unassigned" },
330 { 0x102E0, "Coptic Epact Numbers" },
331 { 0x102FC, "Unassigned" },
332 { 0x10300, "Old Italic" },
333 { 0x10324, "Unassigned" },
334 { 0x10330, "Gothic" },
335 { 0x1034B, "Unassigned" },
336 { 0x10350, "Old Permic" },
337 { 0x10380, "Ugaritic" },
338 { 0x103A0, "Old Persian" },
339 { 0x103D6, "Unassigned" },
340 { 0x103E0, "Unassigned" },
341 { 0x10400, "Deseret" },
342 { 0x10450, "Shavian" },
343 { 0x10480, "Osmanya" },
344 { 0x104AA, "Unassigned" },
345 { 0x104B0, "Unassigned" },
346 { 0x10500, "Elbasan" },
347 { 0x10528, "Unassigned" },
348 { 0x10530, "Caucasian Albanian" },
349 { 0x10570, "Unassigned" },
350 { 0x10600, "Linear A" },
351 { 0x10768, "Unassigned" },
352 { 0x10780, "Unassigned" },
353 { 0x10800, "Cypriot Syllabary" },
354 { 0x10840, "Imperial Aramaic" },
355 { 0x10860, "Palmyrene" },
356 { 0x10880, "Nabataean" },
357 { 0x108B0, "Unassigned" },
358 { 0x108E0, "Hatran" },
359 { 0x10900, "Phoenician" },
360 { 0x10920, "Lydian" },
361 { 0x10940, "Unassigned" },
362 { 0x10980, "Meroitic Hieroglyphs" },
363 { 0x109A0, "Meroitic Cursive" },
364 { 0x10A00, "Kharoshthi" },
365 { 0x10A59, "Unassigned" },
366 { 0x10A60, "Old South Arabian" },
367 { 0x10A80, "Old North Arabian" },
368 { 0x10AA0, "Unassigned" },
369 { 0x10AC0, "Manichaean" },
370 { 0x10AF7, "Unassigned" },
371 { 0x10B00, "Avestan" },
372 { 0x10B40, "Inscriptional Parthian" },
373 { 0x10B60, "Inscriptional Pahlavi" },
374 { 0x10B80, "Psalter Pahlavi" },
375 { 0x10BB0, "Unassigned" },
376 { 0x10C00, "Old Turkic" },
377 { 0x10C49, "Unassigned" },
378 { 0x10C50, "Unassigned" },
379 { 0x10C80, "Old Hungarian" },
380 { 0x10D00, "Unassigned" },
381 { 0x10E60, "Rumi Numeral Symbols" },
382 { 0x10E80, "Unassigned" },
383 { 0x11000, "Brahmi" },
384 { 0x11070, "Unassigned" },
385 { 0x11080, "Kaithi" },
386 { 0x110C2, "Unassigned" },
387 { 0x110D0, "Sora Sompeng" },
388 { 0x110FA, "Unassigned" },
389 { 0x11100, "Chakma" },
390 { 0x11144, "Unassigned" },
391 { 0x11150, "Mahajani" },
392 { 0x11177, "Unassigned" },
393 { 0x11180, "Sharada" },
394 { 0x111E0, "Sinhala Archaic Numbers" },
395 { 0x111F5, "Unassigned" },
396 { 0x11200, "Khojki" },
397 { 0x1123E, "Unassigned" },
398 { 0x11250, "Unassigned" },
399 { 0x11280, "Multani" },
400 { 0x112AA, "Unassigned" },
401 { 0x112B0, "Khudawadi" },
402 { 0x112FA, "Unassigned" },
403 { 0x11300, "Grantha" },
404 { 0x11375, "Unassigned" },
405 { 0x11380, "Unassigned" },
406 { 0x11480, "Tirhuta" },
407 { 0x114DA, "Unassigned" },
408 { 0x114E0, "Unassigned" },
409 { 0x11580, "Siddham" },
410 { 0x115DE, "Unassigned" },
412 { 0x1165A, "Unassigned" },
413 { 0x11660, "Unassigned" },
414 { 0x11680, "Takri" },
415 { 0x116CA, "Unassigned" },
416 { 0x116D0, "Unassigned" },
418 { 0x11740, "Unassigned" },
419 { 0x118A0, "Warang Citi" },
420 { 0x11900, "Unassigned" },
421 { 0x11AC0, "Pau Cin Hau" },
422 { 0x11AF9, "Unassigned" },
423 { 0x11B00, "Unassigned" },
424 { 0x12000, "Cuneiform" },
425 { 0x1239A, "Unassigned" },
426 { 0x12400, "Cuneiform Numbers and Punctuation" },
427 { 0x12475, "Unassigned" },
428 { 0x12480, "Early Dynastic Cuneiform" },
429 { 0x12544, "Unassigned" },
430 { 0x12550, "Unassigned" },
431 { 0x13000, "Egyptian Hieroglyphs" },
432 { 0x13430, "Unassigned" },
433 { 0x14400, "Anatolian Hieroglyphs" },
434 { 0x14647, "Unassigned" },
435 { 0x14680, "Unassigned" },
436 { 0x16800, "Bamum Supplement" },
437 { 0x16A39, "Unassigned" },
439 { 0x16A70, "Unassigned" },
440 { 0x16AD0, "Bassa Vah" },
441 { 0x16AF6, "Unassigned" },
442 { 0x16B00, "Pahawh Hmong" },
443 { 0x16B90, "Unassigned" },
445 { 0x16FA0, "Unassigned" },
446 { 0x1B000, "Kana Supplement" },
447 { 0x1B002, "Unassigned" },
448 { 0x1B100, "Unassigned" },
449 { 0x1BC00, "Duployan Shorthand" },
450 { 0x1BCA4, "Unassigned" },
451 { 0x1BCB0, "Unassigned" },
452 { 0x1D000, "Byzantine Musical Symbols" },
453 { 0x1D0F5, "Unassigned" },
454 { 0x1D100, "Musical Symbols" },
455 { 0x1D1E9, "Unassigned" },
456 { 0x1D200, "Ancient Greek Musical Notation" },
457 { 0x1D246, "Unassigned" },
458 { 0x1D250, "Unassigned" },
459 { 0x1D300, "Tai Xuan Jing Symbols" },
460 { 0x1D357, "Unassigned" },
461 { 0x1D360, "Counting Rod Numerals" },
462 { 0x1D372, "Unassigned" },
463 { 0x1D380, "Unassigned" },
464 { 0x1D400, "Mathematical Alphanumeric Symbols" },
465 { 0x1D800, "Sutton SignWriting" },
466 { 0x1DAB0, "Unassigned" },
467 { 0x1E800, "Mende Kikakui" },
468 { 0X1E8D7, "Unassigned" },
469 { 0x1E8E0, "Unassigned" },
470 { 0x1EE00, "Arabic Mathematical Alphabetic Symbols" },
471 { 0X1EEFC, "Unassigned" },
472 { 0x1EF00, "Unassigned" },
473 { 0x1F000, "Mahjong Tiles" },
474 { 0x1F02C, "Unassigned" },
475 { 0x1F030, "Domino Tiles" },
476 { 0x1F094, "Unassigned" },
477 { 0x1F0A0, "Playing Cards" },
478 { 0x1F0F6, "Unassigned" },
479 { 0x1F100, "Enclosed Alphanumeric Supplement" },
480 { 0x1F19B, "Unassigned" },
481 { 0x1F1E6, "Enclosed Alphanumeric Supplement" },
482 { 0x1F200, "Enclosed Ideographic Supplement" },
483 { 0x1F252, "Unassigned" },
484 { 0x1F300, "Miscellaneous Symbols and Pictographs" },
485 { 0x1F600, "Emoticons" },
486 { 0x1F650, "Ornamental Dingbats" },
487 { 0x1F680, "Transport and Map Symbols" },
488 { 0x1F6F4, "Unassigned" },
489 { 0x1F700, "Alchemical Symbols" },
490 { 0x1F774, "Unassigned" },
491 { 0x1F780, "Geometric Shapes Extended" },
492 { 0x1F7D5, "Unassigned" },
493 { 0x1F800, "Supplemental Arrows-C" },
494 { 0x1F8AD, "Unassigned" },
495 { 0x1F910, "Supplemental Symbols and Pictographs" },
496 { 0x1F9C1, "Unassigned" },
497 { 0x1FA00, "Unassigned" },
499 { 0x20000, "*Supplementary Ideographic" },
500 { 0x20000, "CJK Unified Ideographs Extension B" },
501 { 0x2A6D7, "Unassigned" },
502 { 0x2A6E0, "Unassigned" },
503 { 0x2A700, "CJK Unified Ideographs Extension C" },
504 { 0x2B740, "Unassigned" },
505 { 0x2B740, "CJK Unified Ideographs Extension D" },
506 { 0x2B820, "Unassigned" },
507 { 0x2B820, "CJK Unified Ideographs Extension E" },
508 { 0x2CEA2, "Unassigned" },
509 { 0x2CEB0, "Unassigned" },
510 { 0x2F800, "CJK Compatibility Ideographs Supplement" },
511 { 0x2FA20, "Unassigned" },
513 { 0x30000, "*Unassigned Plane 3" },
514 { 0x40000, "*Unassigned Plane 4" },
515 { 0x50000, "*Unassigned Plane 5" },
516 { 0x60000, "*Unassigned Plane 6" },
517 { 0x70000, "*Unassigned Plane 7" },
518 { 0x80000, "*Unassigned Plane 8" },
519 { 0x90000, "*Unassigned Plane 9" },
520 { 0xA0000, "*Unassigned Plane 10" },
521 { 0xB0000, "*Unassigned Plane 11" },
522 { 0xC0000, "*Unassigned Plane 12" },
523 { 0xD0000, "*Unassigned Plane 13" },
525 { 0xE0000, "*Supplementary Special-Purpose" },
526 { 0xE0080, "Unassigned" },
528 { 0xE0080, "Unassigned" },
529 { 0xE0100, "Variation Selectors Supplement" },
530 { 0xE01F0, "Unassigned" },
532 { 0xF0000, "*Supplementary Private Use Area A" },
533 { 0x100000, "*Supplementary Private Use Area B" },
541 while (*s == ' ' || *s == '\t' || *s == '\n')
544 while (s[L-1] == ' ' || s[L-1] == '\t' || s[L-1] == '\n')
550 /* matches ("AA, BB, CC", "CC") => True
551 matches ("AA, BB, CC", "CCx") => False
554 matches (const char *pattern, const char *string)
556 char *token = strdup (pattern ? pattern : "");
557 char *otoken = token;
560 while ((name = strtok (token, ","))) {
563 if (*name && !strcasecmp (name, string))
576 pick_unichar (ModeInfo *mi)
578 unicrud_configuration *bp = &bps[MI_SCREEN(mi)];
580 unsigned long min = 0;
581 unsigned long max = 0x2F800;
582 unsigned long last = 0;
586 bp->unichar = min + (random() % (max - min));
588 if (++retries > 0xF0000 / 2)
590 fprintf (stderr, "%s: internal error: too many retries\n", progname);
594 /* bp->unichar = 0x1F4A9; */
597 bp->charplane = "Unassigned";
598 bp->charblock = "Unassigned";
599 for (i = 0; i < countof(unicode_block_names); i++)
601 if (unicode_block_names[i].start < last)
603 fprintf (stderr, "%s: progname: internal error: misordered: 0x%lX\n",
604 progname, unicode_block_names[i].start);
607 last = unicode_block_names[i].start;
608 if (bp->unichar >= unicode_block_names[i].start)
610 if (unicode_block_names[i].name[0] == '*')
612 bp->charplane = unicode_block_names[i].name + 1;
613 bp->charblock = "Unassigned";
616 bp->charblock = unicode_block_names[i].name;
622 if (!strncmp (bp->charblock, "Unassigned", 10) ||
623 !strncmp (bp->charblock, "Combining", 9))
626 if (*do_block && !matches (do_block, bp->charblock))
629 /* Skip blank characters */
633 i = utf8_encode (bp->unichar, text, sizeof(text) - 1);
635 texture_string_metrics (bp->char_font, text, &e, 0, 0);
636 if (e.width < 2 || e.ascent + e.descent < 2)
641 bp->charname = texfont_unicode_character_name (bp->char_font, bp->unichar);
644 bp->color[0] = 0.5 + frand(0.5);
645 bp->color[1] = 0.5 + frand(0.5);
646 bp->color[2] = 0.5 + frand(0.5);
652 draw_unichar (ModeInfo *mi)
654 unicrud_configuration *bp = &bps[MI_SCREEN(mi)];
662 i = utf8_encode (bp->unichar, text, sizeof(text) - 1);
666 sprintf (title + strlen(title), "Plane:\t%s\n", bp->charplane);
667 sprintf (title + strlen(title), "Block:\t%s\n", bp->charblock);
669 sprintf (title + strlen(title), "Name:\t%s\n",
670 (bp->charname ? bp->charname : ""));
672 sprintf (title + strlen(title), "Unicode:\t%04lX\n", bp->unichar);
673 sprintf (title + strlen(title), "UTF-8:\t");
674 for (j = 0; j < i; j++)
675 sprintf (title + strlen(title), "%02X ", ((unsigned char *)text)[j]);
677 texture_string_metrics (bp->char_font, text, &e, 0, 0);
684 s = 1.0 / (h > w ? h : w); /* Scale to unit */
687 glTranslatef (-w/2, -h/2, 0);
688 glColor4fv (bp->color);
689 print_texture_string (bp->char_font, text);
693 print_texture_label (mi->dpy, bp->title_font,
694 mi->xgwa.width, mi->xgwa.height,
699 /* Window management, etc
702 reshape_unicrud (ModeInfo *mi, int width, int height)
704 GLfloat h = (GLfloat) height / (GLfloat) width;
707 if (width > height * 5) { /* tiny window: show middle */
708 height = width * 9/16;
710 h = height / (GLfloat) width;
713 glViewport (0, y, (GLint) width, (GLint) height);
715 glMatrixMode(GL_PROJECTION);
717 gluPerspective (30.0, 1/h, 1.0, 100.0);
719 glMatrixMode(GL_MODELVIEW);
721 gluLookAt( 0.0, 0.0, 30.0,
725 # ifdef HAVE_MOBILE /* Keep it the same relative size when rotated. */
727 int o = (int) current_device_rotation();
728 if (o != 0 && o != 180 && o != -180)
729 glScalef (1/h, 1/h, 1/h);
733 glClear(GL_COLOR_BUFFER_BIT);
738 unicrud_handle_event (ModeInfo *mi, XEvent *event)
740 unicrud_configuration *bp = &bps[MI_SCREEN(mi)];
742 if (gltrackball_event_handler (event, bp->trackball,
743 MI_WIDTH (mi), MI_HEIGHT (mi),
746 else if (event->xany.type == KeyPress)
750 XLookupString (&event->xkey, &c, 1, &keysym, 0);
751 if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
753 if (bp->state == LINGER) bp->ratio = 1;
763 init_unicrud (ModeInfo *mi)
765 unicrud_configuration *bp;
769 bp = &bps[MI_SCREEN(mi)];
771 bp->glx_context = init_GL(mi);
773 reshape_unicrud (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
776 double spin_speed = 0.05;
777 double wander_speed = 0.01;
778 double spin_accel = 1.0;
780 bp->rot = make_rotator (do_spin ? spin_speed : 0,
781 do_spin ? spin_speed : 0,
782 do_spin ? spin_speed : 0,
784 do_wander ? wander_speed : 0,
786 bp->trackball = gltrackball_init (True);
789 bp->title_font = load_texture_font (mi->dpy, "titleFont");
790 bp->char_font = load_texture_font (mi->dpy, "font");
793 bp->spin_direction = (random() & 1) ? 1 : -1;
797 if (matches ("all", do_block))
802 for (s = do_block; *s; s++)
803 if (*s == '_') *s = ' ';
806 if (matches ("help", do_block))
810 "%s: --blocks must contain one or more of these,"
811 " separated by commas:\n\n", progname);
812 for (i = 0; i < countof(unicode_block_names); i++)
814 const char *n = unicode_block_names[i].name;
817 if (!strncmp (n, "Unassigned", 10) ||
818 !strncmp (n, "Combining", 9))
820 fprintf (stderr, "\t%s\n", n);
822 fprintf (stderr, "\n");
827 /* Make sure all elements in --block are valid.
831 char *token = strdup (do_block ? do_block : "");
832 char *otoken = token;
834 while ((name = strtok (token, ","))) {
841 for (i = 0; i < countof(unicode_block_names); i++)
843 const char *n = unicode_block_names[i].name;
846 if (!strncmp (n, "Unassigned", 10) ||
847 !strncmp (n, "Combining", 9))
849 if (!strcasecmp (name, n))
857 fprintf (stderr, "%s: unknown block name: \"%s\"\n",
859 fprintf (stderr, "%s: use '--block help' for a list\n",
873 draw_unicrud (ModeInfo *mi)
875 unicrud_configuration *bp = &bps[MI_SCREEN(mi)];
876 Display *dpy = MI_DISPLAY(mi);
877 Window window = MI_WINDOW(mi);
879 if (!bp->glx_context)
882 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
884 glShadeModel (GL_FLAT);
885 glEnable (GL_NORMALIZE);
886 glDisable (GL_CULL_FACE);
887 glDisable (GL_LIGHTING);
889 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
891 if (! bp->button_down_p)
893 case IN: bp->ratio += speed * 0.05; break;
894 case OUT: bp->ratio += speed * 0.05; break;
895 case LINGER: bp->ratio += speed * 0.005; break;
908 bp->spin_direction = (random() & 1) ? 1 : -1;
922 get_position (bp->rot, &x, &y, &z, !bp->button_down_p);
923 glTranslatef((x - 0.5) * 6,
927 gltrackball_rotate (bp->trackball);
929 get_rotation (bp->rot, &x, &y, &z, !bp->button_down_p);
931 glRotatef (x * 360, 1.0, 0.0, 0.0);
932 glRotatef (y * 360, 0.0, 1.0, 0.0);
933 glRotatef (z * 360, 0.0, 0.0, 1.0);
936 # define SINOID(N) (sin(M_PI - (N) / 2 * M_PI))
940 case IN: s = SINOID (bp->ratio); break;
941 case OUT: s = SINOID (1-bp->ratio); break;
942 default: s = 1; break;
945 glRotatef (360 * s * bp->spin_direction * (bp->state == IN ? -1 : 1),
953 if (mi->fps_p) do_fps (mi);
956 glXSwapBuffers(dpy, window);
959 XSCREENSAVER_MODULE_2 ("Unicrud", unicrud, unicrud)