source: titan/titan/skin.h

Last change on this file was 46378, checked in by obi, 7 months ago

subs step 7

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