wmail: added command-line option to specify a different config-file.
[dockapps.git] / wmradio / skin.c
blobe1a3c507814ddf30c6e821c759abdfa6186b52fd
1 /*
2 * Copyright (C) 12 Jun 2003 Tomas Cermak
4 * This file is part of wmradio program.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include "skin.h"
22 #include <string.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <ctype.h>
26 #include <locale.h>
27 #include "stationnames.h"
29 #define ACTION_COUNT 16
30 #ifndef SKIN_DIR
31 #define SKIN_DIR "/usr/local/lib/wmradio/"
32 #endif
34 ButtonInfo buttons[ACTION_COUNT];
35 int button_count = 0;
36 DigitsInfo digits;
37 LettersInfo letters;
38 XpmIcon RadioSkin;
39 ButtonInfo StereoInfo;
40 char radio_is_off = 0;
41 int icon_width = DEFAULTICONSIZE;
42 int icon_height = DEFAULTICONSIZE;
44 int in_region(int x, int y, int btx,int bty,int btw,int bth)
46 if( (x>=btx) && (x < btx + btw) && (y>=bty) && (y<bty+bth) ) return 1;
47 return 0;
50 int xor_string(char *s)
52 int a,r;
54 r = 0;
55 for(a=0; a<strlen(s); a++) {
56 r = r << 1;
57 if( r>0xFFFF ) r = (r & 0xFFFF) + 1;
58 r ^= s[a];
60 return r;
63 /* void add_action(char *name, region reg) */
64 /* { */
65 /* if( action_count < ACTION_COUNT ) { */
66 /* actions[action_count].action = xor_string(name); */
67 /* actions[action_count].r = reg; */
68 /* action_count++; */
69 /* } */
70 /* } */
72 int skin_read_num(char *p)
74 char *q;
75 int res;
77 q = strstr(p,",");
78 if(q) {
79 *q = '\000';
80 q++;
82 res = atoi(p);
83 if(q) strcpy(p,q);
84 return res;
87 void skin_def_line(char *line, Display *display, Drawable drawable, char *skin_desc_dir)
89 char *p,*w;
90 int x,i;
91 char buffer[256];
93 w = line;
94 p = strstr(w,"=");
95 if(!p) return;
96 *p = '\000';
97 p++;
98 x = xor_string(w);
99 switch(x) {
100 case 5829: /* preset1-6 */
101 buttons[button_count].status = BS_SELECTED;
102 case 5830:
103 case 5831:
104 case 5824:
105 case 5825:
106 case 5826:
107 case 1457: /* tune+ */
108 case 1463: /* tune- */
109 case 278: /* off */
110 case 696: /* scan */
111 case 4507: /* display */
112 buttons[button_count].action = x;
113 buttons[button_count].destx = skin_read_num(p);
114 buttons[button_count].desty = skin_read_num(p);
115 buttons[button_count].srcx = skin_read_num(p);
116 buttons[button_count].srcy = skin_read_num(p);
117 buttons[button_count].width = skin_read_num(p);
118 buttons[button_count].height = skin_read_num(p);
119 button_count++;
120 break;
121 case 365: /* xpm */
122 buffer[0] = '\000';
123 if( ! strstr(p,"/") ) {
124 strcpy(buffer,skin_desc_dir);
126 strcat(buffer,p);
127 if(XpmReadFileToPixmap(display,drawable,buffer,
128 &(RadioSkin.pixmap),
129 &(RadioSkin.mask),
130 &(RadioSkin.attributes)) != XpmSuccess) {
131 printf("wmradio: can't load pixmap %s\n",buffer);
133 break;
134 case 2071: /* digits */
135 digits.destx = skin_read_num(p);
136 digits.desty = skin_read_num(p);
137 digits.srcx = skin_read_num(p);
138 digits.srcy = skin_read_num(p);
139 for(i=0; i<12; i++) {
140 digits.w[i] = skin_read_num(p);
142 digits.h = skin_read_num(p);
143 break;
144 case 4675: /* letters */
145 letters.destx = skin_read_num(p);
146 letters.desty = skin_read_num(p);
147 letters.srcx = skin_read_num(p);
148 letters.srcy = skin_read_num(p);
149 for(i=0; i<26; i++) {
150 letters.w[i] = skin_read_num(p);
152 letters.h = skin_read_num(p);
153 break;
154 case 2917: /* stereo */
155 StereoInfo.destx = skin_read_num(p);
156 StereoInfo.desty = skin_read_num(p);
157 StereoInfo.srcx = skin_read_num(p);
158 StereoInfo.srcy = skin_read_num(p);
159 StereoInfo.width = skin_read_num(p);
160 StereoInfo.height = skin_read_num(p);
161 break;
162 case 19368: /* iconwidth */
163 icon_width = atoi(p);
164 case 37920: /* iconheight */
165 icon_height = atoi(p);
169 void create_skin(char *skin_def_file, Display *display, Drawable drawable)
171 FILE *f;
172 char buffer[256], *p, dir[256];
174 buffer[0] = '\000';
175 memset(&letters,0,sizeof(letters));
177 if(!strstr(skin_def_file,"/")) {
178 strcpy(buffer,SKIN_DIR);
180 strcat(buffer,skin_def_file);
181 strncpy(dir,buffer,sizeof(dir));
182 p = &dir[strlen(dir)-1];
183 while( *p != '/' ) p--;
184 p[1] = '\000';
186 f = fopen(buffer,"r");
187 if(! f ){
188 printf("wmradio: Skin %s not found\n", skin_def_file);
189 if( strcmp(skin_def_file,"default.skin") != 0 ) {
190 create_skin("default.skin",display,drawable);
192 return;
194 while(!feof(f)) {
195 fgets(buffer,sizeof(buffer),f);
196 p = strstr(buffer,"#");
197 if(p) *p = '\000';
198 p = strstr(buffer,"\n");
199 if(p) *p = '\000';
200 while(buffer[0] == ' ') strcpy(buffer,&buffer[1]);
201 skin_def_line(buffer,display,drawable,dir);
203 fclose(f);
206 int find_action(int x, int y)
208 int a;
210 for(a=0; a< button_count; a++) {
212 in_region(x,y,
213 buttons[a].destx,
214 buttons[a].desty,
215 buttons[a].width,
216 buttons[a].height
218 ) return buttons[a].action;
220 return 0;
223 int skin_button_index(int x, int y)
225 int i;
226 for(i=0; i< button_count; i++) {
227 if( in_region(x,y,
228 buttons[i].destx,
229 buttons[i].desty,
230 buttons[i].width,
231 buttons[i].height) ) {
232 return i;
235 return -1;
238 void skin_unselect_button(void)
240 int a;
242 for(a=0; a< ACTION_COUNT; a++) {
243 if(buttons[a].status == BS_SELECTED) buttons[a].status = BS_RELEASED;
247 int skin_mouse_event(int x, int y, int mousebutton, int press)
249 int i,r;
250 static int last_press = -1;
252 r=0;
253 if(press) {
254 last_press = skin_button_index(x,y);
255 buttons[last_press].status = BS_PRESSED;
256 } else {
257 /* release */
258 if(last_press == skin_button_index(x,y)) {
259 r = buttons[last_press].action;
260 buttons[last_press].status = BS_RELEASED;
261 if( r/100 == 58 ) {
262 for(i = 0; i< button_count; i++) buttons[i].status = BS_RELEASED;
263 buttons[last_press].status = BS_SELECTED;
265 } else {
266 if(last_press >= 0) {
267 buttons[last_press].status = BS_RELEASED;
269 last_press = -1;
272 return r;
275 int digit_index(char digit) {
276 int i = 10;
278 if(isdigit(digit)) i = digit - '0';
279 if(digit == ' ') i = 10;
280 if(digit == '.') i = 11;
281 return i;
284 int digit_source_x(int index)
286 int i,x;
288 x = digits.srcx;
289 for(i=0; i<index; i++) {
290 x += digits.w[i];
292 return x;
295 int letter_index(char letter) {
297 if(isalpha(letter) && isascii(letter)) return tolower(letter) - 'a';
298 return -1;
301 int letter_source_x(int index)
303 int i,x;
305 x = letters.srcx;
306 for(i=0; i<index; i++) {
307 x += letters.w[i];
309 return x;
312 int have_letters(void)
314 return letters.h != 0;
317 void char_to_window(Display *display, Window win, GC gc, char c, int *x, int y)
319 int idx, sourcex;
321 if(isalpha(c)) {
322 idx = letter_index(c);
323 sourcex = letter_source_x(idx);
324 XCopyArea(display,RadioSkin.pixmap,win, gc,
325 letters.srcx + sourcex,
326 letters.srcy,
327 letters.w[idx],
328 letters.h,
331 *x += letters.w[idx];
332 } else {
333 idx = digit_index(c);
334 sourcex = digit_source_x(idx);
335 XCopyArea(display,RadioSkin.pixmap,win, gc,
336 digits.srcx + sourcex,
337 digits.srcy,
338 digits.w[idx],
339 digits.h,
342 *x += digits.w[idx];
347 void freq_to_window(Display *display, Window win, GC gc, int freq)
349 char freqs[10], temp[10], *stn_name;
350 int x,i;
352 stn_name = station_get_freq_name(freq);
353 if(stn_name && have_letters()) {
354 strncpy(freqs,stn_name,4);
355 freqs[4] = 0;
356 while(strlen(freqs)<3) strcat(freqs," ");
357 strcat(freqs,". ");
358 } else {
359 snprintf(freqs,sizeof(freqs),"%i.%i",freq/100, (freq % 100) / 10);
360 while(strlen(freqs)<5) {
361 strcpy(temp," ");
362 strcat(temp,freqs);
363 strcpy(freqs,temp);
366 /* freq now contain right text */
367 i = 0;
368 x = digits.destx;
369 while(freqs[i]) {
370 char_to_window(display,win,gc,freqs[i],&x,digits.desty);
371 i++;
375 void skin_to_window(Display *display, Window win, GC gc, int freq, char stereo)
377 int i;
378 int xs;
379 char bs;
381 setlocale(LC_ALL,"C");
382 XCopyArea(display,RadioSkin.pixmap,win, gc, 0, 0, skin_width(), skin_height(), 0, 0);
383 for(i=0; i<button_count; i++) {
384 xs = buttons[i].srcx;
385 bs = buttons[i].status;
386 if( radio_is_off ) bs = BS_PRESSED;
387 switch(bs) {
388 case BS_RELEASED:
389 xs = buttons[i].srcx;
390 break;
391 case BS_PRESSED:
392 xs = buttons[i].srcx + buttons[i].width;
393 break;
394 case BS_SELECTED:
395 xs = buttons[i].srcx + buttons[i].width * 2;
396 break;
398 if( buttons[i].action != 4507 ) { /* 4507 is display */
399 XCopyArea(display,RadioSkin.pixmap,win, gc,
400 xs, buttons[i].srcy,
401 buttons[i].width,
402 buttons[i].height,
403 buttons[i].destx,
404 buttons[i].desty);
407 /* digits */
408 if(!radio_is_off){
409 freq_to_window(display,win,gc,freq);
410 /* stereo */
411 xs = StereoInfo.srcx;
412 if(stereo) xs += StereoInfo.width;
413 XCopyArea(display,RadioSkin.pixmap,win, gc,
415 StereoInfo.srcy,
416 StereoInfo.width,
417 StereoInfo.height,
418 StereoInfo.destx,
419 StereoInfo.desty);
423 void skin_select_button(int action) {
424 int a;
426 for(a=0; a< ACTION_COUNT; a++) {
427 if(buttons[a].action == action) buttons[a].status = BS_SELECTED;
431 void skin_switch_radio(char status)
433 radio_is_off = status;
436 int skin_width(void) {
437 return icon_width;
440 int skin_height(void) {
441 return icon_height;
444 void skin_select_station(int station)
446 int i;
448 for(i=0; i<ACTION_COUNT; i++) {
449 switch(buttons[i].action) {
450 case 5829:
451 buttons[i].status = station == 0 ? BS_SELECTED : BS_RELEASED;
452 break;
453 case 5830:
454 buttons[i].status = station == 1 ? BS_SELECTED : BS_RELEASED;
455 break;
456 case 5831:
457 buttons[i].status = station == 2 ? BS_SELECTED : BS_RELEASED;
458 break;
459 case 5824:
460 buttons[i].status = station == 3 ? BS_SELECTED : BS_RELEASED;
461 break;
462 case 5825:
463 buttons[i].status = station == 4 ? BS_SELECTED : BS_RELEASED;
464 break;
465 case 5826:
466 buttons[i].status = station == 5 ? BS_SELECTED : BS_RELEASED;
467 break;