source: titan/titan/skin.h @ 41185

Last change on this file since 41185 was 41185, checked in by gost, 6 years ago

[titan] add new skinfunction getvolumebar

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