dockapps/wmradio/skin.c

471 lines
11 KiB
C

/*
* Copyright (C) 12 Jun 2003 Tomas Cermak
*
* This file is part of wmradio program.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "skin.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <locale.h>
#include "stationnames.h"
#define ACTION_COUNT 16
#ifndef SKIN_DIR
#define SKIN_DIR "/usr/local/lib/wmradio/"
#endif
ButtonInfo buttons[ACTION_COUNT];
int button_count = 0;
DigitsInfo digits;
LettersInfo letters;
XpmIcon RadioSkin;
ButtonInfo StereoInfo;
char radio_is_off = 0;
int icon_width = DEFAULTICONSIZE;
int icon_height = DEFAULTICONSIZE;
int in_region(int x, int y, int btx,int bty,int btw,int bth)
{
if( (x>=btx) && (x < btx + btw) && (y>=bty) && (y<bty+bth) ) return 1;
return 0;
}
int xor_string(char *s)
{
int a,r;
r = 0;
for(a=0; a<strlen(s); a++) {
r = r << 1;
if( r>0xFFFF ) r = (r & 0xFFFF) + 1;
r ^= s[a];
}
return r;
}
/* void add_action(char *name, region reg) */
/* { */
/* if( action_count < ACTION_COUNT ) { */
/* actions[action_count].action = xor_string(name); */
/* actions[action_count].r = reg; */
/* action_count++; */
/* } */
/* } */
int skin_read_num(char *p)
{
char *q;
int res;
q = strstr(p,",");
if(q) {
*q = '\000';
q++;
}
res = atoi(p);
if(q) strcpy(p,q);
return res;
}
void skin_def_line(char *line, Display *display, Drawable drawable, char *skin_desc_dir)
{
char *p,*w;
int x,i;
char buffer[256];
w = line;
p = strstr(w,"=");
if(!p) return;
*p = '\000';
p++;
x = xor_string(w);
switch(x) {
case 5829: /* preset1-6 */
buttons[button_count].status = BS_SELECTED;
case 5830:
case 5831:
case 5824:
case 5825:
case 5826:
case 1457: /* tune+ */
case 1463: /* tune- */
case 278: /* off */
case 696: /* scan */
case 4507: /* display */
buttons[button_count].action = x;
buttons[button_count].destx = skin_read_num(p);
buttons[button_count].desty = skin_read_num(p);
buttons[button_count].srcx = skin_read_num(p);
buttons[button_count].srcy = skin_read_num(p);
buttons[button_count].width = skin_read_num(p);
buttons[button_count].height = skin_read_num(p);
button_count++;
break;
case 365: /* xpm */
buffer[0] = '\000';
if( ! strstr(p,"/") ) {
strcpy(buffer,skin_desc_dir);
}
strcat(buffer,p);
if(XpmReadFileToPixmap(display,drawable,buffer,
&(RadioSkin.pixmap),
&(RadioSkin.mask),
&(RadioSkin.attributes)) != XpmSuccess) {
printf("wmradio: can't load pixmap %s\n",buffer);
}
break;
case 2071: /* digits */
digits.destx = skin_read_num(p);
digits.desty = skin_read_num(p);
digits.srcx = skin_read_num(p);
digits.srcy = skin_read_num(p);
for(i=0; i<12; i++) {
digits.w[i] = skin_read_num(p);
}
digits.h = skin_read_num(p);
break;
case 4675: /* letters */
letters.destx = skin_read_num(p);
letters.desty = skin_read_num(p);
letters.srcx = skin_read_num(p);
letters.srcy = skin_read_num(p);
for(i=0; i<26; i++) {
letters.w[i] = skin_read_num(p);
}
letters.h = skin_read_num(p);
break;
case 2917: /* stereo */
StereoInfo.destx = skin_read_num(p);
StereoInfo.desty = skin_read_num(p);
StereoInfo.srcx = skin_read_num(p);
StereoInfo.srcy = skin_read_num(p);
StereoInfo.width = skin_read_num(p);
StereoInfo.height = skin_read_num(p);
break;
case 19368: /* iconwidth */
icon_width = atoi(p);
case 37920: /* iconheight */
icon_height = atoi(p);
}
}
void create_skin(char *skin_def_file, Display *display, Drawable drawable)
{
FILE *f;
char buffer[256], *p, dir[256];
buffer[0] = '\000';
memset(&letters,0,sizeof(letters));
if(!strstr(skin_def_file,"/")) {
strcpy(buffer,SKIN_DIR);
}
strcat(buffer,skin_def_file);
strncpy(dir,buffer,sizeof(dir));
p = &dir[strlen(dir)-1];
while( *p != '/' ) p--;
p[1] = '\000';
f = fopen(buffer,"r");
if(! f ){
printf("wmradio: Skin %s not found\n", skin_def_file);
if( strcmp(skin_def_file,"default.skin") != 0 ) {
create_skin("default.skin",display,drawable);
}
return;
}
while(!feof(f)) {
fgets(buffer,sizeof(buffer),f);
p = strstr(buffer,"#");
if(p) *p = '\000';
p = strstr(buffer,"\n");
if(p) *p = '\000';
while(buffer[0] == ' ') strcpy(buffer,&buffer[1]);
skin_def_line(buffer,display,drawable,dir);
}
fclose(f);
}
int find_action(int x, int y)
{
int a;
for(a=0; a< button_count; a++) {
if(
in_region(x,y,
buttons[a].destx,
buttons[a].desty,
buttons[a].width,
buttons[a].height
)
) return buttons[a].action;
}
return 0;
}
int skin_button_index(int x, int y)
{
int i;
for(i=0; i< button_count; i++) {
if( in_region(x,y,
buttons[i].destx,
buttons[i].desty,
buttons[i].width,
buttons[i].height) ) {
return i;
}
}
return -1;
}
void skin_unselect_button(void)
{
int a;
for(a=0; a< ACTION_COUNT; a++) {
if(buttons[a].status == BS_SELECTED) buttons[a].status = BS_RELEASED;
}
}
int skin_mouse_event(int x, int y, int mousebutton, int press)
{
int i,r;
static int last_press = -1;
r=0;
if(press) {
last_press = skin_button_index(x,y);
buttons[last_press].status = BS_PRESSED;
} else {
/* release */
if(last_press == skin_button_index(x,y)) {
r = buttons[last_press].action;
buttons[last_press].status = BS_RELEASED;
if( r/100 == 58 ) {
for(i = 0; i< button_count; i++) buttons[i].status = BS_RELEASED;
buttons[last_press].status = BS_SELECTED;
}
} else {
if(last_press >= 0) {
buttons[last_press].status = BS_RELEASED;
}
last_press = -1;
}
}
return r;
}
int digit_index(char digit) {
int i = 10;
if(isdigit(digit)) i = digit - '0';
if(digit == ' ') i = 10;
if(digit == '.') i = 11;
return i;
}
int digit_source_x(int index)
{
int i,x;
x = digits.srcx;
for(i=0; i<index; i++) {
x += digits.w[i];
}
return x;
}
int letter_index(char letter) {
if(isalpha(letter) && isascii(letter)) return tolower(letter) - 'a';
return -1;
}
int letter_source_x(int index)
{
int i,x;
x = letters.srcx;
for(i=0; i<index; i++) {
x += letters.w[i];
}
return x;
}
int have_letters(void)
{
return letters.h != 0;
}
void char_to_window(Display *display, Window win, GC gc, char c, int *x, int y)
{
int idx, sourcex;
if(isalpha(c)) {
idx = letter_index(c);
sourcex = letter_source_x(idx);
XCopyArea(display,RadioSkin.pixmap,win, gc,
letters.srcx + sourcex,
letters.srcy,
letters.w[idx],
letters.h,
*x,
y);
*x += letters.w[idx];
} else {
idx = digit_index(c);
sourcex = digit_source_x(idx);
XCopyArea(display,RadioSkin.pixmap,win, gc,
digits.srcx + sourcex,
digits.srcy,
digits.w[idx],
digits.h,
*x,
y);
*x += digits.w[idx];
}
}
void freq_to_window(Display *display, Window win, GC gc, int freq)
{
char freqs[10], temp[10], *stn_name;
int x,i;
stn_name = station_get_freq_name(freq);
if(stn_name && have_letters()) {
strncpy(freqs,stn_name,4);
freqs[4] = 0;
while(strlen(freqs)<3) strcat(freqs," ");
strcat(freqs,". ");
} else {
snprintf(freqs,sizeof(freqs),"%i.%i",freq/100, (freq % 100) / 10);
while(strlen(freqs)<5) {
strcpy(temp," ");
strcat(temp,freqs);
strcpy(freqs,temp);
}
}
/* freq now contain right text */
i = 0;
x = digits.destx;
while(freqs[i]) {
char_to_window(display,win,gc,freqs[i],&x,digits.desty);
i++;
}
}
void skin_to_window(Display *display, Window win, GC gc, int freq, char stereo)
{
int i;
int xs;
char bs;
setlocale(LC_ALL,"C");
XCopyArea(display,RadioSkin.pixmap,win, gc, 0, 0, skin_width(), skin_height(), 0, 0);
for(i=0; i<button_count; i++) {
xs = buttons[i].srcx;
bs = buttons[i].status;
if( radio_is_off ) bs = BS_PRESSED;
switch(bs) {
case BS_RELEASED:
xs = buttons[i].srcx;
break;
case BS_PRESSED:
xs = buttons[i].srcx + buttons[i].width;
break;
case BS_SELECTED:
xs = buttons[i].srcx + buttons[i].width * 2;
break;
}
if( buttons[i].action != 4507 ) { /* 4507 is display */
XCopyArea(display,RadioSkin.pixmap,win, gc,
xs, buttons[i].srcy,
buttons[i].width,
buttons[i].height,
buttons[i].destx,
buttons[i].desty);
}
}
/* digits */
if(!radio_is_off){
freq_to_window(display,win,gc,freq);
/* stereo */
xs = StereoInfo.srcx;
if(stereo) xs += StereoInfo.width;
XCopyArea(display,RadioSkin.pixmap,win, gc,
xs,
StereoInfo.srcy,
StereoInfo.width,
StereoInfo.height,
StereoInfo.destx,
StereoInfo.desty);
}
}
void skin_select_button(int action) {
int a;
for(a=0; a< ACTION_COUNT; a++) {
if(buttons[a].action == action) buttons[a].status = BS_SELECTED;
}
}
void skin_switch_radio(char status)
{
radio_is_off = status;
}
int skin_width(void) {
return icon_width;
}
int skin_height(void) {
return icon_height;
}
void skin_select_station(int station)
{
int i;
for(i=0; i<ACTION_COUNT; i++) {
switch(buttons[i].action) {
case 5829:
buttons[i].status = station == 0 ? BS_SELECTED : BS_RELEASED;
break;
case 5830:
buttons[i].status = station == 1 ? BS_SELECTED : BS_RELEASED;
break;
case 5831:
buttons[i].status = station == 2 ? BS_SELECTED : BS_RELEASED;
break;
case 5824:
buttons[i].status = station == 3 ? BS_SELECTED : BS_RELEASED;
break;
case 5825:
buttons[i].status = station == 4 ? BS_SELECTED : BS_RELEASED;
break;
case 5826:
buttons[i].status = station == 5 ? BS_SELECTED : BS_RELEASED;
break;
}
}
}