scroll: outsource code
[monky] / src / scroll.c
1 /* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*-
2  *
3  * Conky, a system monitor, based on torsmo
4  *
5  * Any original torsmo code is licensed under the BSD license
6  *
7  * All code written since the fork of torsmo is licensed under the GPL
8  *
9  * Please see COPYING for details
10  *
11  * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
12  * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al.
13  *      (see AUTHORS)
14  * All rights reserved.
15  *
16  * This program is free software: you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation, either version 3 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  * You should have received a copy of the GNU General Public License
26  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
27  *
28  */
29 #include "conky.h"
30 #include "core.h"
31 #include "logging.h"
32 #include "specials.h"
33 #include "text_object.h"
34
35 void parse_scroll_arg(struct text_object *obj, const char *arg, void *free_at_crash)
36 {
37         int n1 = 0, n2 = 0;
38
39         obj->data.scroll.resetcolor = get_current_text_color();
40         obj->data.scroll.step = 1;
41         if (!arg || sscanf(arg, "%u %n", &obj->data.scroll.show, &n1) <= 0)
42                 CRIT_ERR(obj, free_at_crash, "scroll needs arguments: <length> [<step>] <text>");
43
44         sscanf(arg + n1, "%u %n", &obj->data.scroll.step, &n2);
45         if (*(arg + n1 + n2)) {
46                 n1 += n2;
47         } else {
48                 obj->data.scroll.step = 1;
49         }
50         obj->data.scroll.text = malloc(strlen(arg + n1) + obj->data.scroll.show + 1);
51         for(n2 = 0; (unsigned int) n2 < obj->data.scroll.show; n2++) {
52                 obj->data.scroll.text[n2] = ' ';
53         }
54         obj->data.scroll.text[n2] = 0;
55         strcat(obj->data.scroll.text, arg + n1);
56         obj->data.scroll.start = 0;
57         obj->sub = malloc(sizeof(struct text_object));
58         extract_variable_text_internal(obj->sub, obj->data.scroll.text);
59 }
60
61 void print_scroll(struct text_object *obj, char *p, int p_max_size, struct information *cur)
62 {
63         unsigned int j, colorchanges = 0, frontcolorchanges = 0, visibcolorchanges = 0, strend;
64         char *pwithcolors;
65         char buf[max_user_text];
66
67         generate_text_internal(buf, max_user_text, *obj->sub, cur);
68         for(j = 0; buf[j] != 0; j++) {
69                 switch(buf[j]) {
70                         case '\n':      //place all the lines behind each other with LINESEPARATOR between them
71 #define LINESEPARATOR '|'
72                                 buf[j]=LINESEPARATOR;
73                                 break;
74                         case SPECIAL_CHAR:
75                                 colorchanges++;
76                                 break;
77                 }
78         }
79         //no scrolling necessary if the length of the text to scroll is too short
80         if (strlen(buf) - colorchanges <= obj->data.scroll.show) {
81                 snprintf(p, p_max_size, "%s", buf);
82                 return;
83         }
84         //make sure a colorchange at the front is not part of the string we are going to show
85         while(*(buf + obj->data.scroll.start) == SPECIAL_CHAR) {
86                 obj->data.scroll.start++;
87         }
88         //place all chars that should be visible in p, including colorchanges
89         for(j=0; j < obj->data.scroll.show + visibcolorchanges; j++) {
90                 p[j] = *(buf + obj->data.scroll.start + j);
91                 if(p[j] == SPECIAL_CHAR) {
92                         visibcolorchanges++;
93                 }
94                 //if there is still room fill it with spaces
95                 if( ! p[j]) return;
96         }
97         for(; j < obj->data.scroll.show + visibcolorchanges; j++) {
98                 p[j] = ' ';
99         }
100         p[j] = 0;
101         //count colorchanges in front of the visible part and place that many colorchanges in front of the visible part
102         for(j = 0; j < obj->data.scroll.start; j++) {
103                 if(buf[j] == SPECIAL_CHAR) frontcolorchanges++;
104         }
105         pwithcolors=malloc(strlen(p) + 1 + colorchanges - visibcolorchanges);
106         for(j = 0; j < frontcolorchanges; j++) {
107                 pwithcolors[j] = SPECIAL_CHAR;
108         }
109         pwithcolors[j] = 0;
110         strcat(pwithcolors,p);
111         strend = strlen(pwithcolors);
112         //and place the colorchanges not in front or in the visible part behind the visible part
113         for(j = 0; j < colorchanges - frontcolorchanges - visibcolorchanges; j++) {
114                 pwithcolors[strend + j] = SPECIAL_CHAR;
115         }
116         pwithcolors[strend + j] = 0;
117         strcpy(p, pwithcolors);
118         free(pwithcolors);
119         //scroll
120         obj->data.scroll.start += obj->data.scroll.step;
121         if(buf[obj->data.scroll.start] == 0){
122                 obj->data.scroll.start = 0;
123         }
124 #ifdef X11
125         //reset color when scroll is finished
126         new_fg(p + strlen(p), obj->data.scroll.resetcolor);
127 #endif
128 }
129
130 void free_scroll(struct text_object *obj)
131 {
132         if (obj->data.scroll.text)
133                 free(obj->data.scroll.text);
134         if (obj->sub) {
135                 free_text_objects(obj->sub, 1);
136                 free(obj->sub);
137                 obj->sub = NULL;
138         }
139 }