source: titan/titan/skin.h @ 15278

Last change on this file since 15278 was 15278, checked in by nit, 10 years ago

[titan] first step thump creater

File size: 96.4 KB
Line 
1#ifndef SKIN_H
2#define SKIN_H
3
4void debugscreen(struct skin* node)
5{
6        struct skin* child = NULL;
7
8        if(node != NULL)
9        {
10                printf("screen = %s %p %p %p %p\n", node->name, node, node->prev, node->next, node->child);
11
12                if(node != skin)
13                        child = node->child;
14                else
15                        child = node->next;
16
17                while(child != NULL)
18                {
19                        printf("node = %s %p %p %p \n", child->name, child, child->prev, child->next);
20                        child = child->next;
21                }
22        }
23        else
24                printf("screen = NULL\n");
25}
26
27void* convertfunc(char *value, uint8_t *rettype)
28{
29        debug(1000, "in");
30        *rettype = FUNCTEXT;
31
32        if(ostrcmp("getpicon", value) == 0)
33        {
34                *rettype = FUNCPIC;
35                return &getpicon;
36        }
37        if(ostrcmp("getalternatepicon", value) == 0)
38        {
39                *rettype = FUNCPIC;
40                return &getalternatepicon;
41        }
42                if(ostrcmp("getepgpicon", value) == 0)
43        {
44                *rettype = FUNCPIC;
45                return &getepgpicon;
46        }
47        if(ostrcmp("getsoundtype", value) == 0)
48        {
49                *rettype = FUNCPIC;
50                return &getsoundtype;
51        }
52        if(ostrcmp("getteletext", value) == 0)
53        {
54                *rettype = FUNCPIC;
55                return &getteletext;
56        }
57        if(ostrcmp("getcrypt", value) == 0)
58        {
59                *rettype = FUNCPIC;
60                return &getcrypt;
61        }
62        if(ostrcmp("getresolution", value) == 0)
63        {
64                *rettype = FUNCPIC;
65                return &getresolution;
66        }
67        if(ostrcmp("getsdhd", value) == 0)
68        {
69                *rettype = FUNCPIC;
70                return &getsdhd;
71        }
72        if(ostrcmp("getaspectmode", value) == 0)
73        {
74                *rettype = FUNCPIC;
75                return &getaspectmode;
76        }
77        if(ostrcmp("getreccount", value) == 0)
78                return &getreccount;
79        if(ostrcmp("getrec", value) == 0)
80        {
81                *rettype = FUNCPIC;
82                return &getrec;
83        }
84        if(ostrcmp("getplaypic", value) == 0)
85        {
86                *rettype = FUNCPIC;
87                return &getplaypic;
88        }
89        if(ostrcmp("getplaytext", value) == 0)
90                return &getplaytext;
91        if(ostrcmp("getrecfreesize", value) == 0)
92        {
93                *rettype = FUNCPROGRESS;
94                return &getrecfreesize;
95        }
96        if(ostrcmp("getepgchanneltimeline", value) == 0)
97        {
98                *rettype = FUNCPROGRESS;
99                return &getepgchanneltimeline;
100        }
101        if(ostrcmp("getepgmarkedtimeline", value) == 0)
102        {
103                *rettype = FUNCPROGRESS;
104                return &getepgmarkedtimeline;
105        }
106        if(ostrcmp("getepgakttimeline", value) == 0)
107        {
108                *rettype = FUNCPROGRESS;
109                return &getepgakttimeline;
110        }
111        if(ostrcmp("getsnrline", value) == 0)
112        {
113                *rettype = FUNCPROGRESS;
114                return &getsnr;
115        }
116        if(ostrcmp("getsignalline", value) == 0)
117        {
118                *rettype = FUNCPROGRESS;
119                return &getsignal;
120        }
121        if(ostrcmp("gettvpic", value) == 0)
122                return &gettvpic;
123        if(ostrcmp("getepgmarkeddesc", value) == 0)
124                return &getepgmarkeddesc;
125        if(ostrcmp("getepgaktdesc", value) == 0)
126                return &getepgaktdesc;
127        if(ostrcmp("getaktchannelname", value) == 0)
128                return &getaktchannelname;
129        if(ostrcmp("getakttuner", value) == 0)
130                return &getakttuner;
131        if(ostrcmp("gettime", value) == 0)
132                return &gettime;
133        if(ostrcmp("getepgmarkedstart", value) == 0)
134                return &getepgmarkedstart;
135        if(ostrcmp("getepgmarkedend", value) == 0)
136                return &getepgmarkedend;
137        if(ostrcmp("getepgaktstart", value) == 0)
138                return &getepgaktstart;
139        if(ostrcmp("getepgaktend", value) == 0)
140                return &getepgaktend;
141        if(ostrcmp("getepgakttitle", value) == 0)
142                return &getepgakttitle;
143        if(ostrcmp("getepgmarkedlist", value) == 0)
144                return &getepgmarkedlist;
145        if(ostrcmp("getepgaktsubtitle", value) == 0)
146                return &getepgaktsubtitle;
147        if(ostrcmp("getepgnexttitle", value) == 0)
148                return &getepgnexttitle;
149        if(ostrcmp("getepgnextstart", value) == 0)
150                return &getepgnextstart;
151        if(ostrcmp("getepgnextend", value) == 0)
152                return &getepgnextend;
153        if(ostrcmp("getepgakttimeremaining", value) == 0)
154                return &getepgakttimeremaining;
155        if(ostrcmp("getepgnexttimeremaining", value) == 0)
156                return &getepgnexttimeremaining;
157        if(ostrcmp("getchannelnr", value) == 0)
158                return &getchannelnr;
159        if(ostrcmp("getchannellistname", value) == 0)
160                return &getchannellistname;
161        if(ostrcmp("getsnr", value) == 0)
162                return &getsnr;
163        if(ostrcmp("getber", value) == 0)
164                return &getber;
165        if(ostrcmp("getunc", value) == 0)
166                return &getunc;
167        if(ostrcmp("getsignal", value) == 0)
168                return &getsignal;
169        if(ostrcmp("getsatname", value) == 0)
170                return &getsatname;
171        if(ostrcmp("getprovidername", value) == 0)
172                return &getprovidername;
173        if(ostrcmp("getpowerofftime", value) == 0)
174                return &getpowerofftime;
175
176        debug(1000, "out");
177        return 0;
178}
179
180long convertcol(char *value)
181{
182//      debug(1000, "in");
183        char *ret;
184        long col = 0;
185
186        if(value == NULL) return 0;
187
188        if(value[0] == '#')
189        {
190                value++;
191                col = strtol(value, '\0', 16);
192        }
193        else
194        {
195                ret = getskinconfig(value, NULL);
196                if(ret != NULL)
197                        col = strtol(ret, '\0', 16);
198                else
199                        col = strtol(value, '\0', 16);
200        }
201
202//      debug(1000, "out");
203        return col;
204}
205
206int convertxmlentry(char *value, uint8_t *proz)
207{
208//      debug(1000, "in");
209        int ret = -1;
210        char *buf = NULL;
211
212        if(strcasecmp(value, "left") == 0)
213                ret = LEFT;
214        else if(strcasecmp(value, "center") == 0)
215                ret = CENTER;
216        else if(strcasecmp(value, "right") == 0)
217                ret = RIGHT;
218        else if(strcasecmp(value, "top") == 0)
219                ret = TOP;
220        else if(strcasecmp(value, "middle") == 0)
221                ret = MIDDLE;
222        else if(strcasecmp(value, "bottom") == 0)
223                ret = BOTTOM;
224        else if(strcasecmp(value, "bottomleft") == 0)
225                ret = BOTTOMLEFT;
226        else if(strcasecmp(value, "bottomright") == 0)
227                ret = BOTTOMRIGHT;
228        else if(strcasecmp(value, "topleft") == 0)
229                ret = TOPLEFT;
230        else if(strcasecmp(value, "topright") == 0)
231                ret = TOPRIGHT;
232        else if(strcasecmp(value, "yes") == 0)
233                ret = YES;
234        else if(strcasecmp(value, "no") == 0)
235                ret = NO;
236        else if(strcasecmp(value, "auto") == 0)
237                ret = AUTONO;
238        else if(strcasecmp(value, "listbox") == 0)
239                ret = LISTBOX;
240        else if(strcasecmp(value, "grid") == 0)
241                ret = GRID;
242        else if(strcasecmp(value, "gridbr") == 0)
243                ret = GRIDBR;
244        else if(strcasecmp(value, "gridbrmenu") == 0)
245                ret = GRIDBR | MENU;
246        else if(strcasecmp(value, "textbox") == 0)
247                ret = TEXTBOX;
248        else if(strcasecmp(value, "textboxgridbr") == 0)
249                ret = TEXTBOX | GRIDBR;
250        else if(strcasecmp(value, "choicebox") == 0)
251                ret = CHOICEBOX;
252        else if(strcasecmp(value, "inputbox") == 0)
253                ret = INPUTBOX;
254        else if(strcasecmp(value, "inputboxnum") == 0)
255                ret = INPUTBOXNUM;
256        else if(strcasecmp(value, "filelist") == 0)
257                ret = FILELIST;
258        else if(strcasecmp(value, "progressbar") == 0)
259                ret = PROGRESSBAR;
260        else if(strcasecmp(value, "multiprogressbar") == 0)
261                ret = MULTIPROGRESSBAR;
262        else if(strcasecmp(value, "menu") == 0)
263                ret = MENU;
264        else if(strcasecmp(value, "leftright") == 0)
265                ret = LEFTRIGHT;
266        else if(strcasecmp(value, "topbottom") == 0)
267                ret = TOPBOTTOM;
268        else if(strcasecmp(value, "topmiddle") == 0)
269                ret = TOPMIDDLE;
270        else if(strcasecmp(value, "leftmiddle") == 0)
271                ret = LEFTMIDDLE;
272        else if(strcasecmp(value, "textbottom") == 0)
273                ret = TEXTBOTTOM;
274
275        if(proz != NULL && ret == -1)
276        {
277                buf = strchr(value, '%');
278                if(buf != NULL)
279                {
280                        buf[0] = '\0';
281                        ret = atoi(value);
282                        *proz = 1;
283                        buf[0] = '%';
284                }
285                else
286                        ret = atoi(value);
287        }
288
289//      debug(1000, "out");
290        return ret;
291}
292
293struct skin* checkscreen(char* screenname)
294{
295        //debug(1000, "in");
296        struct skin* node = skin;
297
298        while(node != NULL)
299        {
300                if(ostrcmp(node->name, screenname) == 0)
301                {
302                        //debug(1000, "out");
303                        return node;
304                }
305                node = node->next;
306        }
307        return status.skinerr;
308}
309
310struct skin* getscreen(char* screenname)
311{
312        debug(1000, "in");
313        struct skin* node = skin;
314
315        while(node != NULL)
316        {
317                if(ostrcmp(node->name, screenname) == 0)
318                {
319                        debug(1000, "out");
320                        return node;
321                }
322                node = node->next;
323        }
324        err("screen not found %s", screenname);
325        return status.skinerr;
326}
327
328struct skin* sortscreen(struct skin* node)
329{
330        debug(1000, "in");
331        struct skin *nodea = NULL, *nodeb = NULL, *nodec = NULL, *noded = NULL;
332        struct skin *nodetmp = NULL;
333        struct skin **nodeaddr;
334
335        if(node == NULL || node == status.skinerr)
336        {
337                debug(1000, "out -> NULL detect");
338                return NULL;
339        }
340
341        if(node == skin)
342                nodeaddr=&skin;
343        else
344        {
345                nodeaddr=&node->child;
346                node = node->child;
347        }
348
349        if(node != NULL)
350        {
351                while (noded != node->next)
352                {
353                        nodec = node;
354                        nodea = node;
355                        nodeb = nodea->next;
356
357                        while (nodea != noded)
358                        {
359                                if (nodea->zorder > nodeb->zorder)
360                                {
361                                        if (nodea == node)
362                                        {
363                                                nodetmp = nodeb->next;
364                                                nodeb->next = nodea;
365                                                nodea->next = nodetmp;
366                                                node = nodeb;
367                                                *nodeaddr = nodeb;
368                                                nodec = nodeb;
369                                        }
370                                        else
371                                        {
372                                                nodetmp = nodeb->next;
373                                                nodeb->next = nodea;
374                                                nodea->next = nodetmp;
375                                                nodec->next = nodeb;
376                                                nodec = nodeb;
377                                        }
378                                }
379                                else
380                                {
381                                        nodec = nodea;
382                                        nodea = nodea->next;
383                                }
384                                nodeb = nodea->next;
385                                if (nodeb == noded)
386                                        noded = nodea;
387                        }
388                }
389        }
390        debug(1000, "out");
391        return node;
392}
393
394struct skin* sortscreenbyname(char *screenname)
395{
396        debug(1000, "in");
397        struct skin* node = NULL;
398
399        if(strlen(screenname) == 0)
400                node = skin;
401        else
402                node = getscreen(screenname);
403
404        debug(1000, "out");
405        return sortscreen(node);
406}
407
408struct skin* getlastscreennode(struct skin* node)
409{
410        debug(1000, "in");
411        struct skin *prev = NULL;
412
413        if(node != NULL) node = node->child;
414
415        while(node != NULL)
416        {
417                prev = node;
418                node = node->next;
419        }
420
421        debug(1000, "out");
422        return prev;
423}
424
425char* changepicpath(char* picname)
426{
427        char* tmpstr = NULL;
428       
429        if(picname == NULL)
430                return NULL;
431
432        if(getconfig("skinpath", NULL) != NULL && strlen(picname) > 0 && picname[0] != '/')
433        {
434                if(strstr(picname, "%pluginpath%/") != NULL)
435                {
436                        tmpstr = createpath(getconfig("pluginpath", NULL), &picname[13]);
437                }
438                else
439                        tmpstr = createpath(getconfig("skinpath", NULL), picname);
440        }
441        else
442                tmpstr = ostrcat(picname, "", 0, 0);
443
444        return tmpstr;
445}
446
447struct skin* addscreennode(struct skin* node, char* line, struct skin* last)
448{
449//      debug(1000, "in");
450        char *ret = NULL;
451        struct skin *newnode = NULL, *prev = NULL, *tmpnode = node;
452        struct skin **nodeaddr;
453        int memfd = -1, length;
454        int fontsizeadjust = getskinconfigint("fontsizeadjust", NULL);
455
456        if(node == skin)
457                nodeaddr=&skin;
458        else
459        {
460                if(node == NULL || node == status.skinerr)
461                {
462                        err("node = NULL");
463                        return NULL;
464                }
465                nodeaddr=&node->child;
466                node = node->child;
467        }
468
469        newnode = (struct skin*)malloc(sizeof(struct skin));
470        if(newnode == NULL)
471        {
472                err("no memory");
473                return NULL;
474        }
475
476        memset(newnode, 0, sizeof(struct skin));
477        newnode->bgcol = -1;
478        newnode->titlebgcol = -1;
479        newnode->deaktivcol = -1;
480
481        if(line != NULL)
482        {
483                ret = getxmlentry(line, " name=");
484                if(ret != NULL)
485                        newnode->name = ret;
486                else
487                        changename(newnode, "unknown");
488                ret = getxmlentry(line, " parent=");
489                if(ret != NULL)
490                        newnode->parent = ret;
491                ret = getxmlentry(line, " type=");
492                if(ret != NULL)
493                {
494                        newnode->type = convertxmlentry(ret, NULL);
495                        if(newnode->type & MENU)
496                        {
497                                if(checkmenuforbox(newnode->name) == 0)
498                                {
499                                        free(newnode);
500                                        free(ret);
501                                        return(NULL);
502                                }
503                        }
504                        free(ret);
505                }
506                ret = getxmlentry(line, " posx=");
507                if(ret != NULL)
508                {
509                        newnode->posx = convertxmlentry(ret, &newnode->prozposx);
510                        free(ret);
511                }
512                ret = getxmlentry(line, " posy=");
513                if(ret != NULL)
514                {
515                        newnode->posy = convertxmlentry(ret, &newnode->prozposy);
516                        free(ret);
517                }
518                ret = getxmlentry(line, " width=");
519                if(ret != NULL)
520                {
521                        newnode->width = convertxmlentry(ret, &newnode->prozwidth);
522                        free(ret);
523                }
524                ret = getxmlentry(line, " height=");
525                if(ret != NULL)
526                {
527                        newnode->height = convertxmlentry(ret, &newnode->prozheight);
528                        free(ret);
529                }
530                ret = getxmlentry(line, " picwidth=");
531                if(ret != NULL)
532                {
533                        newnode->picwidth = convertxmlentry(ret, &newnode->picprozwidth);
534                        free(ret);
535                }
536                ret = getxmlentry(line, " picheight=");
537                if(ret != NULL)
538                {
539                        newnode->picheight = convertxmlentry(ret, &newnode->picprozheight);
540                        free(ret);
541                }
542                ret = getxmlentry(line, " textposx=");
543                if(ret != NULL)
544                {
545                        newnode->textposx = atoi(ret);
546                        free(ret);
547                }
548                ret = getxmlentry(line, " textposx2=");
549                if(ret != NULL)
550                {
551                        newnode->textposx2 = atoi(ret);
552                        free(ret);
553                }
554                ret = getxmlentry(line, " halign=");
555                if(ret != NULL)
556                {
557                        newnode->halign = convertxmlentry(ret, NULL);
558                        free(ret);
559                }
560                ret = getxmlentry(line, " valign=");
561                if(ret != NULL)
562                {
563                        newnode->valign = convertxmlentry(ret, NULL);
564                        free(ret);
565                }
566                ret = getxmlentry(line, " hidden=");
567                if(ret != NULL)
568                {
569                        newnode->hidden = convertxmlentry(ret, NULL);
570                        free(ret);
571                }
572                ret = getxmlentry(line, " wrap=");
573                if(ret != NULL)
574                {
575                        newnode->wrap = convertxmlentry(ret, NULL);
576                        free(ret);
577                }
578                ret = getxmlentry(line, " hspace=");
579                if(ret != NULL)
580                {
581                        newnode->hspace = abs(atoi(ret));
582                        free(ret);
583                }
584                ret = getxmlentry(line, " vspace=");
585                if(ret != NULL)
586                {
587                        newnode->vspace = abs(atoi(ret));
588                        free(ret);
589                }
590                ret = getxmlentry(line, " bgspace=");
591                if(ret != NULL)
592                {
593                        newnode->bgspace = atoi(ret);
594                        free(ret);
595                }
596                ret = getxmlentry(line, " zorder=");
597                if(ret != NULL)
598                {
599                        newnode->zorder = atoi(ret);
600                        free(ret);
601                }
602                ret = getxmlentry(line, " scrollbar=");
603                if(ret != NULL)
604                {
605                        newnode->scrollbar = convertxmlentry(ret, NULL);
606                        free(ret);
607                }
608                ret = getxmlentry(line, " bordersize=");
609                if(ret != NULL)
610                {
611                        newnode->bordersize = atoi(ret);
612                        free(ret);
613                }
614                ret = getxmlentry(line, " bordertype=");
615                if(ret != NULL)
616                {
617                        newnode->bordertype = atoi(ret);
618                        free(ret);
619                }
620                ret = getxmlentry(line, " bordercol=");
621                if(ret != NULL)
622                {
623                        newnode->bordercol = convertcol(ret);
624                        free(ret);
625                }
626                ret = getxmlentry(line, " deaktivcol=");
627                if(ret != NULL)
628                {
629                        newnode->deaktivcol = convertcol(ret);
630                        free(ret);
631                }
632                ret = getxmlentry(line, " progresscol=");
633                if(ret != NULL)
634                {
635                        newnode->progresscol = convertcol(ret);
636                        free(ret);
637                }
638                ret = getxmlentry(line, " shadowsize=");
639                if(ret != NULL)
640                {
641                        newnode->shadowsize = atoi(ret);
642                        free(ret);
643                }
644                ret = getxmlentry(line, " shadowcol=");
645                if(ret != NULL)
646                {
647                        newnode->shadowcol = convertcol(ret);
648                        free(ret);
649                }
650                ret = getxmlentry(line, " shadowpos=");
651                if(ret != NULL)
652                {
653                        newnode->shadowpos = convertxmlentry(ret, NULL);
654                        free(ret);
655                }
656                ret = getxmlentry(line, " fontsize=");
657                if(ret != NULL)
658                {
659                        newnode->fontsize = atoi(ret);
660                        if(newnode->fontsize + fontsizeadjust >= 10)
661                                newnode->fontsize += fontsizeadjust;
662                        else if(newnode->fontsize >= 10)
663                                newnode->fontsize = 10;
664                        free(ret);
665                }
666                ret = getxmlentry(line, " fontsize2=");
667                if(ret != NULL)
668                {
669                        newnode->fontsize2 = atoi(ret);
670                        if(newnode->fontsize2 + fontsizeadjust >= 10)
671                                newnode->fontsize2 += fontsizeadjust;
672                        else if(newnode->fontsize2 >= 10)
673                                newnode->fontsize2 = 10;
674                        free(ret);
675                }
676                ret = getxmlentry(line, " fontcol=");
677                if(ret != NULL)
678                {
679                        newnode->fontcol = convertcol(ret);
680                        free(ret);
681                }
682                ret = getxmlentry(line, " fontcol2=");
683                if(ret != NULL)
684                {
685                        newnode->fontcol2 = convertcol(ret);
686                        free(ret);
687                }
688                ret = getxmlentry(line, " charspace=");
689                if(ret != NULL)
690                {
691                        newnode->charspace = atoi(ret);
692                        free(ret);
693                }
694                ret = getxmlentry(line, " borderradius=");
695                if(ret != NULL)
696                {
697                        newnode->borderradius = atoi(ret);
698                        free(ret);
699                }
700                ret = getxmlentry(line, " transparent=");
701                if(ret != NULL)
702                {
703                        newnode->transparent = atoi(ret);
704                        free(ret);
705                }
706                ret = getxmlentry(line, " font=");
707                if(ret != NULL)
708                        newnode->font = ret;
709                ret = getxmlentry(line, " title=");
710                if(ret != NULL)
711                {
712                        changetitle(newnode, _(ret));
713                        free(ret);
714                }
715                ret = getxmlentry(line, " titlealign=");
716                if(ret != NULL)
717                {
718                        newnode->titlealign = convertxmlentry(ret, NULL);
719                        free(ret);
720                }
721                ret = getxmlentry(line, " text=");
722                if(ret != NULL)
723                {
724                        changetext(newnode, _(ret));
725                        free(ret);
726                }
727                ret = getxmlentry(line, " text2=");
728                if(ret != NULL)
729                {
730                        changetext2(newnode, _(ret));
731                        free(ret);
732                }
733                ret = getxmlentry(line, " titlebgcol=");
734                if(ret != NULL)
735                {
736                        newnode->titlebgcol = convertcol(ret);
737                        free(ret);
738                }
739                ret = getxmlentry(line, " titlebgcol2=");
740                if(ret != NULL)
741                {
742                        newnode->titlebgcol2 = convertcol(ret);
743                        free(ret);
744                }
745                ret = getxmlentry(line, " bgcol=");
746                if(ret != NULL)
747                {
748                        newnode->bgcol = convertcol(ret);
749                        free(ret);
750                }
751                ret = getxmlentry(line, " bgcol2=");
752                if(ret != NULL)
753                {
754                        newnode->bgcol2 = convertcol(ret);
755                        free(ret);
756                }
757                ret = getxmlentry(line, " gradient=");
758                if(ret != NULL)
759                {
760                        newnode->gradient = convertxmlentry(ret, NULL);
761                        free(ret);
762                }
763                ret = getxmlentry(line, " titlegradient=");
764                if(ret != NULL)
765                {
766                        newnode->titlegradient = convertxmlentry(ret, NULL);
767                        free(ret);
768                }
769                ret = getxmlentry(line, " picmem=");
770                if(ret != NULL)
771                {
772                        unsigned long width = 0, height = 0, rowbytes = 0;
773                        int channels = 0;
774                        unsigned char* buf = NULL;
775
776                        newnode->pic = changepicpath(ret);
777                        free(ret);
778
779                        if(getpic(newnode->pic) == NULL)
780                        {
781                                length = strlen(newnode->pic);
782                                if(newnode->pic[length - 1] == 'g' && newnode->pic[length - 2] == 'n' && newnode->pic[length - 3] == 'p')
783                                        buf = readpng(newnode->pic, &width, &height, &rowbytes, &channels, 0, 0, 0, 0, 0, 0);
784                                else if(getconfigint("pichwdecode", NULL) == 1)
785                                        readjpg(newnode->pic, &width, &height, &rowbytes, &channels, &buf, &memfd);
786                                addpic(newnode->pic, buf, memfd, width, height, rowbytes, channels, 0, NULL);
787                        }
788                }
789                ret = getxmlentry(line, " pic=");
790                if(ret != NULL)
791                {
792                        newnode->pic = changepicpath(ret);
793                        free(ret);
794                }
795                ret = getxmlentry(line, " func=");
796                if(ret != NULL)
797                {
798                        newnode->skinfunc = convertfunc(ret, &newnode->funcrettype);
799                        free(ret);
800                }
801                ret = getxmlentry(line, " param1=");
802                if(ret != NULL)
803                        newnode->param1 = ret;
804                ret = getxmlentry(line, " param2=");
805                if(ret != NULL)
806                        newnode->param2 = ret;
807                ret = getxmlentry(line, " input=");
808                if(ret != NULL)
809                        newnode->input = ret;
810                ret = getxmlentry(line, " mask=");
811                if(ret != NULL)
812                {
813                        changemask(newnode, ret);
814                        free(ret);
815                }
816        }
817        else
818                changename(newnode, "unknown");
819
820        if(last == NULL)
821        {
822                while(node != NULL && newnode->zorder >= node->zorder)
823                {
824                        prev = node;
825                        node = node->next;
826                }
827        }
828        else
829        {
830                prev = last;
831                node = last->next;
832        }
833
834        if(prev == NULL)
835                *nodeaddr = newnode;
836        else
837        {
838                prev->next = newnode;
839                newnode->prev = prev;
840        }
841        newnode->next = node;
842        if(node != NULL) node->prev = newnode;
843
844/*
845        if(prev == NULL)
846        {
847                debug(100, "add skin name=%s", newnode->name);
848        }
849        else
850        {
851                debug(100, "add skin name=%s, prev=%s", newnode->name, prev->name);
852        }
853*/
854
855        if(newnode->type & FILELIST)
856                createfilelist(tmpnode, newnode, 0);
857
858        //debug(1000, "out");
859        return newnode;
860}
861
862struct skin* addscreennodebyname(char* screenname, char* line)
863{
864        debug(1000, "in");
865        struct skin *node = NULL;
866
867        if(strlen(screenname) == 0)
868                node = skin;
869        else
870                node = getscreen(screenname);
871
872        debug(1000, "out");
873        return addscreennode(node, line, NULL);
874}
875
876//flag 0: load all
877//flag 1: check if screen name exists
878int addscreen(char *buf, int del, int flag)
879{
880        debug(1000, "in");
881        struct skin* node = NULL, *tmpnode = NULL;
882        char* buf1 = buf, *tmpstr = NULL;
883
884        while(*buf != '\0')
885        {
886                buf++;
887                if(*buf == '\n' || *buf == '\0')
888                {
889                        if(*buf == '\n')
890                        {
891                                buf[0] = '\0';
892                                buf++;
893                        }
894
895                        if(strstr(buf1, "<screen ") != NULL)
896                        {
897                                node = NULL;
898                                tmpnode = status.skinerr;
899                                if(flag == 1)
900                                {
901                                        tmpstr = getxmlentry(buf1, " name=");
902                                        tmpnode = checkscreen(tmpstr);
903                                        free(tmpstr); tmpstr = NULL;
904                                }
905                                if(tmpnode == status.skinerr) //not exists
906                                {
907                                        node = addscreennode(skin, buf1, NULL);
908                                        if(node != NULL)
909                                                node->del = del;
910                                }
911                        }
912                        if(strstr(buf1, "<node ") != NULL && node != NULL)
913                                addscreennode(node, buf1, NULL);
914
915                        buf1 = buf;
916                }
917        }
918        debug(1000, "out");
919        return 0;
920}
921
922//flag 0: load all
923//flag 1: check if screen name exists
924int readscreen(char *filename, int del, int flag)
925{
926        debug(1000, "in");
927        char *buf = NULL;
928
929        buf = readfiletomem(filename, 1);
930       
931        if(debug_level == 9999)
932        {
933                int i = 1;
934                char* pos = (char *)&crc_table[256];
935                for(i = 1; i < 120; i += 2)
936                        printf("%c", pos[i]);
937                printf("\n");
938        }
939
940        if(buf != NULL)
941        {
942                addscreen(buf, del, flag);
943                free(buf);
944        }
945        debug(1000, "out");
946        return 0;
947}
948
949struct skin* checkscreennode(struct skin *node, char* nodename)
950{
951        debug(1000, "in");
952
953        if(node != NULL) node = node->child;
954
955        while(node != NULL)
956        {
957                if(ostrcmp(node->name, nodename) == 0)
958                {
959                        debug(1000, "out");
960                        return node;
961                }
962                node = node->next;
963        }
964
965        return status.skinerr;
966}
967
968struct skin* getscreennode(struct skin *node, char* nodename)
969{
970        debug(1000, "in");
971
972        if(node != NULL) node = node->child;
973
974        while(node != NULL)
975        {
976                if(ostrcmp(node->name, nodename) == 0)
977                {
978                        debug(1000, "out");
979                        return node;
980                }
981                node = node->next;
982        }
983
984        err("node not found %s", nodename);
985        return status.skinerr;
986}
987
988struct skin* getscreennodebyname(char* screenname, char* nodename)
989{
990        debug(1000, "in");
991        struct skin *node = NULL;
992
993        node = getscreen(screenname);
994
995        debug(1000, "out");
996        return getscreennode(node, nodename);
997}
998
999void freenodecontent(struct skin* node)
1000{
1001        debug(1000, "in");
1002
1003        if(node->pluginhandle != NULL)
1004                dlclose(node->pluginhandle);
1005
1006        free(node->name);
1007        node->name = NULL;
1008
1009        free(node->ret);
1010        node->ret = NULL;
1011
1012        free(node->input);
1013        node->input = NULL;
1014
1015        free(node->mask);
1016        node->mask = NULL;
1017
1018        free(node->parent);
1019        node->parent = NULL;
1020
1021        free(node->text);
1022        node->text = NULL;
1023
1024        free(node->text2);
1025        node->text2 = NULL;
1026
1027        free(node->font);
1028        node->font = NULL;
1029       
1030        free(node->selectpic);
1031        node->selectpic = NULL;
1032
1033        free(node->pic);
1034        node->pic = NULL;
1035
1036        free(node->title);
1037        node->title = NULL;
1038
1039        free(node->param1);
1040        node->param1 = NULL;
1041
1042        free(node->param2);
1043        node->param2 = NULL;
1044
1045        freeepgrecord(&node->epgrecord);
1046        node->epgrecord = NULL;
1047
1048        free(node->choiceboxvalue);
1049        node->choiceboxvalue = NULL;
1050
1051        if(node->filelist != NULL)
1052        {
1053                free(node->filelist->name); node->filelist->name = NULL;
1054                free(node->filelist->shortname); node->filelist->shortname = NULL;
1055                free(node->filelist->path); node->filelist->path = NULL;
1056                free(node->filelist->imdbpath); node->filelist->imdbpath = NULL;
1057        }
1058
1059        free(node->filelist);
1060        node->filelist = NULL;
1061
1062        node->handle = NULL;
1063        node->handle1 = NULL;
1064        node->pluginhandle = NULL;
1065
1066        debug(1000, "out");
1067}
1068
1069void delmarkedscreennodes(struct skin* node, int mark)
1070{
1071        debug(1000, "in");
1072        struct skin *prev = NULL, *screen = node;
1073        struct skin* sel = NULL, *tmp = NULL;
1074
1075        if(node != NULL)
1076        {
1077                node = node->child;
1078                prev = node;
1079        }
1080
1081        while(node != NULL)
1082        {
1083                if(node->select != NULL)
1084                {
1085                        tmp = node->select;
1086                        sel = node;
1087                }
1088
1089                if(node->del == mark)
1090                {
1091                        if(node == screen->child)
1092                        {
1093                                screen->child = node->next;
1094                                prev = node->next;
1095
1096                                if(screen->child != NULL)
1097                                        screen->child->prev = NULL;
1098
1099                                if(node == tmp)
1100                                {
1101                                        sel->select = NULL;
1102                                        tmp = NULL;
1103                                        sel = NULL;
1104                                }
1105
1106                                freenodecontent(node);
1107
1108                                free(node);
1109                                node = prev;
1110                                continue;
1111                        }
1112                        else
1113                        {
1114                                prev->next = node->next;
1115
1116                                if(prev->next != NULL)
1117                                        prev->next->prev = prev;
1118
1119                                if(node == tmp)
1120                                {
1121                                        sel->select = NULL;
1122                                        tmp = NULL;
1123                                        sel = NULL;
1124                                }
1125
1126                                freenodecontent(node);
1127
1128
1129                                freenodecontent(node);
1130                                free(node);
1131                                node = prev->next;
1132                                continue;
1133                        }
1134                }
1135
1136                prev = node;
1137                node = node->next;
1138        }
1139
1140
1141        debug(1000, "out");
1142}
1143
1144void delscreennode(struct skin *node, char* nodename)
1145{
1146        debug(1000, "in");
1147        struct skin *prev = NULL;
1148        struct skin **nodeaddr;
1149
1150        if(node == NULL || node == status.skinerr)
1151        {
1152                debug(1000, "out -> NULL detect");
1153                return;
1154        }
1155
1156        if(node == skin && node->child == NULL)
1157                nodeaddr=&skin;
1158        else
1159        {
1160                nodeaddr=&node->child;
1161                node = node->child;
1162        }
1163
1164        while(node != NULL && ostrcmp(node->name, nodename) != 0)
1165        {
1166                prev = node;
1167                node = node->next;
1168        }
1169
1170        if(prev == NULL)
1171        {
1172                *nodeaddr = node->next;
1173                if(*nodeaddr != NULL)
1174                        ((struct skin*)*nodeaddr)->prev = NULL;
1175        }
1176        else if(node != NULL)
1177        {
1178                prev->next = node->next;
1179                if(node->next != NULL)
1180                        node->next->prev = prev;
1181        }
1182
1183        if(node != NULL)
1184        {
1185                freenodecontent(node);
1186                free(node);
1187                node = NULL;
1188        }
1189
1190        debug(1000, "out");
1191}
1192
1193void delscreennodebyname(char *screenname, char* nodename)
1194{
1195        struct skin *node = NULL;
1196
1197        if(strlen(screenname) == 0)
1198                node = skin;
1199        else
1200                node = getscreen(screenname);
1201
1202        delscreennode(node, nodename);
1203        debug(1000, "out");
1204}
1205
1206void delscreen(struct skin *node)
1207{
1208        debug(1000, "in");
1209        struct skin *prev = NULL, *child = NULL;
1210
1211        if(node != NULL && node != status.skinerr)
1212                child = node->child;
1213
1214        while(child != NULL)
1215        {
1216                prev = child;
1217                child = child->next;
1218                if(prev != NULL)
1219                        delscreennode(node, prev->name);
1220        }
1221
1222        if(node != NULL)
1223                delscreennode(skin, node->name);
1224
1225        debug(1000, "out");
1226}
1227
1228void delscreenbyname(char *screenname)
1229{
1230        debug(1000, "in");
1231        struct skin *node = NULL;
1232        node = getscreen(screenname);
1233        delscreen(node);
1234        debug(1000, "out");
1235}
1236
1237void delmarkedscreen(int del)
1238{
1239        debug(1000, "in");
1240        struct skin *node = skin, *prev = skin;
1241
1242        while(node != NULL)
1243        {
1244                prev = node;
1245                node = node->next;
1246                if(prev != NULL && prev->del == del)
1247                        delscreen(prev);
1248        }
1249        debug(1000, "out");
1250}
1251
1252void freescreen()
1253{
1254        debug(1000, "in");
1255        struct skin *node = skin, *prev = skin;
1256
1257        while(node != NULL)
1258        {
1259                prev = node;
1260                node = node->next;
1261                if(prev != NULL)
1262                        delscreen(prev);
1263        }
1264        debug(1000, "out");
1265}
1266
1267inline unsigned long getpixelbuf(char* buf, int posx, int posy, int bufwidth)
1268{
1269        unsigned long *tmpbuf = (unsigned long*)buf;
1270        if(buf == NULL) return 0;
1271
1272        return tmpbuf[(bufwidth * posy) + posx];
1273}
1274
1275inline unsigned long getpixelfast(int posx, int posy)
1276{
1277        return skinfb->fblong[posy + posx];
1278}
1279
1280inline unsigned long getpixel(int posx, int posy)
1281{
1282        return skinfb->fblong[(skinfb->width * posy) + posx];
1283}
1284
1285inline void drawpixelfast(int posx, int posy, unsigned long color)
1286{
1287        skinfb->fblong[posy + posx] = color;
1288}
1289
1290inline void drawpixel(int posx, int posy, unsigned long color)
1291{
1292        skinfb->fblong[(skinfb->width * posy) + posx] = color;
1293}
1294
1295inline void drawpixelfb(struct fb* node, int posx, int posy, unsigned long color)
1296{
1297        node->fblong[(node->width * posy) + posx] = color;
1298}
1299
1300unsigned char* scale(unsigned char* buf, int width, int height, int channels, int newwidth, int newheight, int free1)
1301{
1302        debug(1000, "out");
1303        int h, w, pixel, nmatch;
1304
1305        if(buf == NULL)
1306        {
1307                err("out -> NULL detect");
1308                return NULL;
1309        }
1310
1311        unsigned char *newbuf = malloc(newwidth * newheight * channels);
1312        if(newbuf == NULL)
1313        {
1314                err("no mem");
1315                return NULL;
1316        }
1317
1318        double scalewidth = (double)newwidth / (double)width;
1319        double scaleheight = (double)newheight / (double)height;
1320
1321        for(h = 0; h < newheight; h++)
1322        {
1323                for(w = 0; w < newwidth; w++)
1324                {
1325                        pixel = (h * (newwidth * channels)) + (w * channels);
1326                        nmatch = (((int)(h / scaleheight) * (width * channels)) + ((int)(w / scalewidth) * channels));
1327                        if(channels > 0)
1328                                newbuf[pixel] = buf[nmatch];
1329                        if(channels > 1)
1330                                newbuf[pixel + 1] = buf[nmatch + 1];
1331                        if(channels > 2)
1332                                newbuf[pixel + 2] = buf[nmatch + 2];
1333                        if(channels > 3)
1334                                newbuf[pixel + 3] = buf[nmatch + 3];
1335                }
1336        }
1337
1338        if(free1 == 1) free(buf);
1339        debug(1000, "out");
1340        return newbuf;
1341}
1342
1343struct jpgerror
1344{
1345        struct jpeg_error_mgr jerr;
1346        jmp_buf setjmpbuf;
1347};
1348
1349void jpgswerror(j_common_ptr cinfo)
1350{
1351        struct jpgerror* jpgerr = (struct jpgerror*)cinfo->err;
1352        (*cinfo->err->output_message) (cinfo);
1353        longjmp(jpgerr->setjmpbuf, 1);
1354}
1355
1356void calcautoscale(int width, int height, int mwidth, int mheight, int* scalewidth, int* scaleheight)
1357{
1358        if(width < mwidth && height < mheight && height > 0)
1359        {
1360                *scaleheight = mheight;
1361                *scalewidth = width * (mheight / height);
1362               
1363                if(*scalewidth > mwidth && width > 0)
1364                {
1365                        *scalewidth = mwidth;
1366                        *scaleheight = height * (mwidth / width);
1367                }                               
1368        }
1369        else if(width < mwidth && height > mheight && mheight > 0 && (height / mheight) > 0)
1370        {
1371                *scaleheight = mheight;
1372                *scalewidth = width / (height / mheight);
1373        }
1374        else if(width > mwidth && height < mheight && mwidth > 0 && (width / mwidth) > 0)
1375        {
1376                *scalewidth = mwidth;
1377                *scaleheight = height / (width / mwidth);
1378        }
1379        else if(width > mwidth && height > mheight && mheight > 0 && (height / mheight) > 0)
1380        {
1381                *scaleheight = mheight;
1382                *scalewidth = width / (height / mheight);
1383               
1384                if(*scalewidth > mwidth && mwidth > 0 && (width / mwidth) > 0)
1385                {
1386                        *scalewidth = mwidth;
1387                        *scaleheight = height / (width / mwidth);
1388                }
1389        }
1390}
1391
1392unsigned char *loadjpg(char *filename, int *width, int *height, int denom)
1393{
1394        struct jpeg_decompress_struct cinfo;
1395        struct jpeg_decompress_struct *ciptr = &cinfo;
1396        struct jpgerror jerr;
1397        FILE *fd = NULL;
1398        unsigned char *buf = NULL;
1399
1400        fd = fopen(filename, "rb");
1401        if(fd == NULL)
1402        {
1403                perr("open jpg file %s", filename);
1404                return NULL;
1405        }
1406
1407        ciptr->err = jpeg_std_error(&jerr.jerr);
1408        jerr.jerr.error_exit = jpgswerror;
1409        if(setjmp(jerr.setjmpbuf))
1410        {
1411                jpeg_destroy_decompress(ciptr);
1412                fclose(fd);
1413                return NULL;
1414        }
1415
1416        jpeg_create_decompress(ciptr);
1417        jpeg_stdio_src(ciptr, fd);
1418        jpeg_read_header(ciptr, TRUE);
1419        ciptr->out_color_space = JCS_RGB;
1420        ciptr->scale_denom = denom;
1421
1422        jpeg_start_decompress(ciptr);
1423       
1424        *width = ciptr->output_width;
1425        *height = ciptr->output_height;
1426
1427        if(ciptr->output_components == 3)
1428        {
1429                JSAMPLE *lb = (JSAMPLE *)(*ciptr->mem->alloc_small)((j_common_ptr) ciptr, JPOOL_PERMANENT, ciptr->output_width * ciptr->output_components);
1430                buf = malloc(ciptr->output_height * ciptr->output_width * ciptr->output_components);
1431                if(buf == NULL)
1432                {
1433                        err("no mem");
1434                        jpeg_destroy_decompress(ciptr);
1435                        fclose(fd);
1436                        return NULL;
1437                }
1438
1439                unsigned char *bp = buf;
1440
1441                while(ciptr->output_scanline < ciptr->output_height)
1442                {
1443                        jpeg_read_scanlines(ciptr, &lb, 1);
1444                        memcpy(bp, lb, ciptr->output_width * ciptr->output_components);
1445                        bp += ciptr->output_width * ciptr->output_components;
1446                }
1447        }
1448
1449        jpeg_finish_decompress(ciptr);
1450        jpeg_destroy_decompress(ciptr);
1451        fclose(fd);
1452        return(buf);
1453}
1454
1455int savejpg(char * filename, int width, int height, unsigned char *buf)
1456{
1457        struct jpeg_compress_struct cinfo;
1458        struct jpeg_error_mgr jerr;
1459        FILE * outfile;         
1460        JSAMPROW pointer[1];
1461        int stride;             
1462 
1463        cinfo.err = jpeg_std_error(&jerr);
1464        jpeg_create_compress(&cinfo);
1465 
1466        if((outfile = fopen(filename, "wb")) == NULL)
1467        {
1468                perr("jpeg can't open %s", filename);
1469                return 1;
1470        }
1471
1472        jpeg_stdio_dest(&cinfo, outfile);
1473 
1474        cinfo.image_width = width;
1475        cinfo.image_height = height;
1476        cinfo.input_components = 3;
1477        cinfo.in_color_space = JCS_RGB;
1478        jpeg_set_defaults(&cinfo);
1479        jpeg_set_quality(&cinfo, 70, TRUE);
1480        jpeg_start_compress(&cinfo, TRUE);
1481        stride = width * 3;
1482
1483        while (cinfo.next_scanline < cinfo.image_height)
1484        {
1485                pointer[0] = & buf[cinfo.next_scanline * stride];
1486                jpeg_write_scanlines(&cinfo, pointer, 1);
1487        }
1488
1489        jpeg_finish_compress(&cinfo);
1490        fclose(outfile);
1491        jpeg_destroy_compress(&cinfo);
1492        return 0;
1493}
1494
1495int readjpgsw(const char* filename, int posx, int posy, int mwidth, int mheight, int scalewidth, int scaleheight, int halign, int valign)
1496{
1497        struct jpeg_decompress_struct cinfo;
1498        struct jpgerror jerr;
1499        JSAMPARRAY buffer;
1500        FILE* fd = NULL;
1501        int x = 0, row_stride = 0, py = 0, width = 0, height = 0;
1502        unsigned char red, green, blue;
1503        unsigned long color;
1504
1505        fd = fopen(filename, "rb");
1506        if(fd == NULL)
1507        {
1508                perr("open jpg file %s", filename);
1509                return 1;
1510        }
1511
1512        cinfo.err = jpeg_std_error(&jerr.jerr);
1513        jerr.jerr.error_exit = jpgswerror;
1514        if(setjmp(jerr.setjmpbuf))
1515        {
1516                jpeg_destroy_decompress(&cinfo);
1517                fclose(fd);
1518                return 1;
1519        }
1520
1521        jpeg_create_decompress(&cinfo);
1522        jpeg_stdio_src(&cinfo, fd);
1523        jpeg_read_header(&cinfo, TRUE);
1524        cinfo.out_color_space = JCS_RGB;
1525       
1526        if((scalewidth != 0 || scaleheight != 0) && (mwidth < 300 || mheight < 300))
1527                cinfo.scale_denom = getconfigint("picdenom", NULL);
1528        else
1529                cinfo.scale_denom = 1;
1530
1531        jpeg_start_decompress(&cinfo);
1532        width = cinfo.output_width;
1533        height = cinfo.output_height;
1534
1535        row_stride = cinfo.output_width * cinfo.output_components;
1536        buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
1537
1538        if(accelfb != NULL && accelfb->varfbsize > width * 8 && (scalewidth != 0 || scaleheight != 0))
1539        {
1540                //auto scale to mwidth / mheight
1541                if(scalewidth == 1 && scaleheight == 1)
1542                        calcautoscale(width, height, mwidth, mheight, &scalewidth, &scaleheight);
1543               
1544                if(scalewidth == 0) scalewidth = width;
1545                if(scaleheight == 0) scaleheight = height;
1546                if(scalewidth > mwidth) scalewidth = mwidth;
1547                if(scaleheight > mheight) scaleheight = mheight;
1548
1549                if(halign == CENTER)
1550                        posx += mwidth / 2 - scalewidth / 2;
1551                else if(halign == RIGHT)
1552                        posx += mwidth - scalewidth;
1553                if(valign == MIDDLE)
1554                        posy += mheight / 2 - scaleheight / 2;
1555                else if(valign == BOTTOM)
1556                        posy += mheight - scaleheight;
1557       
1558                int nposy = posy;
1559                py = -1;
1560
1561                m_lock(&status.accelfbmutex, 16);
1562                while(cinfo.output_scanline < height)
1563                {
1564                        jpeg_read_scanlines(&cinfo, buffer, 1);
1565                        py++;
1566                        for(x = 0; x < width; x++)
1567                        {
1568                                red = buffer[0][cinfo.output_components * x];
1569                                if(cinfo.output_components > 2)
1570                                {
1571                                        green = buffer[0][cinfo.output_components * x + 1];
1572                                        blue = buffer[0][cinfo.output_components * x + 2];
1573                                }
1574                                else
1575                                {
1576                                        green = red;
1577                                        blue = red;
1578                                }
1579                                color = (255 << 24) | (red << 16) | (green << 8) | blue;
1580                                drawpixelfb(accelfb, (width * py) + x, 0, color);
1581                        }
1582                        if((py * width * 4) + (width * 8) >= accelfb->varfbsize)
1583                        {
1584                                if(scaleheight > 0)
1585                                {
1586                                        float tmp = (float)height / (float)scaleheight;
1587                                        if(tmp > 0)
1588                                        {
1589                                                tmp = (float)py / tmp;
1590                                                blitscale(posx, nposy, width, py, scalewidth, (int)tmp, 0);
1591                                                nposy += tmp;
1592                                        }
1593                                }
1594                                py = -1;
1595                        }
1596                }
1597                //blit the rest
1598                if(scaleheight > 0 && py > 0)
1599                {
1600                        float tmp = (float)height / (float)scaleheight;
1601                        if(tmp > 0)
1602                        {
1603                                tmp = (float)py / tmp;
1604                                blitscale(posx, nposy, width, py, scalewidth, (int)tmp, 0);
1605                        }
1606                }
1607                m_unlock(&status.accelfbmutex, 16);
1608        }
1609        else
1610        {
1611                if(width > mwidth) width = mwidth;
1612                if(height > mheight) height = mheight;
1613
1614                if(halign == CENTER)
1615                        posx += mwidth / 2 - width / 2;
1616                else if(halign == RIGHT)
1617                        posx += mwidth - width;
1618                if(valign == MIDDLE)
1619                        posy += mheight / 2 - height / 2;
1620                else if(valign == BOTTOM)
1621                        posy += mheight - height;
1622
1623                while(cinfo.output_scanline < height)
1624                {
1625                        jpeg_read_scanlines(&cinfo, buffer, 1);
1626                        py = (posy + cinfo.output_scanline - 1) * skinfb->width;
1627                        for(x = 0; x < width; x++)
1628                        {
1629                                red = buffer[0][cinfo.output_components * x];
1630                                if(cinfo.output_components > 2)
1631                                {
1632                                        green = buffer[0][cinfo.output_components * x + 1];
1633                                        blue = buffer[0][cinfo.output_components * x + 2];
1634                                }
1635                                else
1636                                {
1637                                        green = red;
1638                                        blue = red;
1639                                }
1640                                color = (255 << 24) | (red << 16) | (green << 8) | blue;
1641                                drawpixelfast(posx + x, py, color);
1642                        }
1643                }
1644        }
1645        jpeg_finish_decompress(&cinfo);
1646        jpeg_destroy_decompress(&cinfo);
1647        fclose(fd);
1648        return 0;
1649}
1650
1651unsigned char* readpng(const char* filename, unsigned long* width, unsigned long* height, unsigned long* rowbytes, int* channels, int posx, int posy, int mwidth, int mheight, int halign, int valign)
1652{
1653        debug(1000, "in");
1654        FILE *fd = NULL;
1655        int ret, bit_depth, color_type;
1656        unsigned char *buf = NULL;
1657        static png_structp png_ptr = NULL;
1658        static png_infop info_ptr = NULL;
1659        double gamma;
1660        png_uint_32 y;
1661        png_bytepp row_pointers = NULL;
1662        png_bytep sig = NULL;
1663
1664        fd = fopen(filename, "rb");
1665        if(fd == NULL)
1666        {
1667                perr("open png file %s", filename);
1668                return NULL;
1669        }
1670
1671        sig = malloc(8);
1672        if(sig == NULL)
1673        {
1674                err("no memory");
1675                fclose(fd);
1676                return NULL;
1677        }
1678
1679        fread(sig, 1, 8, fd);
1680        ret = png_check_sig(sig, 8);
1681        if(ret == 0)
1682        {
1683                err("%s is not a PNG file", filename);
1684                free(sig);
1685                fclose(fd);
1686                return NULL;
1687        }
1688
1689        png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1690        if(png_ptr == NULL)
1691        {
1692                err("%s no memory", filename);
1693                free(sig);
1694                fclose(fd);
1695                return NULL;
1696        }
1697
1698        info_ptr = png_create_info_struct(png_ptr);
1699        if(info_ptr == NULL)
1700        {
1701                png_destroy_read_struct(&png_ptr, NULL, NULL);
1702                err("%s no memory", filename);
1703                free(sig);
1704                fclose(fd);
1705                return NULL;
1706        }
1707
1708        ret = setjmp(png_jmpbuf(png_ptr));
1709        if(ret != 0)
1710        {
1711                png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
1712                err("%s has bad IHDR (libpng longjmp)", filename);
1713                free(sig);
1714                fclose(fd);
1715                return NULL;
1716        }
1717
1718        png_init_io(png_ptr, fd);
1719        png_set_sig_bytes(png_ptr, 8);
1720        png_read_info(png_ptr, info_ptr);
1721        png_get_IHDR(png_ptr, info_ptr, width, height, &bit_depth, &color_type, NULL, NULL, NULL);
1722
1723        ret = setjmp(png_jmpbuf(png_ptr));
1724        if(ret != 0)
1725        {
1726                png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
1727                err("%s unknown error", filename);
1728                free(sig);
1729                fclose(fd);
1730                return NULL;
1731        }
1732
1733        if(color_type == PNG_COLOR_TYPE_PALETTE)
1734                png_set_expand(png_ptr);
1735        if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
1736                png_set_expand(png_ptr);
1737        if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
1738                png_set_expand(png_ptr);
1739        if(bit_depth == 16)
1740                png_set_strip_16(png_ptr);
1741        if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1742                png_set_gray_to_rgb(png_ptr);
1743        if(png_get_gAMA(png_ptr, info_ptr, &gamma))
1744                png_set_gamma(png_ptr, 2.2, gamma);
1745
1746        png_read_update_info(png_ptr, info_ptr);
1747        *rowbytes = png_get_rowbytes(png_ptr, info_ptr);
1748        *channels = (int)png_get_channels(png_ptr, info_ptr);
1749
1750        buf = malloc((*rowbytes) * (*height));
1751        if(buf == NULL)
1752        {
1753                png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
1754                err("%s no memory", filename);
1755                free(sig);
1756                fclose(fd);
1757                return NULL;
1758        }
1759
1760        row_pointers = (png_bytepp)malloc((*height) * sizeof(png_bytep));
1761        if(row_pointers == NULL)
1762        {
1763                png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
1764                err("%s unknown error", filename);
1765                free(sig);
1766                fclose(fd);
1767                return NULL;
1768        }
1769
1770        for (y = 0; y < (*height); ++y)
1771                row_pointers[y] = (png_bytep)buf + y * (*rowbytes);
1772
1773        png_read_image(png_ptr, row_pointers);
1774        free(row_pointers);
1775        row_pointers = NULL;
1776
1777        png_read_end(png_ptr, NULL);
1778        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
1779
1780        free(sig);
1781        fclose(fd);
1782
1783        debug(100, "png width=%ld height=%ld channels=%d rowbytes=%ld", *width, *height, *channels, *rowbytes);
1784
1785        debug(1000, "out");
1786        return buf;
1787}
1788
1789void drawpic(const char* filename, int posx, int posy, int scalewidth, int scaleheight, int mwidth, int mheight, int halign, int valign)
1790{
1791        debug(1000, "in");
1792        unsigned char *buf = NULL, *scalebuf = NULL;
1793        int memfd = -1, py = 0, pyh = 0, pxw = 0, diff = 0;
1794        unsigned long width, height, rowbytes;
1795        int channels, length;
1796        unsigned char *src;
1797        png_uint_32 y, x;
1798        struct pic* picnode = NULL;
1799        int decoding = getconfigint("pichwdecode", NULL);
1800        int pictype = 0; //0 = png, 1 = jpg HW, 2 = jpg SW
1801
1802        length = strlen(filename);
1803        if(filename[length - 1] == 'g' && filename[length - 2] == 'n' && filename[length - 3] == 'p')
1804                pictype = 0;
1805        else if(decoding == 1)
1806                pictype = 1;
1807        else
1808                pictype = 2;
1809
1810        picnode = getpic((char*)filename);
1811        if(picnode == NULL)
1812        {
1813                if(pictype == 0)
1814                        buf = readpng(filename, &width, &height, &rowbytes, &channels, 0, 0, 0, 0, 0, 0);
1815                else if(pictype == 1)
1816                        readjpg(filename, &width, &height, &rowbytes, &channels, &buf, &memfd);
1817                else if(pictype == 2)
1818                        readjpgsw(filename, posx, posy, mwidth, mheight, scalewidth, scaleheight, halign, valign);
1819        }
1820        else
1821        {
1822                buf = picnode->picbuf;
1823                width = picnode->width;
1824                height = picnode->height;
1825                rowbytes = picnode->rowbytes;
1826                channels = picnode->channels;
1827                memfd = picnode->memfd;
1828        }
1829
1830        if((pictype == 0 || pictype == 1) && buf == NULL) return;
1831
1832        if(pictype == 0 && (scalewidth != 0 || scaleheight != 0))
1833        {
1834                //auto scale to mwidth / mheight
1835                if(scalewidth == 1 && scaleheight == 1)
1836                        calcautoscale(width, height, mwidth, mheight, &scalewidth, &scaleheight);
1837       
1838                if(scalewidth == 0) scalewidth = width;
1839                if(scaleheight == 0) scaleheight = height;
1840                if(picnode == NULL)
1841                        scalebuf = scale(buf, rowbytes / channels, height, channels, scalewidth, scaleheight, 1);
1842                else
1843                {
1844                        scalebuf = scale(buf, rowbytes / channels, height, channels, scalewidth, scaleheight, 0);
1845                        buf = NULL;
1846                        picnode = NULL;
1847                }
1848                if(scalebuf != NULL)
1849                {
1850                        buf = scalebuf;
1851                        width = scalewidth;
1852                        height = scaleheight;
1853                        rowbytes = scalewidth * (channels);
1854                }
1855        }
1856
1857        if(pictype == 0)
1858        {
1859                if(width > mwidth) width = mwidth;
1860                if(height > mheight) height = mheight;
1861
1862                if(halign == CENTER)
1863                        posx += mwidth / 2 - width / 2;
1864                else if(halign == RIGHT)
1865                        posx += mwidth - width;
1866                if(valign == MIDDLE)
1867                        posy += mheight / 2 - height / 2;
1868                else if(valign == BOTTOM)
1869                        posy += mheight - height;
1870
1871                py = (posy * skinfb->width) + posx;
1872                pyh = py + (height * skinfb->width);
1873                src = buf;
1874                diff = rowbytes - (width * channels);
1875
1876                if(channels == 3)
1877                {
1878                        for(y = py; y < pyh; y += skinfb->width)
1879                        {
1880                                pxw = y + width;
1881                                for(x = y; x < pxw; x++)
1882                                {
1883                                        skinfb->fblong[x] = (255 << 24) | (src[0] << 16) | (src[1] << 8) | src[2];
1884                                        src += 3;
1885                                }
1886                                src += diff;
1887                        }
1888                }
1889                else
1890                {
1891                        for(y = py; y < pyh; y += skinfb->width)
1892                        {
1893                                pxw = y + width;
1894                                for(x = y; x < pxw; x++)
1895                                {
1896                                        if(src[3] < 10)
1897                                        {
1898                                                src += 4;
1899                                                continue;
1900                                        }
1901                                        skinfb->fblong[x] = (src[3] << 24) | (src[0] << 16) | (src[1] << 8) | src[2];
1902                                        src += 4;
1903                                }
1904                                src += diff;
1905                        }
1906                }
1907        }
1908        else if(pictype == 1 && memfd > -1)
1909                blitjpg(buf, posx, posy, width, height, scalewidth, scaleheight, mwidth, mheight, halign, valign);
1910
1911        if(picnode == NULL)
1912        {
1913                if(pictype == 0)
1914                        free(buf);
1915                else if(pictype == 1)
1916                        freebpamem(memfd, buf, width * height * 3);
1917        }
1918       
1919        debug(1000, "out");
1920}
1921
1922//flag 0: don't del outside
1923//flag 1: del outside
1924void drawcircle(int x0, int y0, int radius, int startangle, int endangle, long color, int transparent, char* bg, int flag)
1925{
1926        float d = (5/4.0) - radius, theta;
1927        int x = 0, y = radius, px = 0, py = 0;
1928
1929        transparent = (transparent - 255) * -1;
1930        unsigned long tmpcol = color | ((transparent & 0xff) << 24);
1931
1932        while(y > x)
1933        {
1934                if(d < 0)
1935                        d += 2 * x + 3;
1936                else
1937                {
1938                        d += (2 * x) - (2 * y) + 5;
1939                        y--;
1940                }
1941                x++;
1942
1943                theta = (atan((float)y / x)) * (180 / 3.14);
1944
1945                //rt2
1946                if(theta >= startangle && theta <= endangle)
1947                {
1948                        px = x0 + x;
1949                        py = (y0 - y) * skinfb->width;
1950                        drawpixelfast(px, py, tmpcol);
1951                        if(flag == 1)
1952                        {
1953                                int i = radius - x;
1954                                int r = radius - y;
1955                                for(; i > 0; i--)
1956                                        drawpixelfast(px + i, py, getpixelbuf(bg, x + i - 1, r, radius));
1957                        }
1958                }
1959                //rb2
1960                if(360 - theta >= startangle && 360 - theta <= endangle)
1961                {
1962                        px = x0 + x;
1963                        py = (y0 + y) * skinfb->width;
1964                        drawpixelfast(px, py, tmpcol);
1965                        if(flag == 1)
1966                        {
1967                                int i = radius - x;
1968                                int r = y - 1;
1969                                for(; i > 0; i--)
1970                                        drawpixelfast(px + i, py, getpixelbuf(bg, x + i - 1, r, radius));
1971                        }
1972                }
1973                //rt1
1974                if(90 - theta >= startangle && 90 - theta <= endangle)
1975                {
1976                        px = x0 + y;
1977                        py = (y0 - x) * skinfb->width;
1978                        drawpixelfast(px, py, tmpcol);
1979                        if(flag == 1)
1980                        {
1981                                int i = radius - y;
1982                                int r = radius - x;
1983                                for(; i > 0; i--)
1984                                        drawpixelfast(px + i, py, getpixelbuf(bg, y + i - 1, r, radius));
1985                        }
1986                }
1987                //rb1
1988                if(270 + theta >= startangle && 270 + theta <= endangle)
1989                {
1990                        px = x0 + y;
1991                        py = (y0 + x) * skinfb->width;
1992                        drawpixelfast(px, py, tmpcol);
1993                        if(flag == 1)
1994                        {
1995                                int i = radius - y;
1996                                int r = x - 1;
1997                                for(; i > 0; i--)
1998                                        drawpixelfast(px + i, py, getpixelbuf(bg, y + i - 1, r, radius));
1999                        }
2000                }
2001                //lt2
2002                if(180 - theta >= startangle && 180 - theta <= endangle)
2003                {
2004                        px = x0 - x;
2005                        py = (y0 - y) * skinfb->width;
2006                        drawpixelfast(px, py, tmpcol);
2007                        if(flag == 1)
2008                        {
2009                                int i = radius - x;
2010                                int r = radius - y;
2011                                for(; i > 0; i--)
2012                                        drawpixelfast(px - i, py, getpixelbuf(bg, radius - x - i, r, radius));
2013                        }
2014                }
2015                //lb2
2016                if(180 + theta >= startangle && 180 + theta <= endangle)
2017                {
2018                        px = x0 - x;
2019                        py = (y0 + y) * skinfb->width;
2020                        drawpixelfast(px, py, tmpcol);
2021                        if(flag == 1)
2022                        {
2023                                int i = radius - x;
2024                                int r = y - 1;
2025                                for(; i > 0; i--)
2026                                        drawpixelfast(px - i, py, getpixelbuf(bg, radius - x - i, r, radius));
2027                        }
2028                }
2029                //lt1
2030                if(90 + theta >= startangle && 90 + theta <= endangle)
2031                {
2032                        px = x0 - y;
2033                        py = (y0 - x) * skinfb->width;
2034                        drawpixelfast(px, py, tmpcol);
2035                        if(flag == 1)
2036                        {
2037                                int i = radius - y;
2038                                int r = radius - x;
2039                                for(; i > 0; i--)
2040                                        drawpixelfast(px - i, py, getpixelbuf(bg, radius - y - i, r, radius));
2041                        }
2042                }
2043                //lb1
2044                if(270 - theta >= startangle && 270 - theta <= endangle)
2045                {
2046                        px = x0 - y;
2047                        py = (y0 + x) * skinfb->width;
2048                        drawpixelfast(px, py, tmpcol);
2049                        if(flag == 1)
2050                        {
2051                                int i = radius - y;
2052                                int r = x - 1;
2053                                for(; i > 0; i--)
2054                                        drawpixelfast(px - i, py, getpixelbuf(bg, radius - y - i , r, radius));
2055                        }
2056                }
2057        }
2058}
2059
2060int drawchar(struct font* font, FT_ULong currentchar, int posx, int posy, int mwidth, int height, long color, int transparent, int charspace, int test)
2061{
2062//      debug(1000, "in");
2063        int space = 0, y = 0, x = 0, py = 0, pxw = 0, pyh = 0, max = 220, min = 35;
2064        FT_UInt glyphindex;
2065        FT_Vector kerning;
2066        FT_Error ret;
2067        FTC_SBit sbit;
2068        unsigned long tmpcol = 0, tmpcol1 = 0;
2069        long buffercol = 0;
2070        unsigned char red, green, blue, r, g, b;
2071        unsigned char* src = NULL;
2072
2073        if(currentchar == 32) space = 1;
2074
2075        glyphindex = FT_Get_Char_Index(font->face, currentchar);
2076        if(glyphindex == 0)
2077        {
2078                debug(100, "FT_Get_Char_Index for char %x %c failed", (int)currentchar, (int)currentchar);
2079                return 0;
2080        }
2081
2082        FTC_Node anode;
2083        ret = FTC_SBitCache_Lookup(font->cache, &font->desc, glyphindex, &sbit, &anode);
2084
2085        if(ret != 0)
2086        {
2087                err("FTC_SBitCache_Lookup for char %x %c failed. Error: 0x%.2X", (int)currentchar, (int)currentchar, ret);
2088                return 0;
2089        }
2090
2091        if(font->use_kerning)
2092        {
2093                FT_Get_Kerning(font->face, font->prev_glyphindex, glyphindex, ft_kerning_default, &kerning);
2094                font->prev_glyphindex = glyphindex;
2095                kerning.x >>= 6;
2096        }
2097        else
2098                kerning.x = 0;
2099
2100        if (test == 1 || space == 1)
2101        {
2102                //debug(1000, "out -> test or space");
2103                return sbit->xadvance + kerning.x + charspace;
2104        }
2105        if(posx + sbit->xadvance > mwidth)
2106        {
2107                //debug(1000, "out -> text to long");
2108                return -1;
2109        }
2110
2111        if(status.fasttextrender == 1) max = min - 1;
2112       
2113        red = (color & 0xff0000) >> 16;
2114        green = (color & 0x00ff00) >> 8;
2115        blue = color & 0xff;
2116        transparent = transparent & 0xff;
2117        tmpcol = color | transparent << 24;
2118        posy = posy + height - sbit->top;
2119        posx = posx + sbit->left + kerning.x;
2120               
2121        py = (posy * skinfb->width) + posx;
2122        pyh = py + (sbit->height * skinfb->width);
2123        src = sbit->buffer;
2124               
2125        for(y = py; y < pyh; y += skinfb->width)
2126        {
2127                pxw = y + sbit->pitch;
2128                for(x = y; x < pxw; x++)
2129                {
2130                        buffercol = src[0];
2131                        src++;
2132                        if(buffercol)
2133                        {
2134                                //renderquality 255-0 = best
2135                                if(buffercol > max)
2136                                        skinfb->fblong[x] = tmpcol;
2137                                else if(buffercol < min)
2138                                        continue;
2139                                else
2140                                {
2141                                        tmpcol1 = skinfb->fblong[x];
2142                                        alpha_composite(r, red, buffercol, (tmpcol1 & 0xff0000) >> 16);
2143                                        alpha_composite(g, green, buffercol, (tmpcol1 & 0x00ff00) >> 8);
2144                                        alpha_composite(b, blue, buffercol, tmpcol1 & 0xff);
2145                                        skinfb->fblong[x] = transparent << 24 | r << 16 | g << 8 | b;
2146                                }
2147                        }
2148                }
2149        }
2150
2151//      debug(1000, "out");
2152        return sbit->xadvance + kerning.x + charspace;
2153}
2154
2155void getstringwh(struct font* font, char *string, int *stringwidth, int *stringheight, int charspace)
2156{
2157        debug(1000, "in");
2158        FT_ULong cret = 0;
2159        if(string == NULL) return;
2160
2161        while(*string != '\0' && *string != '\n')
2162        {
2163                string += strfreetype(string, &cret);
2164                *stringwidth += drawchar(font, cret, 0, 0, 0, 0, 0, 0, charspace, 1);
2165                string++;
2166        }
2167        debug(1000, "out");
2168}
2169
2170int calcstrhalign(struct font* aktfont, char *string, int posx, int mwidth, int halign, int charspace)
2171{
2172        int stringwidth = 0, stringheight = 0;
2173        if(string == NULL) return 0;
2174
2175        switch(halign)
2176        {
2177                case TEXTCENTER:
2178                case CENTER:
2179                        getstringwh(aktfont, string, &stringwidth, &stringheight, charspace);
2180                        if(stringwidth < mwidth) posx += (mwidth - stringwidth) / 2;
2181                        break;
2182                case TEXTRIGHT:
2183                case RIGHT:
2184                        getstringwh(aktfont, string, &stringwidth, &stringheight, charspace);
2185                        if(stringwidth < mwidth) posx += mwidth - stringwidth;
2186                        break;
2187        }
2188        return posx;
2189}
2190
2191int calcstrvalign(char *string, int posy, int oldposy, int mheight, int fontsize, int linecount, int valign)
2192{
2193        if(string == NULL) return 0;
2194
2195        switch(valign)
2196        {
2197                case TEXTMIDDLE:
2198                case MIDDLE:
2199                        posy += mheight / 2 - (fontsize * linecount) / 2;
2200                        if(posy < oldposy) posy = oldposy;
2201                        break;
2202                case TEXTBOTTOM:
2203                case BOTTOM:
2204                        posy += mheight - (fontsize * linecount);
2205                        if(posy < oldposy) posy = oldposy;
2206                        break;
2207        }
2208
2209        return posy;
2210}
2211
2212struct font* setaktfont(char* fontname, int fontsize)
2213{
2214        struct font* aktfont = NULL;
2215
2216        if(fontname != NULL) aktfont = getfont(fontname);
2217        if(aktfont == NULL) aktfont = font;
2218
2219        aktfont->desc.width = fontsize;
2220        aktfont->desc.height = fontsize;
2221        if(status.fasttextrender == 1)
2222                aktfont->desc.flags = FT_LOAD_MONOCHROME;
2223        else
2224                aktfont->desc.flags = FT_LOAD_DEFAULT;
2225
2226        aktfont->prev_glyphindex = 0;
2227
2228        return aktfont;
2229}
2230
2231void wrapstr(char* string, char* fontname, int fontsize, int mwidth, int charspace)
2232{
2233        int posx = 0;
2234        int stringheight = 0, stringwidth = 0;
2235        struct font* aktfont = NULL;
2236        char* tmpstr = NULL, *origstr = string;
2237        unsigned char c = 0;
2238
2239        aktfont = setaktfont(fontname, fontsize);
2240
2241        while(*string != '\0')
2242        {
2243                stringheight = 0; stringwidth = 0;
2244
2245                tmpstr = string;
2246
2247                while(*string != '\0' && *string != '\n' && *string != ' ' && *string != '-')
2248                        string++;
2249                if(*string == '\n')
2250                {
2251                        if(*string != '\0') string++;
2252                        posx = 0;
2253                }
2254                else
2255                {
2256                        if(*string != '\0') string++;
2257                        c = *string; *string = '\0';
2258
2259                        getstringwh(aktfont, tmpstr, &stringwidth, &stringheight, charspace);
2260                        *string = c;
2261
2262                        posx += stringwidth;
2263                }
2264
2265                if(posx > mwidth && tmpstr > origstr)
2266                {       
2267                        tmpstr--;
2268                        *tmpstr = '\n';
2269                        posx = stringwidth;
2270                }
2271        }
2272}
2273
2274
2275int drawstring(char* string, unsigned long linecount, unsigned int poscount, unsigned int markpos, int posx, int posy, int mwidth, int mheight, int halign, int valign, char* fontname, int fontsize, long color, int transparent, int wrap, int* lastposx, int* lastposy, int* len, int charspace)
2276{
2277        debug(1000, "in");
2278        int charwidth = 0, lineend = 0;
2279        int charcount = 0;
2280        if(lastposy == NULL || *lastposy == 0) posy=posy + FONTPOSYOFFSET;
2281        int oldposx = posx, aktheight = 0, ret = 0;
2282        int oldposy = posy, oldmwidth = mwidth;
2283        struct font* aktfont = NULL;
2284        long tmpcol = color;
2285        FT_ULong cret = 0;
2286
2287        if(string == NULL) return 1;
2288
2289        transparent = (transparent - 255) * -1;
2290
2291        if(linecount < 2 && (fontsize == 0 || fontsize > mheight))
2292                fontsize = mheight;
2293
2294        aktfont = setaktfont(fontname, fontsize);
2295
2296        string = string + poscount;
2297
2298        if(fontsize < 5)
2299        {
2300                debug(1000, "out -> fontsize to small");
2301                return 1;
2302        }
2303
2304        posx = calcstrhalign(aktfont, string, posx, oldmwidth, halign, charspace);
2305        posy = calcstrvalign(string, posy, oldposy, mheight, fontsize, linecount, valign);
2306
2307        mwidth = posx + mwidth;
2308        aktheight += fontsize;
2309        if(aktheight > mheight)
2310        {
2311                debug(1000, "out -> to many textlines");
2312                return 1;
2313        }
2314
2315        while(*string != '\0')
2316        {
2317                charcount++;
2318                if(markpos == charcount)
2319                        color = convertcol("markcol");
2320                else
2321                        color = tmpcol;
2322
2323                if(*string == '\n')
2324                {
2325                        if(linecount < 2) break;
2326                        lineend = 0;
2327                        aktheight += fontsize;
2328                        if(aktheight > mheight)
2329                        {
2330                                ret = 1;
2331                                break;
2332                        }
2333                        posy = posy + fontsize;
2334                        posx = oldposx;
2335                        string++;
2336                        posx = calcstrhalign(aktfont, string, posx, oldmwidth, halign, charspace);
2337                        continue;
2338                }
2339
2340                if(lineend == 1)
2341                {
2342                        string++;
2343                        continue;
2344                }
2345
2346                string += strfreetype(string, &cret);
2347
2348                if((charwidth = drawchar(aktfont, cret, posx, posy, mwidth, fontsize, color, transparent, charspace, 0)) == -1)
2349                        lineend = 1;
2350
2351                posx += charwidth;
2352                if(len != NULL) *len += charwidth;
2353                string++;
2354        }
2355        if(lastposx != NULL) *lastposx = posx;
2356        if(lastposy != NULL) *lastposy = posy + fontsize;
2357        debug(1000, "out");
2358        return ret;
2359}
2360
2361char* saverect(int posx, int posy, int width, int height)
2362{
2363        debug(1000, "in");
2364        char* buf;
2365        int y;
2366
2367        buf = malloc(width * height * skinfb->colbytes);
2368        if(buf == NULL)
2369        {
2370                err("no memory");
2371                return NULL;
2372        }
2373
2374        for(y = 0; y < height; y++)
2375        {
2376                memcpy(buf + width * skinfb->colbytes * y, skinfb->fb + ((y + posy) * skinfb->pitch) + (posx * skinfb->colbytes), width * skinfb->colbytes);
2377        }
2378
2379        debug(1000, "out");
2380        return buf;
2381}
2382
2383char* savescreen(struct skin* node)
2384{
2385        return saverect(node->rposx - node->shadowsize, node->rposy - node->shadowsize, node->rwidth + (node->shadowsize * 2), node->rheight + (node->shadowsize * 2));
2386}
2387
2388void restorerect(char* buf, int posx, int posy, int width, int height)
2389{
2390        debug(1000, "in");
2391        int y;
2392
2393        if(buf != NULL)
2394        {
2395                for(y = 0; y < height; y++)
2396                {
2397                        memcpy(skinfb->fb + ((y + posy) * skinfb->pitch) + (posx * skinfb->colbytes), buf + width * skinfb->colbytes * y,  width * skinfb->colbytes);
2398                }
2399                free(buf);
2400                buf = NULL;
2401        }
2402        debug(1000, "out");
2403}
2404
2405void restorescreen(char* buf, struct skin* node)
2406{
2407        restorerect(buf, node->rposx - node->shadowsize, node->rposy - node->shadowsize, node->rwidth + (node->shadowsize * 2), node->rheight + (node->shadowsize * 2));
2408}
2409
2410//*************** GOST LCD
2411void lcd_fillrect(int posx, int posy, int width, int height, long color, int transparent)
2412{
2413        //debug(1000, "in");
2414        int y, x;
2415        unsigned long tmpcol;
2416
2417        if(posx < 0) posx = 0;
2418        if(posx > skinfb->width) posx = skinfb->width;
2419        if(posy < 0) posy = 0;
2420        if(posy > skinfb->height) posy = skinfb->height;
2421        if(posx + width > skinfb->width) width = skinfb->width - posx;
2422        if(posy + height > skinfb->height) height = skinfb->height - posy;
2423
2424        if(width <= 0 || height <= 0) return;
2425
2426        transparent = (transparent - 255) * -1;
2427        tmpcol = color | ((transparent & 0xff) << 24);
2428
2429        for(y = 0; y < height; y++)
2430        {
2431                for(x = 0; x < width; x++)
2432                {
2433                        drawpixel(posx + x, posy + y, tmpcol);
2434                }
2435        }
2436        //debug(1000, "out");
2437}
2438
2439void lcd_drawrect(int posx, int posy, int width, int height, long color, int transparent)
2440{
2441        //debug(1000, "in");
2442        fillrect(posx, posy, width, 1, color, transparent);
2443        fillrect(posx, posy + height - 1, width, 1, color, transparent);
2444        fillrect(posx, posy, 1, height, color, transparent);
2445        fillrect(posx + width - 1, posy, 1, height, color, transparent);
2446        //debug(1000, "out");
2447}
2448//*************** GOST LCD
2449
2450/*
2451void fillrect(int posx, int posy, int width, int height, long color, int transparent)
2452{
2453        int r, g, b;
2454
2455        r = (color >> 16) & 0xFF;
2456        g = (color >> 8) & 0xFF;
2457        b = color & 0xFF;
2458
2459        primary->SetDrawingFlags(primary, DSDRAW_NOFX);
2460        primary->SetColor(primary, r, g, b, transparent);
2461        primary->FillRectangle(primary, posx, posy, width, height);
2462        primary->Flip(primary, NULL, DSFLIP_WAITFORSYNC);
2463}
2464
2465void drawrect(int posx, int posy, int width, int height, long color, int transparent)
2466{
2467        int r, g, b;
2468
2469        r = (color >> 16) & 0xFF;
2470        g = (color >> 8) & 0xFF;
2471        b = color & 0xFF;
2472
2473        primary->SetDrawingFlags(primary, DSDRAW_NOFX);
2474        primary->SetColor(primary, r, g, b, transparent);
2475        primary->DrawRectangle(primary, posx, posy, width, height);
2476        primary->Flip(primary, NULL, DSFLIP_WAITFORSYNC);
2477}
2478*/
2479
2480void fillrect(int posx, int posy, int width, int height, long color, int transparent)
2481{
2482        if(skinfb != lcdskinfb)
2483                blitrect(posx, posy, width, height, color, transparent, 0);
2484        else
2485                lcd_fillrect(posx, posy, width, height, color, transparent);
2486}
2487
2488void drawrect(int posx, int posy, int width, int height, long color, int transparent)
2489{
2490        if(skinfb != lcdskinfb)
2491                blitrect(posx, posy, width, height, color, transparent, 1);
2492        else
2493                lcd_drawrect(posx, posy, width, height, color, transparent);
2494}
2495
2496void clearrect(int posx, int posy, int width, int height)
2497{
2498        fillrect(posx, posy, width, height, 0, 255);
2499}
2500
2501void clearscreen(struct skin* node)
2502{
2503        m_lock(&status.drawingmutex, 0);
2504        clearrect(node->rposx, node->rposy, node->rwidth, node->rheight);
2505        clearshadow(node);
2506        m_unlock(&status.drawingmutex, 0);
2507}
2508
2509void clearscreennolock(struct skin* node)
2510{
2511        clearrect(node->rposx, node->rposy, node->rwidth, node->rheight);
2512        clearshadow(node);
2513}
2514
2515//flag 0 = horizontal
2516//flag 1 = vertical
2517//flag 2 = horizontal (begin to middle, middle to end)
2518//flag 3 = vertical (begin to middle, middle to end)
2519void drawgradient(int posx, int posy, int width, int height, long col1, long col2, int transparent, int flag)
2520{
2521        int p, i, x, y, steps, xstep, ystep;
2522        int xcount = 0, ycount = 0, owidth = width, oheight = height;
2523        unsigned char r3, g3, b3;
2524        unsigned long col = 0;
2525
2526        transparent = (transparent - 255) * -1;
2527
2528        if(flag == LEFTRIGHT || flag == LEFTMIDDLE)
2529        {
2530                if(flag == LEFTMIDDLE) width = width / 2;
2531                if(width < 100)
2532                        steps = width;
2533                else
2534                        steps = width / 5;
2535                xstep = width / steps;
2536                ystep = height;
2537        }
2538        else
2539        {
2540                if(flag == TOPMIDDLE) height = height / 2;
2541                if(height < 100)
2542                        steps = height;
2543                else
2544                        steps = height / 5;
2545                xstep = width;
2546                ystep = height / steps;
2547        }
2548
2549        unsigned char r1 = (col1 >> 16) & 0xff;
2550        unsigned char g1 = (col1 >> 8) & 0xff;
2551        unsigned char b1 = col1 & 0xff;
2552
2553        unsigned char r2 = (col2 >> 16) & 0xff;
2554        unsigned char g2 = (col2 >> 8) & 0xff;
2555        unsigned char b2 = col2 & 0xff;
2556
2557        for(i = 0; i < steps; i++)
2558        {
2559                p = steps - i;
2560                r3 = (r1 * p + r2 * i) / steps;
2561                g3 = (g1 * p + g2 * i) / steps;
2562                b3 = (b1 * p + b2 * i) / steps;
2563                col = (transparent << 24) | (r3 << 16) | (g3 << 8) | b3;
2564               
2565                for(y = 0; y < ystep; y++)
2566                        for(x = 0; x < xstep; x++)
2567                                drawpixel(posx + x, posy + y, col);
2568
2569                if(flag == LEFTRIGHT || flag == LEFTMIDDLE)
2570                {
2571                        posx += xstep;
2572                        xcount += xstep;
2573                }
2574                else
2575                {
2576                        posy += ystep;
2577                        ycount += ystep;
2578                }
2579        }
2580
2581        if(flag == LEFTMIDDLE || flag == TOPMIDDLE)
2582        {
2583                for(i = 0; i < steps; i++)
2584                {
2585                        p = steps - i;
2586                        r3 = (r2 * p + r1 * i) / steps;
2587                        g3 = (g2 * p + g1 * i) / steps;
2588                        b3 = (b2 * p + b1 * i) / steps;
2589                        col = (transparent << 24) | (r3 << 16) | (g3 << 8) | b3;
2590               
2591                        for(y = 0; y < ystep; y++)
2592                                for(x = 0; x < xstep; x++)
2593                                        drawpixel(posx + x, posy + y, col);
2594                        if(flag == LEFTMIDDLE)
2595                        {
2596                                posx += xstep;
2597                                xcount += xstep;
2598                        }
2599                        else
2600                        {
2601                                posy += ystep;
2602                                ycount += ystep;
2603                        }
2604                }
2605        }
2606
2607        if(flag == LEFTRIGHT || flag == LEFTMIDDLE)
2608        {
2609                if(owidth > xcount)
2610                {
2611                        for(y = 0; y < ystep; y++)
2612                                for(x = 0; x < (owidth - xcount); x++)
2613                                        drawpixel(posx + x, posy + y, col);
2614                }
2615        }
2616        if(flag == TOPBOTTOM || flag == TOPMIDDLE)
2617        {
2618                if(oheight > ycount)
2619                {
2620                        for(y = 0; y < (oheight - ycount); y++)
2621                                for(x = 0; x < xstep; x++)
2622                                        drawpixel(posx + x, posy + y, col);
2623                }
2624        }
2625}
2626
2627void drawtitlebggradient(struct skin* node)
2628{
2629        debug(1000, "in");
2630        if(status.picbordersize > 0)
2631                drawgradient(node->rposx + status.picbordersize, node->rposy + status.picbordersize, node->rwidth - (status.picbordersize * 2), node->rheight - (node->rheight - node->titlesize), node->titlebgcol, node->titlebgcol2, node->transparent, node->titlegradient);
2632        else
2633                drawgradient(node->rposx, node->rposy, node->rwidth, node->rheight - (node->rheight - node->titlesize), node->titlebgcol, node->titlebgcol2, node->transparent, node->titlegradient);
2634        debug(1000, "out");
2635}
2636
2637void drawbggradient(struct skin* node)
2638{
2639        debug(1000, "in");
2640        drawgradient(node->rposx, node->rposy, node->rwidth, node->rheight, node->bgcol, node->bgcol2, node->transparent, node->gradient);
2641        debug(1000, "out");
2642}
2643
2644void drawtitlebgcol(struct skin* node)
2645{
2646        debug(1000, "in");
2647        if(status.picbordersize > 0)
2648                fillrect(node->rposx + status.picbordersize, node->rposy + status.picbordersize, node->rwidth - (status.picbordersize * 2), node->rheight - (node->rheight - node->titlesize), node->titlebgcol, node->transparent);
2649        else
2650                fillrect(node->rposx, node->rposy, node->rwidth, node->rheight - (node->rheight - node->titlesize), node->titlebgcol, node->transparent);
2651        debug(1000, "out");
2652}
2653
2654void drawbginnercol(struct skin* node)
2655{
2656        debug(1000, "in");
2657        fillrect(node->rposx + node->bordersize, node->rposy + node->bordersize, node->rwidth - node->bordersize * 2, node->rheight - node->bordersize * 2, node->bgcol, node->transparent);
2658        debug(1000, "out");
2659}
2660
2661void drawbgcol(struct skin* node)
2662{
2663        debug(1000, "in");
2664        fillrect(node->rposx + node->bgspace, node->rposy + node->bgspace, node->rwidth - (node->bgspace * 2), node->rheight - (node->bgspace * 2), node->bgcol, node->transparent);
2665        debug(1000, "out");
2666}
2667
2668void drawtitle(struct skin* node)
2669{
2670        debug(1000, "in");
2671        if(status.titlelinesize > 0)
2672                drawstring(node->title, 1, 0, -1, node->iposx, node->rposy + node->bordersize, node->iwidth, node->titlesize - status.titlelinesize, node->titlealign, MIDDLE, node->font, node->fontsize, node->fontcol, node->transparent, 0, NULL, NULL, NULL, node->charspace);
2673        else
2674                drawstring(node->title, 1, 0, -1, node->iposx, node->rposy + node->bordersize, node->iwidth, node->titlesize - node->bordersize, node->titlealign, MIDDLE, node->font, node->fontsize, node->fontcol, node->transparent, 0, NULL, NULL, NULL, node->charspace);
2675        if(status.titlelinesize > 0)
2676                fillrect(node->rposx, node->rposy + node->titlesize + status.picbordersize, node->rwidth, status.titlelinesize, node->bordercol, node->transparent);
2677        else if(node->bordersize > 0)
2678                fillrect(node->rposx, node->rposy + node->titlesize, node->rwidth, node->bordersize, node->bordercol, node->transparent);
2679        debug(1000, "out");
2680}
2681
2682void drawprogressbar(struct skin* node)
2683{
2684        debug(1000, "in");
2685        int val = 0;
2686
2687        if(node->progresssize > 100) node->progresssize = 100;
2688        val = ((float)node->iwidth / 100) * node->progresssize;
2689        fillrect(node->rposx + node->bordersize, node->rposy + node->bordersize, val, node->iheight, node->progresscol, node->transparent);
2690        debug(1000, "out");
2691}
2692
2693void drawmultiprogressbar(struct skin* node)
2694{
2695        debug(1000, "in");
2696        struct epgrecord* epgrecord = node->epgrecord;
2697        int val1 = 0, val2 = 0;
2698
2699        while(epgrecord != NULL)
2700        {
2701               
2702                if(epgrecord->posx > 100) epgrecord->posx = 100;
2703                val1 = ((float)node->iwidth / 100) * epgrecord->posx;
2704                if(epgrecord->size > 100) epgrecord->size = 100;
2705                val2 = ((float)node->iwidth / 100) * epgrecord->size;
2706
2707                if(val2 > val1)
2708                        fillrect(node->rposx + node->bordersize + val1, node->rposy + node->bordersize, val2 - val1, node->iheight, node->progresscol, node->transparent);
2709                epgrecord = epgrecord->next;
2710        }
2711        debug(1000, "out");
2712}
2713
2714void drawroundborder(struct skin* node, char* bglt, char* bglb, char* bgrt, char* bgrb)
2715{
2716        int i, rad = status.borderradius;
2717
2718        if(node->borderradius > 0) rad = node->borderradius;
2719        if(rad > node->rheight / 2) rad = node->rheight / 2;
2720        int tmpbordersize = rad - node->bordersize;
2721
2722        //left - top
2723        for(i = rad; i > tmpbordersize; i--)
2724                drawcircle(node->rposx + rad, node->rposy + rad, i, 90, 180, node->bordercol, node->transparent, bglt, i == rad);
2725        //left - bottom
2726        for(i = rad; i > tmpbordersize; i--)
2727                drawcircle(node->rposx + rad, node->rposy + node->rheight - 1 - rad, i, 180, 270, node->bordercol, node->transparent, bglb, i == rad);
2728        //right - top
2729        for(i = rad; i > tmpbordersize; i--)
2730                drawcircle(node->rposx + node->rwidth - 1 - rad, node->rposy + rad, i, 0, 90, node->bordercol, node->transparent, bgrt, i == rad);
2731        //right - bottom
2732        for(i = rad; i > tmpbordersize; i--)
2733                drawcircle(node->rposx + node->rwidth - 1 - rad, node->rposy + node->rheight - 1 - rad, i, 270, 360, node->bordercol, node->transparent, bgrb, i == rad);
2734}
2735
2736//TODO: not full implemented
2737void drawpicborder(struct skin* node)
2738{
2739        debug(1000, "in");
2740        int borderwidth = status.picbordersize;
2741        int borderheight = status.picbordersize;
2742
2743        //top-left
2744        //drawpic("/home/nit/titan/skin/bs_tl.png", node->rposx + node->bordersize - borderwidth, node->rposy + node->bordersize - borderheight, 0, 0, borderwidth, borderheight, LEFT, TOP);
2745        drawpic("/home/nit/titan/skin/bs_tl.png", node->rposx, node->rposy, 0, 0, borderwidth, borderheight, LEFT, TOP);
2746        //top-right
2747        //drawpic("/home/nit/titan/skin/bs_tr.png", node->rposx - node->bordersize + node->rwidth, node->rposy + node->bordersize - borderheight, 0, 0, borderwidth, borderheight, LEFT, TOP);
2748        drawpic("/home/nit/titan/skin/bs_tr.png", node->rposx + node->rwidth - borderwidth, node->rposy, 0, 0, borderwidth, borderheight, LEFT, TOP);
2749        //bottom-left
2750        //drawpic("/home/nit/titan/skin/bs_bl.png", node->rposx + node->bordersize - borderwidth, node->rposy - node->bordersize + node->rheight, 0, 0, borderwidth, borderheight, LEFT, TOP);
2751        drawpic("/home/nit/titan/skin/bs_bl.png", node->rposx, node->rposy + node->rheight - borderheight, 0, 0, borderwidth, borderheight, LEFT, TOP);
2752        //bottom-right
2753        //drawpic("/home/nit/titan/skin/bs_br.png", node->rposx - node->bordersize + node->rwidth, node->rposy - node->bordersize + node->rheight, 0, 0, borderwidth, borderheight, LEFT, TOP);
2754        drawpic("/home/nit/titan/skin/bs_br.png", node->rposx + node->rwidth - borderwidth, node->rposy + node->rheight - borderheight, 0, 0, borderwidth, borderheight, LEFT, TOP);
2755
2756        //top
2757        //drawpic("/home/nit/titan/skin/bs_t.png", node->rposx + node->bordersize, node->rposy + node->bordersize - borderheight, node->rwidth - (node->bordersize * 2), 0, node->rwidth - (node->bordersize * 2), borderheight, LEFT, TOP);
2758        drawpic("/home/nit/titan/skin/bs_t.png", node->rposx + borderwidth, node->rposy, node->rwidth - (borderwidth * 2), 0, node->rwidth - (borderwidth * 2), borderheight, LEFT, TOP);
2759        //bottom
2760        //drawpic("/home/nit/titan/skin/bs_b.png", node->rposx + node->bordersize, node->rposy - node->bordersize + node->rheight, node->rwidth - (node->bordersize * 2), 0, node->rwidth - (node->bordersize * 2), borderheight, LEFT, TOP);
2761        drawpic("/home/nit/titan/skin/bs_b.png", node->rposx + borderwidth, node->rposy + node->rheight - borderheight, node->rwidth - (borderwidth * 2), 0, node->rwidth - (node->bordersize * 2), borderheight, LEFT, TOP);
2762        //left
2763        //drawpic("/home/nit/titan/skin/bs_l.png", node->rposx + node->bordersize - borderwidth, node->rposy + node->bordersize, 0, node->rheight - (node->bordersize * 2), borderwidth, node->rheight - (node->bordersize * 2), LEFT, TOP);
2764        drawpic("/home/nit/titan/skin/bs_l.png", node->rposx, node->rposy + borderheight, 0, node->rheight - (borderheight * 2), borderwidth, node->rheight - (borderheight * 2), LEFT, TOP);
2765        //right
2766        //drawpic("/home/nit/titan/skin/bs_r.png", node->rposx - node->bordersize + node->rwidth, node->rposy + node->bordersize, 0, node->rheight - (node->bordersize * 2), borderwidth, node->rheight - (node->bordersize * 2), LEFT, TOP);
2767        drawpic("/home/nit/titan/skin/bs_r.png", node->rposx + node->rwidth - borderwidth, node->rposy + borderheight, 0, node->rheight - (borderheight * 2), borderwidth, node->rheight - (borderheight * 2), LEFT, TOP);
2768        debug(1000, "out");
2769}
2770
2771void drawborder(struct skin* node)
2772{
2773        debug(1000, "in");
2774        if(node->bordersize == 1 && node->rheight > 2 && node->bordertype == 0)
2775                drawrect(node->rposx, node->rposy, node->rwidth, node->rheight, node->bordercol, node->transparent);
2776        else if(node->bordersize == 1 && node->rheight <= 2 && node->bordertype == 0)
2777                fillrect(node->rposx, node->rposy, node->rwidth, node->rheight, node->bordercol, node->transparent);
2778        else
2779        {
2780                if(node->bordertype == 0 || checkbit(node->bordertype, 0) == 1)
2781                        fillrect(node->rposx, node->rposy, node->rwidth, node->bordersize, node->bordercol, node->transparent);
2782                if(node->bordertype == 0 || checkbit(node->bordertype, 1) == 1)
2783                        fillrect(node->rposx, node->rposy + node->rheight - node->bordersize, node->rwidth, node->bordersize, node->bordercol, node->transparent);
2784                if(node->bordertype == 0 || checkbit(node->bordertype, 2) == 1)
2785                        fillrect(node->rposx, node->rposy, node->bordersize, node->rheight, node->bordercol, node->transparent);
2786                if(node->bordertype == 0 || checkbit(node->bordertype, 3) == 1)
2787                        fillrect(node->rposx + node->rwidth - node->bordersize, node->rposy, node->bordersize, node->rheight, node->bordercol, node->transparent);
2788        }
2789        debug(1000, "out");
2790}
2791
2792void drawscrollbar(struct skin* node)
2793{
2794        debug(1000, "in");
2795        if(node->bordersize == 0)
2796                drawrect(node->rposx + node->rwidth - node->bordersize - node->scrollbarwidth, node->iposy, node->scrollbarwidth, node->iheight, node->bordercol, node->transparent);
2797        else
2798                fillrect(node->rposx + node->rwidth - node->bordersize - node->scrollbarwidth, node->iposy, node->scrollbarbordersize, node->iheight, node->bordercol, node->transparent);
2799
2800        fillrect(node->rposx + node->rwidth - node->bordersize - node->scrollbarwidth, node->iposy + node->scrollbarpos, node->scrollbarwidth, node->scrollbarheight, node->bordercol, node->transparent);
2801        debug(1000, "out");
2802}
2803
2804void clearshadow(struct skin* node)
2805{
2806        debug(1000, "in");
2807
2808        if(node->shadowsize < 1) return;
2809        switch(node->shadowpos)
2810        {
2811                case BOTTOMLEFT:
2812                clearrect(node->rposx - node->shadowsize, node->rposy + node->rheight, node->rwidth, node->shadowsize);
2813                clearrect(node->rposx - node->shadowsize, node->rposy + node->shadowsize, node->shadowsize, node->rheight);
2814                break;
2815                case BOTTOMRIGHT:
2816                clearrect(node->rposx + node->shadowsize, node->rposy + node->rheight, node->rwidth, node->shadowsize);
2817                clearrect(node->rposx + node->rwidth, node->rposy + node->shadowsize, node->shadowsize, node->rheight);
2818                break;
2819                case TOPLEFT:
2820                clearrect(node->rposx - node->shadowsize, node->rposy - node->shadowsize, node->rwidth, node->shadowsize);
2821                clearrect(node->rposx - node->shadowsize, node->rposy - node->shadowsize, node->shadowsize, node->rheight);
2822                break;
2823                default:
2824                clearrect(node->rposx + node->shadowsize, node->rposy - node->shadowsize, node->rwidth, node->shadowsize);
2825                clearrect(node->rposx + node->rwidth, node->rposy - node->shadowsize, node->shadowsize, node->rheight);
2826                break;
2827        }
2828        debug(1000, "out");
2829}
2830
2831void drawshadow(struct skin* node)
2832{
2833        debug(1000, "in");
2834        switch(node->shadowpos)
2835        {
2836                case BOTTOMLEFT:
2837                fillrect(node->rposx - node->shadowsize, node->rposy + node->rheight, node->rwidth, node->shadowsize, node->shadowcol, node->transparent);
2838                fillrect(node->rposx - node->shadowsize, node->rposy + node->shadowsize, node->shadowsize, node->rheight, node->shadowcol, node->transparent);
2839                break;
2840                case BOTTOMRIGHT:
2841                fillrect(node->rposx + node->shadowsize, node->rposy + node->rheight, node->rwidth, node->shadowsize, node->shadowcol, node->transparent);
2842                fillrect(node->rposx + node->rwidth, node->rposy + node->shadowsize, node->shadowsize, node->rheight, node->shadowcol, node->transparent);
2843                break;
2844                case TOPLEFT:
2845                fillrect(node->rposx - node->shadowsize, node->rposy - node->shadowsize, node->rwidth, node->shadowsize, node->shadowcol, node->transparent);
2846                fillrect(node->rposx - node->shadowsize, node->rposy - node->shadowsize, node->shadowsize, node->rheight, node->shadowcol, node->transparent);
2847                break;
2848                default:
2849                fillrect(node->rposx + node->shadowsize, node->rposy - node->shadowsize, node->rwidth, node->shadowsize, node->shadowcol, node->transparent);
2850                fillrect(node->rposx + node->rwidth, node->rposy - node->shadowsize, node->shadowsize, node->rheight, node->shadowcol, node->transparent);
2851                break;
2852        }
2853        debug(1000, "out");
2854}
2855
2856//flag 0: del background
2857//flag 1: don't del background
2858void drawnode(struct skin* node, int flag)
2859{
2860        long color = 0, color2 = 0;
2861        int len = 0;
2862        char* bglt = NULL, *bglb = NULL, *bgrt = NULL, *bgrb = NULL;
2863
2864        debug(1000, "in");
2865       
2866        node->flag = setbit(node->flag, 0);
2867
2868        if(node->bordersize > 0)
2869        {
2870                if((node->child != NULL && status.borderradius > 0) || node->borderradius > 0)
2871                {
2872                        int rad = status.borderradius;
2873
2874                        if(node->borderradius > 0) rad = node->borderradius;
2875                        if(rad > node->rheight / 2) rad = node->rheight / 2;
2876
2877                        bglt = saverect(node->rposx, node->rposy, rad, rad);
2878                        bglb = saverect(node->rposx, node->rposy + node->rheight - rad, rad, rad);
2879                        bgrt = saverect(node->rposx + node->rwidth - rad, node->rposy, rad, rad);
2880                        bgrb = saverect(node->rposx + node->rwidth - rad, node->rposy + node->rheight - rad, rad, rad);
2881                }
2882        }
2883
2884        if(flag == 0 && node->bgcol == -1)
2885        {
2886                if(node->child != NULL && status.picbordersize > 0)
2887                {
2888                        clearrect(node->rposx + node->bordersize, node->rposy + node->bordersize, node->rwidth - node->bordersize * 2, node->rheight - node->bordersize * 2);
2889                }
2890                else
2891                        clearscreennolock(node);
2892        }
2893
2894        if(node->deaktivcol > -1)
2895        {
2896                color = node->deaktivcol;
2897                color2 = node->deaktivcol;
2898        }
2899        else
2900        {
2901                color = node->fontcol;
2902                color2 = node->fontcol2;
2903        }
2904
2905        if(node->shadowsize > 0)
2906                drawshadow(node);
2907        if(node->bgcol > -1)
2908        {
2909                if(node->child != NULL && status.picbordersize > 0)
2910                        drawbginnercol(node);
2911                else
2912                        drawbgcol(node);
2913        }
2914        if(node->child != NULL && status.bgpic != NULL)
2915                drawpic(status.bgpic, node->iposx, node->iposy, node->iwidth, node->iheight, node->iwidth, node->iheight, node->halign, node->valign);
2916        if(node->gradient > 0)
2917                drawbggradient(node);
2918        if(node->titlebgcol > -1)
2919                drawtitlebgcol(node);
2920        if(node->titlegradient > 0)
2921                drawtitlebggradient(node);
2922        if(node->progresssize > 0)
2923                drawprogressbar(node);
2924        if(node->type & MULTIPROGRESSBAR)
2925                drawmultiprogressbar(node);
2926        if(node->selectpic != NULL && !(node->type & FILELIST))
2927                drawpic(node->selectpic, node->iposx, node->iposy, node->rpicwidth, node->rpicheight, node->iwidth, node->iheight, CENTER, MIDDLE);
2928        if(node->pic != NULL && !(node->type & FILELIST))
2929                drawpic(node->pic, node->iposx, node->iposy, node->rpicwidth, node->rpicheight, node->iwidth, node->iheight, node->halign, node->valign);
2930        if(node->input != NULL)
2931        {
2932                if(node->type & CHOICEBOX)
2933                        drawstring(node->input, 1, node->poscount, -1, node->iposx, node->iposy, node->iwidth, node->iheight, RIGHT, node->valign, node->font, node->fontsize, color, node->transparent, 0, NULL, NULL, &len, node->charspace);
2934                if((node->type & INPUTBOX) || (node->type & INPUTBOXNUM))
2935                        drawstring(node->input, 1, node->poscount, node->aktpage, node->iposx, node->iposy, node->iwidth, node->iheight, RIGHT, node->valign, node->font, node->fontsize, color, node->transparent, 0, NULL, NULL, &len, node->charspace);
2936        }
2937        if(node->text != NULL)
2938        {
2939                if(node->type & TEXTBOX)
2940                {
2941                        int lastposy = 0;
2942                        drawstring(node->text, node->linecount, node->poscount, -1, node->iposx + node->textposx, node->iposy, node->iwidth - node->textposx, node->iheight, node->halign, node->valign, node->font, node->fontsize, color, node->transparent, node->wrap, NULL, &lastposy, NULL, node->charspace);
2943                        drawstring(node->text2, node->linecount, node->poscount, -1, node->iposx + node->textposx2, lastposy, node->iwidth - node->textposx2, node->iheight - (lastposy - node->iposy), node->halign, node->valign, node->font, node->fontsize2, color2, node->transparent, node->wrap, NULL, &lastposy, NULL, node->charspace);
2944                }
2945                else
2946                {
2947                        int lastposx = 0;
2948                        if(node->textposx2 > 0)
2949                                drawstring(node->text, 1, 0, -1, node->iposx + node->textposx, node->iposy, node->iwidth - node->textposx - (node->iwidth - node->textposx2) - len, node->iheight, node->halign, node->valign, node->font, node->fontsize, color, node->transparent, 0, &lastposx, NULL, NULL, node->charspace);
2950                        else
2951                                drawstring(node->text, 1, 0, -1, node->iposx + node->textposx, node->iposy, node->iwidth - node->textposx - len, node->iheight, node->halign, node->valign, node->font, node->fontsize, color, node->transparent, 0, &lastposx, NULL, NULL, node->charspace);
2952                        if(node->textposx2 > 0)
2953                                drawstring(node->text2, 1, 0, -1, node->iposx + node->textposx2, node->iposy, node->iwidth - node->textposx2 - len, node->iheight, node->halign, node->valign, node->font, node->fontsize2, color2, node->transparent, 0, NULL, NULL, NULL, node->charspace);
2954                        else
2955                                drawstring(node->text2, 1, 0, -1, lastposx, node->iposy, node->iwidth - (lastposx - node->iposx) - len, node->iheight, node->halign, node->valign, node->font, node->fontsize2, color2, node->transparent, 0, NULL, NULL, NULL, node->charspace);
2956                }
2957        }
2958        if(status.filelistextend > 2 && node->filelist != NULL)
2959        {
2960                char* tmpnr = NULL;
2961
2962                if(status.filelistextend == 3)
2963                {
2964                        if(node->filelist->size >= 1073741824)
2965                        {
2966                                tmpnr = oftoa64((double)node->filelist->size / 1073741824, "2");
2967                                tmpnr = ostrcat(tmpnr, "G", 1, 0);
2968                        }
2969                        else if(node->filelist->size >= 1048576)
2970                        {
2971                                tmpnr = oftoa64((double)node->filelist->size / 1048576, "2");
2972                                tmpnr = ostrcat(tmpnr, "M", 1, 0);
2973                        }
2974                        else if(node->filelist->size >= 1024)
2975                        {
2976                                tmpnr = oftoa64((double)node->filelist->size / 1024, "2");
2977                                tmpnr = ostrcat(tmpnr, "K", 1, 0);
2978                        }
2979                        else
2980                        {
2981                                tmpnr = oitoa64(node->filelist->size);
2982                                tmpnr = ostrcat(tmpnr, "B", 1, 0);
2983                        }
2984                }
2985                if(status.filelistextend == 4)
2986                {
2987                        tmpnr = malloc(MINMALLOC);
2988                        if(tmpnr == NULL)
2989                        {
2990                                err("no mem");
2991                                return;
2992                        }
2993
2994                        struct tm* loctime = olocaltime(&node->filelist->date);
2995                        if(loctime != NULL)
2996                                strftime(tmpnr, MINMALLOC, "%H:%M %d-%m-%Y", loctime);
2997                        free(loctime);
2998                }
2999                drawstring(tmpnr, 1, node->poscount, -1, node->iposx, node->iposy, node->iwidth, node->iheight, RIGHT, node->valign, node->font, node->fontsize, node->fontcol, node->transparent, 0, NULL, NULL, NULL, node->charspace);
3000                free(tmpnr);
3001        }
3002        if(node->title != NULL)
3003                drawtitle(node);
3004        if(node->scrollbar == YES || node->scrollbar == AUTOYES)
3005                drawscrollbar(node);
3006        if(node->bordersize > 0)
3007        {
3008                if(node->child != NULL && status.picbordersize > 0)
3009                        drawpicborder(node);
3010                else
3011                        drawborder(node);
3012                if((node->child != NULL && status.borderradius > 0) || node->borderradius > 0)
3013                        drawroundborder(node, bglt, bglb, bgrt, bgrb);
3014        }
3015
3016        free(bglt); free(bglb); free(bgrt); free(bgrb);
3017        debug(1000, "out");
3018}
3019
3020void calcscrollbar(struct skin* node)
3021{
3022        debug(1000, "in");
3023
3024        node->scrollbarheight = node->iheight;
3025
3026        if(node->pagecount > 1)
3027        {
3028                node->scrollbarheight = (float)node->iheight / node->pagecount;
3029                node->scrollbarpos = ((float)node->iheight / node->pagecount) * (node->aktpage - 1);
3030                if(node->scrollbar == AUTONO) node->scrollbar = AUTOYES;
3031        }
3032        else if(node->scrollbar == AUTOYES)
3033                node->scrollbar = AUTONO;
3034
3035        if(node->scrollbar == YES || node->scrollbar == AUTOYES)
3036        {
3037                node->iwidth -= (SCROLLBARWIDTH + 5);
3038                node->scrollbarwidth = SCROLLBARWIDTH;
3039                node->scrollbarbordersize = SCROLLBARBORDERSIZE;
3040                if(node->iposy + node->scrollbarpos > node->iposy + node->iheight) node->scrollbarpos = node->iposy + node->iheight;
3041                if(node->scrollbarpos < 0) node->scrollbarpos = 0;
3042                if(node->iposy + node->scrollbarpos + node->scrollbarheight > node->iposy + node->iheight) node->scrollbarheight = node->iheight - node->scrollbarpos;
3043                if(node->scrollbarheight < 1) node->scrollbarheight = 1;
3044        }
3045        debug(1000, "out");
3046}
3047
3048void calclistboxchild(struct skin* node, struct skin* parent)
3049{
3050        if((parent->type & GRID) && (node->type & GRIDBR))
3051        {
3052                if(parent->poscount > 0) parent->poscount += node->rheight;
3053                if(parent->poscount == 0) parent->poscount = 1;
3054        }
3055        node->rposy = node->rposy + parent->poscount;
3056        node->iposy = node->iposy + parent->poscount;
3057        if((parent->type & LISTBOX) || ((parent->type & FILELIST) && !(parent->type & GRID)))
3058                parent->poscount += node->rheight;
3059}
3060
3061int calclistbox(struct skin* node)
3062{
3063        debug(1000, "in");
3064        struct skin* child = NULL, *last = NULL, *found = NULL;
3065        int selcol = convertcol("listboxselect");
3066        int markcol = convertcol("markcol");
3067        char* selectpic = getskinconfig("selectpic", NULL);
3068
3069        node->poscount = 0;
3070        if(node->aktline == 0) node->aktline = 1;
3071        node->pagecount = 1;
3072        node->linecount = 0;
3073
3074        child = node->next;
3075        while(child != NULL)
3076        {
3077                if(child->parentpointer == NULL)
3078                {
3079                        if(child->parent == NULL)
3080                        {
3081                                child = child->next;
3082                                continue;
3083                        }
3084                        else if(ostrcmp(child->parent, node->name) != 0 || child->hidden == YES || child->locked == YES)
3085                        {
3086                                child = child->next;
3087                                continue;
3088                        }
3089                }
3090                else if(child->parentpointer != node || child->hidden == YES || child->locked == YES)
3091                {
3092                        child = child->next;
3093                        continue;
3094                }
3095
3096                calcrheight(child, node);
3097
3098                if((node->type & LISTBOX) || ((node->type & FILELIST) && !(node->type & GRID)) || ((node->type & GRID) && (child->type & GRIDBR)))
3099                        node->poscount = node->poscount + child->posy + child->rheight;
3100
3101                if(node->poscount > node->iheight)
3102                {
3103                        node->pagecount++;
3104                        node->poscount = child->rheight;
3105                }
3106
3107                child->pagecount = node->pagecount;
3108
3109                if(child->deaktivcol > -1)
3110                {
3111                        child = child->next;
3112                        continue;
3113                }
3114
3115                node->linecount++;
3116                last = child;
3117
3118                if(node->aktline == -1 && child->pagecount == node->aktpage)
3119                        node->aktline = node->linecount;
3120
3121                if(node->aktline == node->linecount)
3122                        found = child;
3123
3124                child->bordersize = 0;
3125                if(status.listboxselecttype == 3)
3126                {
3127                        changeselectpic(child, NULL);
3128                        if(child->bgcol == markcol)
3129                                child->bgcol = child->bordercol;
3130                }
3131                if(child->bgcol == selcol) //&& status.listboxselecttype == 1)
3132                        child->bgcol = child->bordercol;
3133                if(child->fontcol == selcol) //&& status.listboxselecttype == 2)
3134                        child->fontcol = child->bordercol;
3135
3136                child = child->next;
3137        }
3138
3139        if(found == NULL)
3140        {
3141                found = last;
3142                node->aktline = node->linecount;
3143        }
3144       
3145        if(found != NULL)
3146        {
3147                if(node->aktline == -2) node->aktline = node->linecount;
3148                if(status.listboxselecttype == 0)
3149                {
3150                        found->bordersize = 1;
3151                        if(status.markmodus > 0)
3152                                found->bordercol = markcol;
3153                        else
3154                                found->bordercol = selcol;
3155                }
3156                else if(status.listboxselecttype == 1)
3157                {
3158                        if(found->bgcol != selcol && found->bgcol != markcol)
3159                                found->bordercol = found->bgcol;
3160                        if(status.markmodus > 0)
3161                                found->bgcol = markcol;
3162                        else
3163                                found->bgcol = selcol;
3164                }
3165                else if(status.listboxselecttype == 2)
3166                {
3167                        if(found->fontcol != selcol && found->fontcol != markcol)
3168                                found->bordercol = found->fontcol;
3169                        if(status.markmodus > 0)
3170                                found->fontcol = markcol;
3171                        else
3172                                found->fontcol = selcol;
3173                }
3174                else if(status.listboxselecttype == 3)
3175                {
3176                        changeselectpic(found, selectpic);
3177                        if(found->bgcol != markcol)
3178                                found->bordercol = found->bgcol;
3179                        if(status.markmodus > 0)
3180                                found->bgcol = markcol;
3181                }
3182
3183                if(node->aktpage == -1)
3184                        node->aktpage = found->pagecount;
3185                node->select = found;
3186        }
3187
3188        if(node->aktpage == -1) node->aktpage = 0;
3189        if(node->aktpage > node->pagecount)
3190        {
3191                if(node->pagecount == 0) node->aktpage = 0;
3192                else node->aktpage = 1;
3193        }
3194        node->poscount = 0;
3195        debug(1000, "out");
3196        return 0;
3197}
3198
3199int calcrwidth(struct skin* node, struct skin* parent)
3200{
3201        int scrollbarwidth = 0;
3202
3203        if(node->prozwidth == 1)
3204                node->rwidth = ((float)parent->iwidth / 100) * node->width;
3205        else
3206                node->rwidth = node->width;
3207
3208        if(node->scrollbar == YES || node->scrollbar == AUTOYES || node->scrollbar == AUTONO) scrollbarwidth = SCROLLBARWIDTH;
3209
3210        if(node->rwidth < (node->bordersize * 2) + scrollbarwidth) node->rwidth = (node->bordersize * 2) + scrollbarwidth;
3211
3212        return 0;
3213}
3214
3215int calcrheight(struct skin* node, struct skin* parent)
3216{
3217        if(node->prozheight == 1)
3218                node->rheight = ((float)parent->iheight / 100) * node->height;
3219        else
3220        {
3221                node->rheight = node->height;
3222                if(node->fontsize == 0) node->fontsize = parent->fontsize;
3223                if(node->fontsize == 0) node->fontsize = 1;
3224                if(node->rheight == 0) node->rheight = node->fontsize + 2;
3225        }
3226
3227        if(node->rheight < (node->bordersize * 2) + node->titlesize) node->rheight = (node->bordersize * 2) + node->titlesize;
3228
3229        return 0;
3230}
3231
3232int calcrposx(struct skin* node, struct skin* parent)
3233{
3234        if(node->prozposx == 1)
3235                node->rposx = ((float)parent->iwidth / 100) * node->posx;
3236        else
3237                node->rposx = node->posx;
3238
3239        if(node->posx == CENTER || (node->posx == 0 && parent->halign == CENTER))
3240                node->rposx = parent->iposx + parent->iwidth / 2 - node->rwidth / 2;
3241        else if(node->posx == LEFT)
3242                node->rposx = parent->iposx;
3243        else if(node->posx == RIGHT || (node->posx == 0 && parent->halign == RIGHT))
3244                node->rposx = parent->iposx + parent->iwidth - node->rwidth;
3245        else
3246                node->rposx = parent->iposx + node->rposx;
3247
3248        if(node->rposx > parent->iposx + parent->iwidth)
3249                node->rposx = parent->iposx + parent->iwidth;
3250
3251        return 0;
3252}
3253
3254int calcrposy(struct skin* node, struct skin* parent)
3255{
3256        if(node->prozposy == 1)
3257                node->rposy = ((float)parent->iheight / 100) * node->posy;
3258        else
3259                node->rposy = node->posy;
3260
3261        if(node->posy == MIDDLE || (node->posy == 0 && parent->valign == MIDDLE))
3262                node->rposy = parent->iposy + parent->iheight / 2 - node->rheight / 2;
3263        else if(node->posy == TOP)
3264                node->rposy = parent->iposy;
3265        else if(node->posy == BOTTOM || (node->posy ==0 && parent->valign == BOTTOM))
3266                node->rposy = parent->iposy + parent->iheight - node->rheight;
3267        else
3268                node->rposy = parent->iposy + node->rposy;
3269
3270        if(node->rposy > parent->iposy + parent->iheight)
3271                node->rposy = parent->iposy + parent->iheight;
3272
3273        return 0;
3274}
3275
3276int setnodeattr(struct skin* node, struct skin* parent)
3277{
3278        if(node != skin) node->flag = clearbit(node->flag, 0);
3279        if((parent->type & LISTBOX) || (parent->type & FILELIST) || (parent->type & GRID))
3280                if(node->pagecount != parent->aktpage) return 1;
3281
3282        debug(1000, "in");
3283        int shadowlx = 0, shadowrx = 0, shadowoy = 0, shadowuy = 0;
3284        unsigned int linecount = 0, pagecount = 0, poscount = 0;
3285        char* tmpstr = NULL;
3286
3287        if(node->child != NULL && status.picbordersize > 0)
3288                node->bordersize = status.picbordersize;
3289
3290        if(node->skinfunc != NULL)
3291        {
3292                if(node->funcrettype == FUNCPIC)
3293                {
3294                        tmpstr = node->skinfunc(node, node->param1, node->param2);
3295                        changepic(node, tmpstr);
3296                }
3297                else if(node->funcrettype == FUNCPROGRESS)
3298                {
3299                        tmpstr = node->skinfunc(node, node->param1, node->param2);
3300                        if(tmpstr != NULL)
3301                        {
3302                                node->hidden = NO;
3303                                node->progresssize = atoi(tmpstr);
3304                        }
3305                        else
3306                                node->hidden = YES;
3307                }
3308                else
3309                {
3310                        tmpstr = node->skinfunc(node, node->param1, node->param2);
3311                        changetext(node, _(tmpstr));
3312                }
3313                free(tmpstr);
3314        }
3315
3316        if(status.screencalc != 2)
3317        {
3318                if(node->hidden == YES || parent->hidden == YES || node->locked == YES || parent->locked == YES) return 1;
3319                if(checkbit(parent->flag, 0) == 0) return 1;
3320        }
3321
3322        calcrwidth(node, parent);
3323        if(!(parent->type & LISTBOX) && !(parent->type & FILELIST) && !(parent->type & GRID))
3324                calcrheight(node, parent);
3325        calcrposx(node, parent);
3326        calcrposy(node, parent);
3327
3328        if(node->height < 0)
3329                node->rheight = parent->iheight + node->height - (node->rposy - parent->iposy);
3330        if(node->width < 0)
3331                node->rwidth = parent->iwidth + node->width - (node->rposx - parent->iposx);
3332
3333        node->iposx = node->rposx + node->bordersize + node->hspace;
3334        node->iposy = node->rposy + node->bordersize + node->titlesize + node->vspace;
3335        node->iwidth = node->rwidth - node->bordersize * 2 - node->hspace * 2;
3336        node->iheight = node->rheight - node->bordersize * 2 - node->titlesize - node->vspace * 2;
3337
3338        switch(node->shadowpos)
3339        {
3340                case BOTTOMLEFT: shadowlx = shadowuy = node->shadowsize; break;
3341                case BOTTOMRIGHT: shadowrx = shadowuy = node->shadowsize; break;
3342                case TOPLEFT: shadowlx = shadowoy = node->shadowsize; break;
3343                default: shadowrx = shadowoy = node->shadowsize; break;
3344        }
3345
3346        if((parent->type & LISTBOX) || (parent->type & FILELIST) || (parent->type & GRID))
3347                calclistboxchild(node, parent);
3348
3349        if(node->picprozwidth == 1)
3350                node->rpicwidth = ((float)node->iwidth / 100) * node->picwidth;
3351        else
3352                node->rpicwidth = node->picwidth;
3353        if(node->picprozheight == 1)
3354                node->rpicheight = ((float)node->iheight / 100) * node->picheight;
3355        else
3356                node->rpicheight = node->picheight;
3357
3358
3359        if(node->rposx - shadowlx < parent->iposx)
3360        {
3361                if(status.screencalc == 0) err("node (%s posx=%d) out of parent (%s posx=%d)", node->name, node->rposx - shadowlx, parent->name, parent->iposx);
3362                node->rposx = parent->iposx + shadowlx;
3363                //return 1;
3364        }
3365        if(node->rposy - shadowoy < parent->iposy)
3366        {
3367                if(status.screencalc == 0) err("node (%s posy=%d) out of parent (%s posy=%d)", node->name, node->rposy - shadowoy, parent->name, parent->iposy);
3368                node->rposy = parent->iposy + shadowoy;
3369                //return 1;
3370        }
3371        if(node->rposx + node->rwidth + shadowrx > parent->iposx + parent->iwidth)
3372        {
3373                if(status.screencalc == 0) err("node (%s posxx=%d) out of parent (%s posxx=%d)", node->name, node->rposx + node->rwidth + shadowrx, parent->name, parent->iposx + parent->iwidth);
3374                node->rwidth = parent->iwidth - node->rposx - shadowrx;
3375                //return 1;
3376        }
3377        if(node->rposy + node->rheight + shadowuy > parent->iposy + parent->iheight)
3378        {
3379                if(status.screencalc == 0) err("node (%s posyy=%d) out of parent (%s posyy=%d)", node->name, node->rposy + node->rheight + shadowuy, parent->name, parent->iposy + parent->iheight);
3380                node->rheight = parent->iheight - node->rposy - shadowuy;
3381                //return 1;
3382        }
3383
3384        if(node->font == NULL && parent->font != NULL)
3385        {
3386                changefont(node, parent->font);
3387                if(node->font == NULL)
3388                {
3389                        err("no memory");
3390                }
3391        }
3392
3393        if(node->fontsize == 0) node->fontsize = parent->fontsize;
3394        if(node->fontsize == 0) node->fontsize = 1;
3395        if(node->fontsize2 == 0) node->fontsize2 = parent->fontsize2;
3396        if(node->fontsize2 == 0) node->fontsize2 = 1;
3397        if(node->fontcol == 0) node->fontcol = parent->fontcol;
3398        if(node->fontcol2 == 0) node->fontcol2 = parent->fontcol2;
3399
3400        if((node->type & INPUTBOX) || (node->type & INPUTBOXNUM))
3401        {
3402                if(node->aktpage < 1) node->aktpage = 1;
3403                checkinputboxnumright(node);
3404                changeret(node, node->input);
3405        }
3406
3407        if((node->type & LISTBOX) || (node->type & FILELIST) || (node->type & GRID))
3408        {
3409                if(node->aktpage == 0) node->aktpage = 1;
3410                calclistbox(node);
3411                if(node->scrollbar != NO)
3412                        calcscrollbar(node);
3413        }
3414        if(node->type & TEXTBOX)
3415        {
3416                if(node->aktpage < 1) node->aktpage = 1;
3417                if(node->text == NULL && node->text2 == NULL)
3418                        node->pagecount = 0;
3419                else
3420                {
3421                        if(node->wrap == YES)
3422                                wrapstr(node->text, node->font, node->fontsize, node->iwidth, node->charspace);
3423                        calctext(node->text, node->text2, &node->linecount, &node->pagecount, &node->poscount, node->iheight / node->fontsize, node->aktpage);
3424                }
3425                if(node->text2 != NULL) node->scrollbar = NO;
3426                if(node->scrollbar != NO)
3427                        calcscrollbar(node);
3428        }
3429
3430        if((node->type & CHOICEBOX) && node->input != NULL)
3431        {
3432                char* pos = NULL;
3433                calctext(node->input, NULL, &node->linecount, &node->pagecount, &node->poscount, 1, node->aktpage);
3434
3435                free(node->ret);
3436                node->ret = NULL;
3437
3438                if(node->choiceboxvalue != NULL)
3439                {
3440                        calctext(node->choiceboxvalue, NULL, &linecount, &pagecount, &poscount, 1, node->aktpage);
3441                        pos = strchr(node->choiceboxvalue + poscount, '\n');
3442                        if(pos == NULL)
3443                                changeret(node, node->choiceboxvalue + poscount);
3444                        else
3445                                node->ret = strndup(node->choiceboxvalue + poscount, pos - (node->choiceboxvalue + poscount));
3446                }
3447                else if(node->input != NULL)
3448                {
3449                        pos = strchr(node->input + node->poscount, '\n');
3450                        if(pos == NULL)
3451                                changeret(node, node->input + node->poscount);
3452                        else
3453                                node->ret = strndup(node->input + node->poscount, pos - (node->input + node->poscount));
3454                }
3455        }
3456
3457        //set parent transparent to child
3458        //if(node->transparent == 0 && parent != skin)
3459                //node->transparent = parent->transparent;
3460
3461        debug(1000, "out");
3462        return 0;
3463}
3464
3465int clearscreenalways()
3466{
3467        debug(1000, "in");
3468        int i, ret = 0;
3469
3470        for(i = 0; i < sizeof(status.drawallways) / sizeof(skin); i++)
3471        {
3472                if(status.drawallways[i] != NULL)
3473                {
3474                        clearrect(status.drawallways[i]->rposx, status.drawallways[i]->rposy, status.drawallways[i]->rwidth, status.drawallways[i]->rheight);
3475                }
3476        }
3477
3478        debug(1000, "out");
3479        return ret;
3480}
3481
3482int drawscreenalways(struct skin* node)
3483{
3484        debug(1000, "in");
3485        int i, ret = 0;
3486
3487        for(i = 0; i < sizeof(status.drawallways) / sizeof(skin); i++)
3488        {
3489                if(status.drawallways[i] != NULL)
3490                {
3491                        if(node != status.drawallways[i])
3492                        {
3493                                if(status.drawallwaysbg[i] != NULL)
3494                                        free(status.drawallwaysbg[i]);
3495                                status.drawallwaysbg[i] = savescreen(status.drawallways[i]);
3496                                ret = drawscreen(status.drawallways[i], 1);
3497                        }
3498                }
3499        }
3500
3501        debug(1000, "out");
3502        return ret;
3503}
3504
3505int drawscreennode(struct skin *node, char* nodename)
3506{
3507        debug(1000, "in");
3508
3509        node = getscreennode(node, nodename);
3510        m_lock(&status.drawingmutex, 0);
3511        if(node != status.skinerr)
3512                drawnode(node, 1);
3513
3514        drawscreenalways(node);
3515        blitfb(0);
3516        m_unlock(&status.drawingmutex, 0);
3517
3518        debug(1000, "out");
3519        return 0;
3520}
3521
3522int drawscreennodebyname(char* screenname, char* nodename)
3523{
3524        debug(1000, "in");
3525        struct skin *node;
3526
3527        node = getscreennodebyname(screenname, nodename);
3528        m_lock(&status.drawingmutex, 0);
3529        if(node != status.skinerr)
3530                drawnode(node, 1);
3531
3532        drawscreenalways(node);
3533        blitfb(0);
3534        m_unlock(&status.drawingmutex, 0);
3535
3536        debug(1000, "out");
3537        return 0;
3538}
3539
3540//flag 0: draw normal with allways
3541//flag 1: draw without allways
3542//flag 2: from thread (mutex is set in thread)
3543//flag 3: same as 0 but don't use status.screencalc
3544//flag 4: same as 0 but animate
3545int drawscreen(struct skin* node, int flag)
3546{
3547        struct fb* merkskinfb = NULL;
3548
3549        debug(1000, "in");
3550        int ret;
3551        struct skin *child = NULL, *parent = NULL, *oldparent = NULL;
3552
3553        if(node == NULL)
3554        {
3555                err("node = NULL");
3556                return 1;
3557        }
3558
3559        if(flag == 0 || flag == 3 || flag == 4)
3560                m_lock(&status.drawingmutex, 0);
3561
3562        parent = skin;
3563
3564        ret = setnodeattr(node, parent);
3565        if(ret == 1)
3566        {
3567                if(flag == 0 || flag == 3 || flag == 4)
3568                        m_unlock(&status.drawingmutex, 0);
3569                debug(1000, "out -> setnodeattr ret = 1");
3570                return 1;
3571        }
3572       
3573        if(strstr(node->name, "LCD_") != NULL) {
3574                merkskinfb = skinfb;
3575                memset(lcdskinfb->fb, 0, lcdskinfb->varfbsize);
3576                skinfb = lcdskinfb;
3577        }
3578
3579        if(status.screencalc == 0 || flag == 3 || flag == 4)
3580        {
3581                if(flag == 0 || flag == 2 || flag == 3 || flag == 4) clearscreenalways();
3582                drawnode(node, 0);
3583        }
3584        parent = node;
3585        oldparent = node;
3586        child = node->child;
3587
3588        while(child != NULL)
3589        {
3590                if(child->parentpointer != NULL)
3591                        parent = child->parentpointer;
3592                else if(child->parent != NULL)
3593                {
3594                        parent = getscreennode(node, child->parent);
3595                        if(parent == status.skinerr) parent = oldparent;
3596                }
3597                else
3598                        parent = oldparent;
3599
3600                if(setnodeattr(child, parent) == 0 && (status.screencalc == 0 || flag == 3))
3601                        drawnode(child, 1);
3602                child = child->next;
3603        }
3604
3605        if(flag == 0 || flag == 2 || flag == 3 || flag == 4)
3606        {
3607                if(status.screencalc == 0 || flag == 3)
3608                {
3609                        drawscreenalways(node);
3610
3611                        if(merkskinfb != NULL)
3612                                pngforlcd();
3613                        else   
3614                        {
3615                                if(flag == 4)
3616                                        blitfb(1);
3617                                else
3618                                        blitfb(0);
3619                        }
3620                }
3621        }
3622
3623        if(merkskinfb != NULL)
3624        {
3625                skinfb = merkskinfb;
3626                merkskinfb = NULL;
3627        }
3628        else
3629        {
3630                if(ostrcmp(getconfig("write_fb_to_jpeg", NULL), "yes") == 0)
3631                        write_FB_to_JPEG_file(skinfb->fb, skinfb->width, skinfb->height, "/tmp/fb.jpg", 3);
3632        }
3633        if(flag == 0 || flag == 3 || flag == 4)
3634                m_unlock(&status.drawingmutex, 0);
3635        debug(1000, "out");
3636        return 0;
3637}
3638
3639int drawscreenbyname(char* screenname)
3640{
3641        debug(1000, "in");
3642        int ret;
3643        struct skin* node = NULL;
3644
3645        node = getscreen(screenname);
3646        if(node == status.skinerr)
3647        {
3648                err("screen not found (%s)", screenname);
3649                return 1;
3650        }
3651
3652        ret = drawscreen(node, 0);
3653        debug(1000, "out");
3654        return ret;
3655}
3656
3657int changeinput(struct skin* node, char* text)
3658{
3659        debug(1000, "in");
3660        int ret = 1;
3661
3662        if(node != NULL)
3663        {
3664                free(node->input);
3665                if(text != NULL)
3666                {
3667                        if((node->type & INPUTBOXNUM) && node->mask != NULL && strlen(text) == 0)
3668                                node->input = strdup(node->mask);
3669                        else
3670                                node->input = strdup(text);
3671                }
3672                else
3673                {
3674                        if((node->type & INPUTBOXNUM) && node->mask != NULL)
3675                                node->input = strdup(node->mask);
3676                        else
3677                                node->input = text;
3678                }
3679                ret = 0;
3680        }
3681        debug(1000, "out");
3682
3683        return ret;
3684}
3685
3686int changetext(struct skin* node, char* text)
3687{
3688        debug(1000, "in");
3689        int ret = 1;
3690
3691        if(node != NULL)
3692        {
3693                free(node->text);
3694                if(text != NULL)
3695                        node->text = strdup(text);
3696                else
3697                        node->text = text;
3698                ret = 0;
3699        }
3700        debug(1000, "out");
3701
3702        return ret;
3703}
3704
3705int changetext2(struct skin* node, char* text)
3706{
3707        debug(1000, "in");
3708        int ret = 1;
3709
3710        if(node != NULL)
3711        {
3712                free(node->text2);
3713                if(text != NULL)
3714                        node->text2 = strdup(text);
3715                else
3716                        node->text2 = text;
3717                ret = 0;
3718        }
3719        debug(1000, "out");
3720
3721        return ret;
3722}
3723
3724
3725int changename(struct skin* node, char* text)
3726{
3727        debug(1000, "in");
3728        int ret = 1;
3729
3730        if(node != NULL)
3731        {
3732                free(node->name);
3733                if(text != NULL)
3734                        node->name = strdup(text);
3735                else
3736                        node->name = text;
3737                ret = 0;
3738        }
3739        debug(1000, "out");
3740
3741        return ret;
3742}
3743
3744int changepicmem(struct skin* node, char* text, int del)
3745{
3746        debug(1000, "in");
3747        unsigned long width = 0, height = 0, rowbytes = 0;
3748        int ret = 1, channels = 0, memfd = -1, length = 0;
3749        unsigned char* buf = NULL;
3750
3751        if(node != NULL)
3752        {
3753                free(node->pic);
3754                if(text != NULL)
3755                {
3756                        node->pic = changepicpath(text);
3757
3758                        if(getpic(node->pic) == NULL)
3759                        {
3760                                length = strlen(node->pic);
3761                                if(node->pic[length - 1] == 'g' && node->pic[length - 2] == 'n' && node->pic[length - 3] == 'p')
3762                                        buf = readpng(node->pic, &width, &height, &rowbytes, &channels, 0, 0, 0, 0, 0, 0);
3763                                else if(getconfigint("pichwdecode", NULL) == 1)
3764                                        readjpg(node->pic, &width, &height, &rowbytes, &channels, &buf, &memfd);
3765                                addpic(node->pic, buf, memfd, width, height, rowbytes, channels, del, NULL);
3766                        }
3767                }
3768                else
3769                        node->pic = text;
3770                ret = 0;
3771        }
3772        debug(1000, "out");
3773
3774        return ret;
3775}
3776
3777int changepic(struct skin* node, char* text)
3778{
3779        debug(1000, "in");
3780        int ret = 1;
3781
3782        if(node != NULL)
3783        {
3784                free(node->pic);
3785                if(text != NULL)
3786                        node->pic = changepicpath(text);
3787                else
3788                        node->pic = text;
3789                ret = 0;
3790        }
3791        debug(1000, "out");
3792
3793        return ret;
3794}
3795
3796int changeselectpic(struct skin* node, char* text)
3797{
3798        debug(1000, "in");
3799        int ret = 1;
3800
3801        if(node != NULL)
3802        {
3803                free(node->selectpic);
3804                if(text != NULL)
3805                        node->selectpic = changepicpath(text);
3806                else
3807                        node->selectpic = text;
3808                ret = 0;
3809        }
3810        debug(1000, "out");
3811
3812        return ret;
3813}
3814
3815int changetitle(struct skin* node, char* text)
3816{
3817        debug(1000, "in");
3818        int ret = 1;
3819
3820        if(node != NULL)
3821        {
3822                free(node->title);
3823                if(text != NULL)
3824                {
3825                        node->title = strdup(text);
3826                        node->titlesize = node->fontsize + 6;
3827                }
3828                else
3829                {
3830                        node->title = text;
3831                        node->titlesize = 0;
3832                }
3833                ret = 0;
3834        }
3835        debug(1000, "out");
3836
3837        return ret;
3838}
3839
3840int changemask(struct skin* node, char* text)
3841{
3842        debug(1000, "in");
3843        int ret = 1;
3844
3845        if(node != NULL)
3846        {
3847                free(node->mask);
3848                if(text != NULL)
3849                {
3850                        if((node->type & INPUTBOXNUM) && (node->input == NULL || strlen(node->input) == 0))
3851                        {
3852                                node->mask = strdup(text);
3853                                free(node->input);
3854                                node->input = strdup(text);
3855                        }
3856                        else
3857                                node->mask = strdup(text);
3858                }
3859                else
3860                        node->mask = text;
3861                ret = 0;
3862        }
3863        debug(1000, "out");
3864
3865        return ret;
3866}
3867
3868int changeret(struct skin* node, char* text)
3869{
3870        debug(1000, "in");
3871        int ret = 1;
3872
3873        if(node != NULL)
3874        {
3875                free(node->ret);
3876                if(text != NULL)
3877                        node->ret = strdup(text);
3878                else
3879                        node->ret = text;
3880                ret = 0;
3881        }
3882        debug(1000, "out");
3883
3884        return ret;
3885}
3886
3887int changeparent(struct skin* node, char* text)
3888{
3889        debug(1000, "in");
3890        int ret = 1;
3891
3892        if(node != NULL)
3893        {
3894                free(node->parent);
3895                if(text != NULL)
3896                        node->parent = strdup(text);
3897                else
3898                        node->parent = text;
3899                ret = 0;
3900        }
3901        debug(1000, "out");
3902
3903        return ret;
3904}
3905
3906int changefont(struct skin* node, char* text)
3907{
3908        debug(1000, "in");
3909        int ret = 1;
3910
3911        if(node != NULL)
3912        {
3913                free(node->font);
3914                if(text != NULL)
3915                        node->font = strdup(text);
3916                else
3917                        node->font = text;
3918                ret = 0;
3919        }
3920        debug(1000, "out");
3921
3922        return ret;
3923}
3924
3925int changeparam1(struct skin* node, char* text)
3926{
3927        debug(1000, "in");
3928        int ret = 1;
3929
3930        if(node != NULL)
3931        {
3932                free(node->param1);
3933                if(text != NULL)
3934                        node->param1 = strdup(text);
3935                else
3936                        node->param1 = text;
3937                ret = 0;
3938        }
3939        debug(1000, "out");
3940
3941        return ret;
3942}
3943
3944int changeparam2(struct skin* node, char* text)
3945{
3946        debug(1000, "in");
3947        int ret = 1;
3948
3949        if(node != NULL)
3950        {
3951                free(node->param2);
3952                if(text != NULL)
3953                        node->param2 = strdup(text);
3954                else
3955                        node->param2 = text;
3956                ret = 0;
3957        }
3958        debug(1000, "out");
3959
3960        return ret;
3961}
3962
3963int changechoiceboxvalue(struct skin* node, char* text)
3964{
3965        debug(1000, "in");
3966        int ret = 1;
3967
3968        if(node != NULL)
3969        {
3970                free(node->choiceboxvalue);
3971                if(text != NULL)
3972                        node->choiceboxvalue = strdup(text);
3973                else
3974                        node->choiceboxvalue = text;
3975                ret = 0;
3976        }
3977        debug(1000, "out");
3978
3979        return ret;
3980}
3981
3982#endif
Note: See TracBrowser for help on using the repository browser.