1 /* bitmapbutton.c - buttons with little pictures on them
2    Copyright (C) 1996-2017 Paul Sheer
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307, USA.
18  */
19 
20 #include <config.h>
21 #include <stdio.h>
22 #include <my_string.h>
23 #include <stdlib.h>
24 #include <stdarg.h>
25 
26 #include <X11/Intrinsic.h>
27 #include "lkeysym.h"
28 
29 #include "stringtools.h"
30 #include "app_glob.c"
31 
32 #include "coolwidget.h"
33 
34 #include "mad.h"
35 
36 extern struct look *look;
37 
38 void render_rounded_bevel (Window win, int x1, int y1, int x2, int y2, int radius, int thick, int sunken);
39 
CDrawBitmapButton(const char * identifier,Window parent,int x,int y,int width,int height,unsigned long fg,unsigned long bg,const unsigned char data[])40 CWidget *CDrawBitmapButton (const char *identifier, Window parent, int x, int y,
41 			    int width, int height, unsigned long fg, unsigned long bg, const unsigned char data[])
42 {
43     XSetWindowAttributes xswa;
44     CWidget *w = CSetupWidget (identifier, parent, x, y,
45       width + 8, height + 8, C_BITMAPBUTTON_WIDGET, INPUT_BUTTON, bg, 1);
46     w->render = render_button;
47     xswa.background_pixmap = w->pixmap = XCreateBitmapFromData (CDisplay, w->winid, (char *) data, width, height);
48     if (xswa.background_pixmap)
49 	XChangeWindowAttributes (CDisplay, w->winid, CWBackPixmap, &xswa);
50     w->fg = fg;
51     w->bg = bg;
52     w->options |= WIDGET_TAKES_FOCUS_RING | WIDGET_HOTKEY_ACTIVATES;
53 
54     set_hint_pos (x + width + 8 + WIDGET_SPACING, y + height + 8 + WIDGET_SPACING);
55 
56     return w;
57 }
58 
CDrawBitmap(const char * identifier,Window parent,int x,int y,int width,int height,unsigned long fg,unsigned long bg,const unsigned char data[])59 CWidget *CDrawBitmap (const char *identifier, Window parent, int x, int y,
60 		      int width, int height, unsigned long fg, unsigned long bg, const unsigned char data[])
61 {
62     CWidget *w = CSetupWidget (identifier, parent, x, y,
63 	     width + 8, height + 8, C_BITMAP_WIDGET, INPUT_EXPOSE, bg, 0);
64     Pixmap pixmap;
65 
66     pixmap = XCreateBitmapFromData (CDisplay, w->winid, (char *) data, width, height);
67     w->pixmap = pixmap;
68 
69     w->fg = fg;
70     w->bg = bg;
71 
72     set_hint_pos (x + width + 8 + WIDGET_SPACING, height + 8 + WIDGET_SPACING);
73 
74     return w;
75 }
76 
CDrawPixmapButton(const char * identifier,Window parent,int x,int y,int width,int height,const char * data[],char start_char)77 CWidget *CDrawPixmapButton (const char *identifier, Window parent,
78     int x, int y, int width, int height, const char *data[], char start_char)
79 {
80     CWidget *w;
81     w = CDrawButton (identifier, parent, x, y, width, height, "");
82     CSetBackgroundPixmap (identifier, data, width, height, start_char);
83     w->pixmap_mask = CCreateClipMask (data, width, height, ' ');
84     return w;
85 }
86 
87 #define PICTURE_SWITCH_SIZE 32
88 
89 Pixmap Cswitchon = 0;
90 Pixmap Cswitchoff = 0;
91 
92 /* here ->cursor holds the group (8 bits only)
93     and ->keypressed hold if the switch is on or off */
94 
CDrawSwitch(const char * identifier,Window parent,int x,int y,int on,const char * label,int group)95 CWidget *CDrawSwitch (const char *identifier, Window parent, int x, int y, int on, const char *label, int group)
96 {
97     int y_button, y_label, h = 0, xt = 0, yt = 0, l;
98     CWidget *w;
99 
100     if (group & SWITCH_PICTURE_TYPE) {
101 	l = PICTURE_SWITCH_SIZE;
102     } else
103 	l = (*look->get_switch_size) ();
104 
105     if (label) {
106 	CTextSize (0, &h, label);
107 	h += TEXT_RELIEF * 2 + 2;
108     }
109 
110     if (h > l ) {
111 	y_button = y + (h - l) / 2;
112 	y_label = y;
113     } else {
114 	y_button = y;
115 	y_label = y + (l - h) / 2;
116     }
117 
118     w = CSetupWidget (identifier, parent, x, y_button,
119 	 l, l, C_SWITCH_WIDGET, INPUT_BUTTON, COLOR_FLAT, 1);
120 
121     if (group & SWITCH_PICTURE_TYPE)
122     if (!Cswitchon) {
123 	Cswitchon = XCreateBitmapFromData (CDisplay, w->winid, (char *) switchon_bits, PICTURE_SWITCH_SIZE, PICTURE_SWITCH_SIZE);
124 	Cswitchoff = XCreateBitmapFromData (CDisplay, w->winid, (char *) switchoff_bits, PICTURE_SWITCH_SIZE, PICTURE_SWITCH_SIZE);
125     }
126     w->fg = COLOR_BLACK;
127     w->bg = COLOR_FLAT;
128     w->keypressed = on;
129     if (label)
130 	w->label = (char *) strdup (label);
131     w->hotkey = find_hotkey (w);
132     w->cursor = group & 0x0FFUL;
133     w->render = render_switch;
134     w->options |= (group & 0xFFFFFF00UL) | WIDGET_TAKES_FOCUS_RING | WIDGET_HOTKEY_ACTIVATES;
135 
136     if (label) {
137 	CWidget *t;
138 #ifdef NEXT_LOOK
139 	t = CDrawText (catstrs (identifier, ".label", NULL), parent, x + l, y_label, "%s", label);
140 #else
141 	t = CDrawText (catstrs (identifier, ".label", NULL), parent, x + l + WIDGET_SPACING, y_label, "%s", label);
142 #endif
143 	t->hotkey = w->hotkey; 		/* underlines the character */
144 	CGetHintPos (&xt, &yt);
145     }
146 
147     if (xt < x + l + WIDGET_SPACING)
148 	xt = x + l + WIDGET_SPACING;
149     if (yt < y + l + WIDGET_SPACING)
150 	yt = y + l + WIDGET_SPACING;
151     if (yt < y + h + WIDGET_SPACING)
152 	yt = y + h + WIDGET_SPACING;
153 
154     set_hint_pos (xt, yt);
155 
156     return w;
157 }
158 
159 /* sets and redraws in the group all except w */
set_switch_group(CWidget * w,int group,int on)160 void set_switch_group (CWidget * w, int group, int on)
161 {
162     CWidget *p = w;
163 
164     if (!w->cursor)	/* belongs to no group */
165 	return;
166     for (;;) {
167 	w = CNextFocus (w);
168 	if (!w)
169 	    return;
170 	if ((unsigned long) w == (unsigned long) p)
171 	    return;
172 	if (w->cursor == group)
173 	    if (w->keypressed != on) {
174 		w->keypressed = on;
175 		CExpose (w->ident);
176 	    }
177     };
178 }
179 
toggle_radio_button(CWidget * w)180 void toggle_radio_button (CWidget * w)
181 {
182     if (w->options & RADIO_INVERT_GROUP)
183 	set_switch_group (w, w->cursor, w->keypressed);
184     else
185 	set_switch_group (w, w->cursor, 0);
186     if (w->cursor && w->options & RADIO_ONE_ALWAYS_ON)
187 	w->keypressed = 1;
188     else
189 	w->keypressed = (w->keypressed == 0);
190 
191     /* don't expose, 'cos called from eh_button which renders by itself */
192 }
193 
render_switch(CWidget * wdt)194 void render_switch (CWidget * wdt)
195 {
196     (*look->render_switch) (wdt);
197 }
198 
render_rounded_bevel(Window win,int xs1,int ys1,int xs2,int ys2,int radius,int thick,int sunken)199 void render_rounded_bevel (Window win, int xs1, int ys1, int xs2, int ys2, int radius, int thick, int sunken)
200 {
201     unsigned long cn, cs, cnw, cne, cse;
202     int i;
203     int x1, y1, x2, y2;
204 
205     if (option_low_bandwidth)
206 	return;
207 
208     if ((sunken & 2)) {
209 	CSetColor (COLOR_FLAT);
210 	CRectangle (win, xs1, ys1, xs2 - xs1 + 1, ys2 - ys1 + 1);
211     }
212     sunken &= 1;
213 
214     cn = sunken ? color_widget (4) : color_widget (11);
215     cs = sunken ? color_widget (11) : color_widget (4);
216     cnw = color_widget (14);
217     cse = color_widget (2);
218 
219     if (sunken) {
220 	cne = cnw;
221 	cnw = cse;
222 	cse = cne;
223     }
224     cne = color_widget (8);
225 
226 #define Carc(win,x,y,w,h,a,b) XDrawArc(CDisplay,win,CGC,x,y,w,h,a,b)
227 
228     for (x1 = xs1; x1 < xs1 + thick; x1++)
229 	for (y1 = ys1; y1 < ys1 + thick; y1++) {
230 	    x2 = x1 + (xs2 - xs1 - thick + 1);
231 	    y2 = y1 + (ys2 - ys1 - thick + 1);
232 	    CSetColor (cnw);
233 	    Carc (win, x1, y1, (radius) * 2, (radius) * 2, 90 * 64, 90 * 64);
234 	    CSetColor (cse);
235 	    Carc (win, x2 - radius * 2, y2 - radius * 2, (radius) * 2, (radius) * 2, 270 * 64, 90 * 64);
236 	    CSetColor (cne);
237 	    Carc (win, x1, y2 - radius * 2, (radius) * 2, (radius) * 2, 180 * 64, 90 * 64);
238 	    Carc (win, x2 - radius * 2, y1, (radius) * 2, (radius) * 2, 0, 90 * 64);
239 	}
240 
241 
242     if (radius)
243 	radius--;
244     for (i = 0; i < thick; i++) {
245 	CSetColor (cn);
246 	CLine (win, xs1 + i, ys1 + radius, xs1 + i, ys2 - radius);
247 	CLine (win, xs1 + radius, ys1 + i, xs2 - radius, ys1 + i);
248 	CSetColor (cs);
249 	CLine (win, xs2 - radius, ys2 - i, xs1 + radius, ys2 - i);
250 	CLine (win, xs2 - i, ys1 + radius, xs2 - i, ys2 - radius);
251 	CSetColor (color_widget (15));
252 	if (sunken)
253 	    XDrawPoint (CDisplay, win, CGC, xs2 - i - (radius + 1) * 300 / 1024, ys2 - i - (radius + 1) * 300 / 1024);
254 	else
255 	    XDrawPoint (CDisplay, win, CGC, xs1 + i + (radius + 1) * 300 / 1024, ys1 + i + (radius + 1) * 300 / 1024);
256     }
257 
258 
259     CSetColor (COLOR_BLACK);
260 }
261