source: titan/titan/skin.h @ 30133

Last change on this file since 30133 was 30133, checked in by obi, 8 years ago

[atemio6200] update titan stuff

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