Releasing version 3-2014010501
[notion/jeffpc.git] / de / fontset.c
blob3ab85d51531be3179167d39a5a97b340828076e8
1 /*
2 * notion/de/fontset.c
3 *
4 * This file contains routines to attempt to add fonts to a font pattern
5 * so that XCreateFontSet will not fail because the given font(s) do not
6 * contain all the characters required by the locale.
8 * The original code was apparently written by Tomohiro Kubota; see
9 * <http://www.debian.org/doc/manuals/intro-i18n/ch-examples.en.html#s13.4.5>.
11 * However, the code that this file is based on, was taken from:
13 * Copyright (c) 2013 - the Notion team
14 * Screen.cc for Blackbox - an X11 Window manager
15 * Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
16 * Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
18 * Permission is hereby granted, free of charge, to any person obtaining a
19 * copy of this software and associated documentation files (the "Software"),
20 * to deal in the Software without restriction, including without limitation
21 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
22 * and/or sell copies of the Software, and to permit persons to whom the
23 * Software is furnished to do so, subject to the following conditions:
25 * The above copyright notice and this permission notice shall be included in
26 * all copies or substantial portions of the Software.
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
31 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
33 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
34 * DEALINGS IN THE SOFTWARE.
37 #include <string.h>
38 #include <ctype.h>
39 #include <locale.h>
41 #include <ioncore/common.h>
42 #include <ioncore/global.h>
43 #include <ioncore/log.h>
45 #ifndef CF_FONT_ELEMENT_SIZE
46 #define CF_FONT_ELEMENT_SIZE 50
47 #endif
49 static const char *get_font_element(const char *pattern, char *buf,
50 int bufsiz, ...)
52 const char *p, *v;
53 char *p2;
54 va_list va;
56 va_start(va, bufsiz);
57 buf[bufsiz-1]=0;
58 buf[bufsiz-2]='*';
59 while((v=va_arg(va, char *))!=NULL){
60 p=libtu_strcasestr(pattern, v);
61 if(p){
62 strncpy(buf, p+1, bufsiz-2);
63 p2=strchr(buf, '-');
64 if(p2) *p2=0;
65 va_end(va);
66 return p;
69 va_end(va);
70 strncpy(buf, "*", bufsiz);
71 return NULL;
75 static const char *get_font_size(const char *pattern, int *size)
77 const char *p;
78 const char *p2=NULL;
79 int n=0;
81 for(p=pattern; 1; p++){
82 if(!*p){
83 if(p2!=NULL && n>1 && n<72){
84 *size=n; return p2+1;
85 }else{
86 *size=16; return NULL;
88 }else if(*p=='-'){
89 if(n>1 && n<72 && p2!=NULL){
90 *size=n;
91 return p2+1;
93 p2=p; n=0;
94 }else if(*p>='0' && *p<='9' && p2!=NULL){
95 n*=10;
96 n+=*p-'0';
97 }else{
98 p2=NULL; n=0;
103 XFontSet de_create_font_in_current_locale(const char *fontname)
105 XFontSet fs;
106 char **missing=NULL, *def="-";
107 int nmissing=0;
108 int i;
110 LOG(DEBUG, FONT, "Creating fontset for: %s", fontname);
112 fs=XCreateFontSet(ioncore_g.dpy, fontname, &missing, &nmissing, &def);
114 if(fs){
115 if(nmissing==0)
116 LOG(DEBUG, FONT, "Found a font without missing charsets for %s, returning it.", fontname);
117 else {
118 int i;
119 LOG(INFO, FONT, "Found a font with %d missing charsets for %s:", nmissing, fontname);
120 for(i=0;i<nmissing;i++)
121 LOG(DEBUG, FONT, "* %s", missing[i]);
123 }else{
124 LOG(WARN, FONT, "Found no font for %s.", fontname);
127 if(missing!=NULL)
128 XFreeStringList(missing);
130 return fs;
133 XFontSet de_create_font_in_c_locale(const char *fontname)
135 XFontSet fs;
136 char *lcc=NULL;
137 const char *lc;
139 LOG(DEBUG, FONT, "Trying to load %s with the C locale.", fontname);
141 lc=setlocale(LC_CTYPE, NULL);
142 if(lc!=NULL && strcmp(lc, "POSIX")!=0 && strcmp(lc, "C")!=0)
143 lcc=scopy(lc);
145 setlocale(LC_CTYPE, "C");
147 fs=de_create_font_in_current_locale(fontname);
149 if(lcc!=NULL){
150 setlocale(LC_CTYPE, lcc);
151 free(lcc);
154 return fs;
158 XFontSet de_create_font_kludged(const char *fontname)
160 XFontSet fs = NULL;
161 #ifndef CF_NO_FONTSET_KLUDGE
162 char *pattern2=NULL;
163 char weight[CF_FONT_ELEMENT_SIZE], slant[CF_FONT_ELEMENT_SIZE];
164 int pixel_size=0;
166 LOG(DEBUG, FONT, "Doing the fontset_kludge with fontname %s.", fontname);
168 get_font_element(fontname, weight, CF_FONT_ELEMENT_SIZE,
169 "-medium-", "-bold-", "-demibold-", "-regular-", NULL);
170 get_font_element(fontname, slant, CF_FONT_ELEMENT_SIZE,
171 "-r-", "-i-", "-o-", "-ri-", "-ro-", NULL);
172 get_font_size(fontname, &pixel_size);
174 if(!strcmp(weight, "*"))
175 strncpy(weight, "medium", CF_FONT_ELEMENT_SIZE);
176 if(!strcmp(slant, "*"))
177 strncpy(slant, "r", CF_FONT_ELEMENT_SIZE);
178 if(pixel_size<3)
179 pixel_size=3;
180 else if(pixel_size>97)
181 pixel_size=97;
183 if(ioncore_g.enc_utf8){
184 libtu_asprintf(&pattern2,
185 "%s,"
186 "-misc-fixed-%s-%s-*-*-%d-*-*-*-*-*-*-*,"
187 "-misc-fixed-*-*-*-*-%d-*-*-*-*-*-*-*",
188 fontname, weight, slant, pixel_size, pixel_size);
189 }else{
190 libtu_asprintf(&pattern2,
191 "%s,"
192 "-*-*-%s-%s-*-*-%d-*-*-*-*-*-*-*,"
193 "-*-*-*-*-*-*-%d-*-*-*-*-*-*-*",
194 fontname, weight, slant, pixel_size, pixel_size);
197 if(pattern2!=NULL){
198 LOG(DEBUG, FONT, "no_fontset_kludge resulted in fontname %s", pattern2);
200 fs = de_create_font_in_current_locale(pattern2);
202 free(pattern2);
205 #endif
206 return fs;
209 XFontSet de_create_font_set(const char *fontname)
211 XFontSet fs=de_create_font_in_current_locale(fontname);
213 if (fs)
214 return fs;
216 fs=de_create_font_in_c_locale(fontname);
218 if (fs)
219 return fs;
220 else
221 return de_create_font_kludged(fontname);