1 /*
2  * wmslib/src/but/write.c, part of wmslib (Library functions)
3  * Copyright (C) 1994 William Shubert.
4  * See "configure.h.in" for more copyright information.
5  */
6 
7 #include <configure.h>
8 
9 #ifdef  X11_DISP
10 
11 #ifdef  STDC_HEADERS
12 #include <stdlib.h>
13 #include <unistd.h>
14 #endif  /* STDC_HEADERS */
15 #include <stdio.h>
16 #include <X11/Xlib.h>
17 #include <X11/Xutil.h>
18 #include <X11/cursorfont.h>
19 #include <X11/Xatom.h>
20 #include <X11/keysym.h>
21 #include <sys/time.h>
22 #ifdef  HAVE_SYS_SELECT_H
23 #include <sys/select.h>
24 #endif
25 #include <wms.h>
26 #include <but/but.h>
27 #include <but/write.h>
28 
29 
butEnv_setChar(ButEnv * env,double width,const char * id,void (* draw)(void * packet,ButWin * win,int x,int y,int w,int h),void * packet)30 void  butEnv_setChar(ButEnv *env, double width, const char *id,
31 		     void (*draw)(void *packet, ButWin *win,
32 				  int x, int y, int w, int h), void *packet)  {
33   int  idval;
34 
35   idval = ((int)(uchar)id[0] << 8) + (uchar)id[1] - 256;
36   env->write[idval].width = width;
37   env->write[idval].packet = packet;
38   env->write[idval].draw = draw;
39 }
40 
41 
butEnv_textWidth(ButEnv * env,const char * text,int fnum)42 int  butEnv_textWidth(ButEnv *env, const char *text, int fnum)  {
43   uchar  c;
44   int  special;
45   int  total = 0, min_char, std_width;
46   XCharStruct  *charlist;
47 
48   if (env->fonts[fnum]->per_char != NULL)  {
49     charlist = env->fonts[fnum]->per_char;
50     min_char = env->fonts[fnum]->min_char_or_byte2;
51     for (;;)  {
52       c = text[0];
53       ++text;
54       switch(c)  {
55       case '\0':
56 	return(total);
57 	break;
58       case '\1':
59       case '\2':
60 	special = 256 * (c - 1) + text[0];
61 	++text;
62 	assert(env->write[special].draw != NULL);
63 	total += (env->fonts[fnum]->ascent + env->fonts[fnum]->descent) *
64 	  env->write[special].width + 0.5;
65 	break;
66       default:
67 	assert((c >= min_char) && (c <= env->fonts[fnum]->max_char_or_byte2));
68 	total += charlist[c - min_char].width;
69 	break;
70       }
71     }
72   } else  {  /* All chars are the same width. */
73     std_width = env->fonts[fnum]->min_bounds.width;
74     for (;;)  {
75       c = text[0];
76       ++text;
77       switch(c)  {
78       case '\0':
79 	return(total);
80 	break;
81       case '\1':
82       case '\2':
83 	special = 256 * (c - 1) + text[0];
84 	++text;
85 	assert(env->write[special].draw != NULL);
86 	total += (env->fonts[fnum]->ascent + env->fonts[fnum]->descent) *
87 	  env->write[special].width + 0.5;
88 	break;
89       default:
90 	total += std_width;
91 	break;
92       }
93     }
94   }
95 }
96 
97 
butEnv_charWidth(ButEnv * env,const char * text,int fnum)98 int  butEnv_charWidth(ButEnv *env, const char *text, int fnum)  {
99   uchar  c, special;
100   int  width;
101 
102   c = text[0];
103   assert(c != '\0');
104   switch(c)  {
105   case '\1':
106   case '\2':
107     special = 256 * (c - 1) + text[1];
108     assert(env->write[special].draw != NULL);
109     width = (env->fonts[fnum]->ascent + env->fonts[fnum]->descent) *
110       env->write[special].width + 0.5;
111     break;
112   default:
113     if (env->fonts[fnum]->per_char != NULL)
114       width = env->fonts[fnum]->per_char[c -
115 					 env->fonts[fnum]->min_char_or_byte2].
116 					   width;
117     else
118       width = env->fonts[fnum]->min_bounds.width;
119     break;
120   }
121   return(width);
122 }
123 
124 
butWin_write(ButWin * win,int x,int y,const char * text,int font)125 void  butWin_write(ButWin *win, int x, int y, const char *text, int font)  {
126   int  wlen;
127   ButEnv  *env = win->env;
128   int  ascent = env->fonts[font]->ascent, special;
129   int  w, h = ascent + env->fonts[font]->descent;
130   uchar  c;
131 
132   XSetFont(env->dpy, env->gc, env->fonts[font]->fid);
133   for (;;)  {
134     for (wlen = 0;  (uchar)(text[wlen]) > BUTWRITE_MINPRINT;  ++wlen);
135     if (wlen > 0)  {
136       XDrawString(env->dpy, win->win, env->gc,
137 		  x-win->xOff, y+ascent-win->yOff, text, wlen);
138       x += XTextWidth(env->fonts[font], text, wlen);
139       text += wlen;
140     }
141     switch(c = text[0])  {
142     case '\0':
143       return;
144       break;
145     case '\1':
146     case '\2':
147       special = 256 * (c-1) + text[1];
148       text += 2;
149       assert(env->write[special].draw != NULL);
150       w = h * env->write[special].width + 0.5;
151       env->write[special].draw(env->write[special].packet, win,
152 			       x-win->xOff,y-win->yOff, w,h);
153       x += w;
154       break;
155     }
156   }
157 }
158 
159 
butWin_writeTabs(ButWin * win,int startX,int y,const char * text,int font,const int * tabList,const ButTextAlign * aligns)160 void  butWin_writeTabs(ButWin *win, int startX, int y, const char *text,
161 		       int font, const int *tabList,
162 		       const ButTextAlign *aligns)  {
163   int  wlen;
164   ButEnv  *env = win->env;
165   int  ascent = env->fonts[font]->ascent, special;
166   int  w, h = ascent + env->fonts[font]->descent;
167   int  x = startX;
168   uchar  c;
169   int  tabNum = 0;
170   ButTextAlign  align = butText_left;
171 
172   XSetFont(env->dpy, env->gc, env->fonts[font]->fid);
173   for (;;)  {
174     for (wlen = 0;  (uchar)(text[wlen]) > BUTWRITE_MINPRINT;  ++wlen);
175     if (wlen > 0)  {
176       w = XTextWidth(env->fonts[font], text, wlen);
177       switch(align)  {
178       case butText_left:
179 	break;
180       case butText_center:
181 	x -= w / 2;
182 	break;
183       case butText_right:
184 	x -= w;
185 	break;
186       case butText_just:
187 	assert(0);
188 	break;
189       }
190       XDrawString(env->dpy, win->win, env->gc,
191 		  x - win->xOff, y+ascent-win->yOff, text, wlen);
192       x += w;
193       text += wlen;
194     }
195     switch(c = text[0])  {
196     case '\0':
197       return;
198       break;
199     case '\1':
200     case '\2':
201       special = 256 * (c-1) + text[1];
202       text += 2;
203       assert(env->write[special].draw != NULL);
204       w = h * env->write[special].width + 0.5;
205       env->write[special].draw(env->write[special].packet, win,
206 			       x-win->xOff,y-win->yOff, w,h);
207       x += w;
208       break;
209     case '\t':
210       x = startX + tabList[tabNum];
211       align = aligns[tabNum];
212       ++tabNum;
213       ++text;
214       break;
215     }
216   }
217 }
218 
219 
220 #endif  /* X11_DISP */
221