source: titan/titan/skin.h @ 32070

Last change on this file since 32070 was 32070, checked in by gost, 8 years ago

back to M32067

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