source: titan/titan/skin.h @ 40896

Last change on this file since 40896 was 39667, checked in by gost, 7 years ago

[titan] add new skin funktion -> getlasttitle

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