source: titan/titan/skin.h @ 30883

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

add debug for oled

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