diff --git a/doc/variables.xml b/doc/variables.xml
index a016be57..a8ca92c3 100644
--- a/doc/variables.xml
+++ b/doc/variables.xml
@@ -2583,11 +2583,10 @@
may also contain variables. 'step' is optional and defaults
to 1 if not set. If a var creates output on multiple lines
then the lines are placed behind each other separated with
- a '|'-sign. The effect of $color is disabled inside scroll.
- If you want spaces between the start and the end of 'text',
- place them at the end of 'text' not at the front ("4 foobar"
- can generate "arfo" but "4 foobar " will keep the space like
- this "ar f").
+ a '|'-sign. If you change the textcolor inside $scroll it
+ will automatically have it's old value back at the end of
+ $scroll. The end and the start of text will be seperated by
+ 'length' number of spaces.
diff --git a/src/conky.c b/src/conky.c
index 57dbbd20..d100534d 100644
--- a/src/conky.c
+++ b/src/conky.c
@@ -2992,7 +2992,12 @@ static struct text_object *construct_text_object(const char *s,
} else {
obj->data.scroll.step = 1;
}
- obj->data.scroll.text = strndup(arg + n1, text_buffer_size);
+ obj->data.scroll.text = malloc(strlen(arg + n1) + obj->data.scroll.show + 1);
+ for(n2 = 0; (unsigned int) n2 < obj->data.scroll.show; n2++) {
+ obj->data.scroll.text[n2] = ' ';
+ }
+ obj->data.scroll.text[n2] = 0;
+ strcat(obj->data.scroll.text, arg + n1);
obj->data.scroll.start = 0;
obj->sub = malloc(sizeof(struct text_object));
extract_variable_text_internal(obj->sub,
@@ -5792,50 +5797,68 @@ static void generate_text_internal(char *p, int p_max_size,
snprintf(p, p_max_size, "%s", buf);
}
OBJ(scroll) {
- unsigned int j, k, colorchanges = 0;
- char *tmp, buf[max_user_text];
+ unsigned int j, colorchanges = 0, frontcolorchanges = 0, visibcolorchanges = 0, strend;
+ char *pwithcolors;
+ char buf[max_user_text];
generate_text_internal(buf, max_user_text,
*obj->sub, cur);
-
- if (strlen(buf) <= obj->data.scroll.show) {
- snprintf(p, p_max_size, "%s", buf);
- break;
- }
for(j = 0; buf[j] != 0; j++) {
switch(buf[j]) {
case '\n': //place all the lines behind each other with LINESEPARATOR between them
#define LINESEPARATOR '|'
buf[j]=LINESEPARATOR;
break;
- case 1: //make sure $color isn't treated like a char
- strfold(buf+j, 1);
+ case 1: //every 1 is a color change (1, not '1')
colorchanges++;
break;
}
}
- //scroll the output obj->data.scroll.start places by copying that many chars from
- //the front of the string to tmp, scrolling the rest to the front and placing tmp
- //at the back of the string
- tmp = calloc(obj->data.scroll.start + 1, sizeof(char));
- strncpy(tmp, buf, obj->data.scroll.start); tmp[obj->data.scroll.start] = 0;
- for(j = obj->data.scroll.start; buf[j] != 0; j++){
- buf[j - obj->data.scroll.start] = buf[j];
+ //no scrolling necessary if the length of the text to scroll is too short
+ if (strlen(buf) - colorchanges <= obj->data.scroll.show) {
+ snprintf(p, p_max_size, "%s", buf);
+ break;
}
- strcpy(&buf[j - obj->data.scroll.start], tmp);
- free(tmp);
- //only show the requested number of chars
- if(obj->data.scroll.show < j) {
- for(k = 0; k < colorchanges; k++) {
- buf[obj->data.scroll.show + k] = 1;
+ //make sure a colorchange at the front is not part of the string we are going to show
+ while(*(buf + obj->data.scroll.start) == 1) {
+ obj->data.scroll.start++;
+ }
+ //place all chars that should be visible in p, including colorchanges
+ for(j=0; j < obj->data.scroll.show + visibcolorchanges; j++) {
+ p[j] = *(buf + obj->data.scroll.start + j);
+ if(p[j] == 1) {
+ visibcolorchanges++;
}
- buf[obj->data.scroll.show + colorchanges] = 0;
+ //if there is still room fill it with spaces
+ if( ! p[j]) break;
}
- //next time, scroll a place more or reset scrolling if we are at the end
+ for(; j < obj->data.scroll.show + visibcolorchanges; j++) {
+ p[j] = ' ';
+ }
+ p[j] = 0;
+ //count colorchanges in front of the visible part and place that many colorchanges in front of the visible part
+ for(j = 0; j < obj->data.scroll.start; j++) {
+ if(buf[j] == 1) frontcolorchanges++;
+ }
+ pwithcolors=malloc(strlen(p) + 1 + colorchanges - visibcolorchanges);
+ for(j = 0; j < frontcolorchanges; j++) {
+ pwithcolors[j] = 1;
+ }
+ pwithcolors[j] = 0;
+ strcat(pwithcolors,p);
+ strend = strlen(pwithcolors);
+ //and place the colorchanges not in front or in the visible part behind the visible part
+ for(j = 0; j < colorchanges - frontcolorchanges - visibcolorchanges; j++) {
+ pwithcolors[strend + j] = 1;
+ }
+ pwithcolors[strend + j] = 0;
+ strcpy(p, pwithcolors);
+ free(pwithcolors);
+ //scroll
obj->data.scroll.start += obj->data.scroll.step;
- if(obj->data.scroll.start >= j){
+ if(buf[obj->data.scroll.start] == 0){
obj->data.scroll.start = 0;
}
- snprintf(p, p_max_size, "%s", buf);
+ //reset color when scroll is finished
new_fg(p + strlen(p), obj->data.scroll.resetcolor);
}
OBJ(combine) {