source: titan/titan/skin.h @ 38558

Last change on this file since 38558 was 38558, checked in by obi, 7 years ago

fix

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