Changeset 3954


Ignore:
Timestamp:
11/19/09 11:46:15 (4 years ago)
Author:
jylam
Message:
  • Fixed numerous warnings (warn_unused_result and deprecated libcaca functions, mostly)
Location:
neercs/trunk/src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • neercs/trunk/src/client.c

    r3942 r3954  
    1 /* 
     1/*  
    22 *  neercs        console-based window manager 
    33 *  Copyright (c) 2006 Sam Hocevar <sam@zoy.org> 
     
    4040void mainloop(struct screen_list *screen_list) 
    4141{ 
    42     char * buf = NULL; 
     42    char *buf = NULL; 
    4343 
    44     long long unsigned int last_key_time = 0; 
    45     last_key_time = get_us(); 
     44    screen_list->last_key_time = get_us(); 
    4645 
    47     for(;;) 
     46    for (;;) 
    4847    { 
    4948        caca_event_t ev; 
    5049        int ret = 0; 
    5150        ssize_t n; 
    52         if(!screen_list) goto end; 
    53         if(!buf) 
     51        if (!screen_list) 
     52            goto end; 
     53        if (!buf) 
    5454            buf = malloc(NEERCS_RECV_BUFSIZE); 
    55         if(!buf) 
     55        if (!buf) 
    5656        { 
    5757            debug("Failed to allocate memory"); 
    5858            goto end; 
    5959        } 
    60         if(screen_list->socket[SOCK_CLIENT] && (n = read(screen_list->socket[SOCK_CLIENT], buf, NEERCS_RECV_BUFSIZE-1)) > 0) 
     60        if (screen_list->socket[SOCK_CLIENT] 
     61            && (n = 
     62                read(screen_list->socket[SOCK_CLIENT], buf, 
     63                     NEERCS_RECV_BUFSIZE - 1)) > 0) 
    6164        { 
    6265            buf[n] = 0; 
    6366            debug("Received from server: %s", buf); 
    64             if(!strncmp("DETACH", buf, 6)) 
     67            if (!strncmp("DETACH", buf, 6)) 
    6568            { 
    6669                ret = 1; 
    6770                break; 
    6871            } 
    69             else if(!strncmp("UPDATE ", buf, 7)) 
     72            else if (!strncmp("UPDATE ", buf, 7)) 
    7073            { 
    7174                int x, y; 
    7275                ssize_t l2 = 0, lb = 0; 
    73                 char * buf2; 
     76                char *buf2; 
    7477                size_t l = 0; 
    75                 /* FIXME check the length before calling atoi*/ 
    76                 x = atoi(buf+8); 
    77                 y = atoi(buf+19); 
    78                 /* 0 means we have valid data but incomplete, so read the rest */ 
    79                 while(l == 0) 
     78                /* FIXME check the length before calling atoi */ 
     79                x = atoi(buf + 8); 
     80                y = atoi(buf + 19); 
     81                /* 0 means we have valid data but incomplete, so read the rest  
     82                 */ 
     83                while (l == 0) 
    8084                { 
    8185                    buf2 = realloc(buf, l2 + NEERCS_RECV_BUFSIZE); 
    82                     if(!buf2) 
     86                    if (!buf2) 
    8387                    { 
    8488                        debug("Failed to allocate memory"); 
     
    8791                    buf = buf2; 
    8892                    fcntl(screen_list->socket[SOCK_CLIENT], F_SETFL, 0); 
    89                     lb = read(screen_list->socket[SOCK_CLIENT], buf+l2, NEERCS_RECV_BUFSIZE-1); 
    90                     if(lb < 0) 
     93                    lb = read(screen_list->socket[SOCK_CLIENT], buf + l2, 
     94                              NEERCS_RECV_BUFSIZE - 1); 
     95                    if (lb < 0) 
    9196                    { 
    92                         debug("Failed to read the end of the refresh message (%s)", strerror(errno)); 
     97                        debug 
     98                            ("Failed to read the end of the refresh message (%s)", 
     99                             strerror(errno)); 
    93100                        l = -1; 
    94101                    } 
     
    97104                        l2 += lb; 
    98105#if defined HAVE_CACA_DIRTY_RECTANGLES 
    99                         l = caca_import_area_from_memory(screen_list->cv, x, y, buf, l2, "caca"); 
     106                        l = caca_import_area_from_memory(screen_list->cv, x, y, 
     107                                                         buf, l2, "caca"); 
    100108#else 
    101                         l = caca_import_memory(screen_list->cv, buf, l2, "caca"); 
     109                        l = caca_import_memory(screen_list->cv, buf, l2, 
     110                                               "caca"); 
    102111#endif 
    103112                    } 
     
    105114                fcntl(screen_list->socket[SOCK_CLIENT], F_SETFL, O_NONBLOCK); 
    106115            } 
    107             else if(!strncmp("REFRESH ", buf, 8)) 
     116            else if (!strncmp("REFRESH ", buf, 8)) 
    108117            { 
    109118                int dt, x, y; 
    110                 /* FIXME check the length before calling atoi*/ 
    111                 x = atoi(buf+8); 
    112                 y = atoi(buf+19); 
     119                /* FIXME check the length before calling atoi */ 
     120                x = atoi(buf + 8); 
     121                y = atoi(buf + 19); 
    113122                caca_gotoxy(screen_list->cv, x, y); 
    114123                caca_refresh_display(screen_list->dp); 
    115124                dt = caca_get_display_time(screen_list->dp); 
    116                 debug("refreshtime=%dms (limit %d, requested %d)", dt/1000, screen_list->delay, screen_list->requested_delay); 
    117                 /* Adjust refresh delay so that the server do not compute useless things */ 
    118                 if(dt > 2*1000*screen_list->delay && screen_list->delay <= 100) 
     125                debug("refreshtime=%dms (limit %d, requested %d)", dt / 1000, 
     126                      screen_list->delay, screen_list->requested_delay); 
     127                /* Adjust refresh delay so that the server do not compute 
     128                   useless things */ 
     129                if (dt > 2 * 1000 * screen_list->delay 
     130                    && screen_list->delay <= 100) 
    119131                { 
    120                     screen_list->delay*=2; 
     132                    screen_list->delay *= 2; 
    121133                    send_delay(screen_list); 
    122134                } 
    123                 else if(dt < screen_list->delay*1000*1.2 && 
    124                         screen_list->delay >= 3*screen_list->requested_delay/2) 
     135                else if (dt < screen_list->delay * 1000 * 1.2 && 
     136                         screen_list->delay >= 
     137                         3 * screen_list->requested_delay / 2) 
    125138                { 
    126                     screen_list->delay=2*screen_list->delay/3; 
     139                    screen_list->delay = 2 * screen_list->delay / 3; 
    127140                    send_delay(screen_list); 
    128141                } 
    129142            } 
    130             else if(!strncmp("CURSOR ", buf, 7)) 
     143            else if (!strncmp("CURSOR ", buf, 7)) 
    131144            { 
    132                 caca_set_cursor(screen_list->dp, atoi(buf+7)); 
     145                caca_set_cursor(screen_list->dp, atoi(buf + 7)); 
    133146            } 
    134             else if(!strncmp("TITLE ", buf, 6)) 
     147            else if (!strncmp("TITLE ", buf, 6)) 
    135148            { 
    136                 caca_set_display_title(screen_list->dp, buf+6); 
     149                caca_set_display_title(screen_list->dp, buf + 6); 
    137150                caca_refresh_display(screen_list->dp); 
    138151            } 
     
    143156        } 
    144157 
    145         if(ret) 
     158        if (ret) 
    146159            break; 
    147160 
    148161        ret = caca_get_event(screen_list->dp, 
    149162                             CACA_EVENT_KEY_PRESS 
    150                              |CACA_EVENT_RESIZE 
    151                              |CACA_EVENT_QUIT, 
    152                              &ev, 10000); 
    153         if(ret) 
     163                             | CACA_EVENT_RESIZE 
     164                             | CACA_EVENT_QUIT, &ev, 10000); 
     165        if (ret) 
    154166            ret = send_event(ev, screen_list); 
    155167 
    156         if(ret) 
     168        if (ret) 
    157169            break; 
    158170    } 
    159171 
    160 end: 
    161     if(buf) 
     172  end: 
     173    if (buf) 
    162174        free(buf); 
    163175 
  • neercs/trunk/src/grab.c

    r3942 r3954  
    1 /* 
     1/*  
    22 *  neercs        console-based window manager 
    33 *  Copyright (c) 2008 Pascal Terjan 
     
    1515#include "config.h" 
    1616 
    17 #define _XOPEN_SOURCE 500 /* getsid() */ 
     17#define _XOPEN_SOURCE 500       /* getsid() */ 
    1818 
    1919#include <dirent.h> 
     
    5757 
    5858    parent = mytrace_attach(pid); 
    59     if(!parent) 
     59    if (!parent) 
    6060    { 
    6161        fprintf(stderr, "Cannot access process %ld\n", pid); 
     
    6969 
    7070    /* Look for file descriptors that are PTYs */ 
    71     while((fddirent = readdir(fddir)) && i < (int)sizeof(to_open)-1) 
     71    while ((fddirent = readdir(fddir)) && i < (int)sizeof(to_open) - 1) 
    7272    { 
    7373        fd = atoi(fddirent->d_name); 
     
    7575        to_open[i] = 0; 
    7676        lstat(fdstr, &stat_buf); 
    77         if((stat_buf.st_mode & S_IRUSR) && (stat_buf.st_mode & S_IWUSR)) 
     77        if ((stat_buf.st_mode & S_IRUSR) && (stat_buf.st_mode & S_IWUSR)) 
    7878            mode[i] = O_RDWR; 
    79         else if(stat_buf.st_mode & S_IWUSR) 
     79        else if (stat_buf.st_mode & S_IWUSR) 
    8080            mode[i] = O_WRONLY; 
    8181        else 
    8282            mode[i] = O_RDONLY; 
    8383 
    84         snprintf(fdstr, sizeof(fdstr), "/proc/%ld/fd/%s", pid, fddirent->d_name); 
    85  
    86         if(stat(fdstr, &stat_buf) < 0) 
    87             continue; 
    88  
    89         if(!S_ISCHR(stat_buf.st_mode) 
     84        snprintf(fdstr, sizeof(fdstr), "/proc/%ld/fd/%s", pid, 
     85                 fddirent->d_name); 
     86 
     87        if (stat(fdstr, &stat_buf) < 0) 
     88            continue; 
     89 
     90        if (!S_ISCHR(stat_buf.st_mode) 
    9091            || MAJOR(stat_buf.st_rdev) != UNIX98_PTY_SLAVE_MAJOR) 
    9192            continue; 
     
    9394        debug("found pty %d for pid %d", fd, pid); 
    9495 
    95         if(!validtos) 
     96        if (!validtos) 
    9697        { 
    9798            ret = mytrace_tcgets(child, fd, &tos); 
    98             if(ret < 0) 
     99            if (ret < 0) 
    99100            { 
    100101                perror("mytrace_tcgets"); 
     
    110111    closedir(fddir); 
    111112 
    112     if(i>=(int)sizeof(to_open)-1) 
     113    if (i >= (int)sizeof(to_open) - 1) 
    113114    { 
    114115        fprintf(stderr, "too many open pty\n"); 
     
    118119 
    119120    ret = mytrace_exec(parent, "/usr/bin/reset"); 
    120     if(ret < 0) 
     121    if (ret < 0) 
    121122        mytrace_exit(parent, 0); 
    122123    mytrace_detach(parent); 
    123     waitpid(pid, NULL, 0); /* Wait for reset to finish before displaying */ 
     124    waitpid(pid, NULL, 0);      /* Wait for reset to finish before displaying */ 
    124125    mytrace_write(child, 2, "\033[H\033[2J", 7); 
    125126    mytrace_write(child, 2, "\n[Process stolen by neercs]\r\n\n", 30); 
     
    132133 
    133134    ret = mytrace_setpgid(child, 0, getsid(pid)); 
    134     if(ret < 0) 
     135    if (ret < 0) 
    135136    { 
    136137        fprintf(stderr, "syscall setpgid failed\n"); 
     
    139140    } 
    140141 
    141     if(ret != 0) 
     142    if (ret != 0) 
    142143    { 
    143144        fprintf(stderr, "setpgid returned %d\n", ret); 
     
    147148 
    148149    ret = mytrace_setsid(child); 
    149     if(ret < 0) 
     150    if (ret < 0) 
    150151    { 
    151152        fprintf(stderr, "syscall setsid failed\n"); 
     
    157158 
    158159    /* Reopen PTY file descriptors */ 
    159     for(; i >= 0; i--) 
    160     { 
    161         if(!to_open[i]) 
     160    for (; i >= 0; i--) 
     161    { 
     162        if (!to_open[i]) 
    162163            continue; 
    163164        ret = mytrace_close(child, fds[i]); 
    164         if(ret < 0) 
     165        if (ret < 0) 
    165166        { 
    166167            perror("mytrace_close"); 
     
    168169        } 
    169170        fd = mytrace_open(child, ptyname, mode[i]); 
    170         if(fd < 0) 
     171        if (fd < 0) 
    171172        { 
    172173            perror("mytrace_open"); 
     
    177178        mytrace_sctty(child, fd); 
    178179 
    179         if(validtos) 
     180        if (validtos) 
    180181        { 
    181182            ret = mytrace_tcsets(child, fd, &tos); 
    182             if(ret < 0) 
     183            if (ret < 0) 
    183184            { 
    184185                perror("mytrace_tcsets"); 
     
    187188        } 
    188189        ret = mytrace_dup2(child, fd, fds[i]); 
    189         if(ret < 0) 
     190        if (ret < 0) 
    190191        { 
    191192            perror("mytrace_dup2"); 
     
    204205} 
    205206 
    206 struct process { 
     207struct process 
     208{ 
    207209    long pid; 
    208210    char *cmdline; 
    209211}; 
    210212 
    211 static int list_process(struct process ** process_list) 
     213static int list_process(struct process **process_list) 
    212214{ 
    213215    glob_t pglob; 
    214     unsigned int i, n=0; 
     216    unsigned int i, n = 0; 
    215217    glob("/proc/[0-9]*", GLOB_NOSORT, NULL, &pglob); 
    216     *process_list = malloc(pglob.gl_pathc*sizeof(struct process)); 
    217     for(i=0; i<pglob.gl_pathc; i++) 
     218    *process_list = malloc(pglob.gl_pathc * sizeof(struct process)); 
     219    for (i = 0; i < pglob.gl_pathc; i++) 
    218220    { 
    219221        glob_t pglob2; 
    220222        unsigned int j; 
    221         char * fds; 
     223        char *fds; 
    222224        (*process_list)[n].pid = atoi(basename(pglob.gl_pathv[i])); 
    223225        /* Don't allow grabbing ourselves */ 
    224         if((*process_list)[n].pid == getpid()) 
    225             continue; 
    226         asprintf(&fds, "%s/fd/*", pglob.gl_pathv[i]); 
     226        if ((*process_list)[n].pid == getpid()) 
     227            continue; 
     228        /* FIXME check value of r */ 
     229        int r = asprintf(&fds, "%s/fd/*", pglob.gl_pathv[i]); 
    227230        glob(fds, GLOB_NOSORT, NULL, &pglob2); 
    228231        free(fds); 
    229         for(j=0; j<pglob2.gl_pathc; j++) 
     232        for (j = 0; j < pglob2.gl_pathc; j++) 
    230233        { 
    231234            char path[4096]; 
    232235            ssize_t l = readlink(pglob2.gl_pathv[j], path, sizeof(path)); 
    233             if(l <= 0) 
     236            if (l <= 0) 
    234237                continue; 
    235238            path[l] = '\0'; 
    236             if(strstr(path, "/dev/pt")) 
    237             { 
    238                 char * cmdfile; 
     239            if (strstr(path, "/dev/pt")) 
     240            { 
     241                char *cmdfile; 
    239242                int fd; 
    240                 asprintf(&cmdfile, "%s/cmdline", pglob.gl_pathv[i]); 
     243                /* FIXME check value of r */ 
     244                r = asprintf(&cmdfile, "%s/cmdline", pglob.gl_pathv[i]); 
    241245                fd = open(cmdfile, O_RDONLY); 
    242246                free(cmdfile); 
    243                 if(fd) 
     247                if (fd) 
    244248                { 
    245                     read(fd, path,  sizeof(path)); 
     249                    /* FIXME check value of r */ 
     250                    r = read(fd, path, sizeof(path)); 
    246251                    (*process_list)[n].cmdline = strdup(path); 
    247252                    close(fd); 
     
    257262} 
    258263 
    259 long select_process(struct screen_list* screen_list) 
     264long select_process(struct screen_list *screen_list) 
    260265{ 
    261266    caca_event_t ev; 
     
    266271    int ret = 0; 
    267272    int start = 0; 
    268     struct process * process_list; 
     273    struct process *process_list; 
    269274 
    270275    nb_process = list_process(&process_list); 
     
    272277    screen_list->cv = caca_create_canvas(0, 0); 
    273278    screen_list->dp = caca_create_display(screen_list->cv); 
    274     if(!screen_list->dp) 
     279    if (!screen_list->dp) 
    275280        goto end; 
    276281    caca_set_cursor(screen_list->dp, 0); 
    277282    caca_set_display_title(screen_list->dp, PACKAGE_STRING); 
    278     while(1) 
    279     { 
    280         if(refresh) 
     283    while (1) 
     284    { 
     285        if (refresh) 
    281286        { 
    282287            caca_set_color_ansi(screen_list->cv, CACA_BLUE, CACA_BLUE); 
     
    284289                          0, 0, 
    285290                          caca_get_canvas_width(screen_list->cv), 
    286                           caca_get_canvas_height(screen_list->cv), 
    287                           '#'); 
     291                          caca_get_canvas_height(screen_list->cv), '#'); 
    288292            caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_BLUE); 
    289293            caca_draw_cp437_box(screen_list->cv, 
    290294                                0, 0, 
    291295                                caca_get_canvas_width(screen_list->cv), 
    292                                 caca_get_canvas_height(screen_list->cv) 
    293                                 ); 
    294             caca_printf(screen_list->cv, 2, 2, "Please select a process to grab:"); 
    295             for(i=0; i<nb_process && i<caca_get_canvas_height(screen_list->cv)-4; i++) 
    296             { 
    297                 if(i == current_line-1) 
     296                                caca_get_canvas_height(screen_list->cv)); 
     297            caca_printf(screen_list->cv, 2, 2, 
     298                        "Please select a process to grab:"); 
     299            for (i = 0; 
     300                 i < nb_process 
     301                 && i < caca_get_canvas_height(screen_list->cv) - 4; i++) 
     302            { 
     303                if (i == current_line - 1) 
    298304                { 
    299305                    caca_set_attr(screen_list->cv, CACA_BOLD); 
    300                     caca_set_color_ansi(screen_list->cv, CACA_GREEN, CACA_BLUE); 
    301                     caca_put_char(screen_list->cv, 1, i+3, '>'); 
     306                    caca_set_color_ansi(screen_list->cv, CACA_GREEN, 
     307                                        CACA_BLUE); 
     308                    caca_put_char(screen_list->cv, 1, i + 3, '>'); 
    302309                } 
    303310                else 
    304311                { 
    305312                    caca_set_attr(screen_list->cv, 0); 
    306                     caca_set_color_ansi(screen_list->cv, CACA_LIGHTGRAY, CACA_BLUE); 
    307                     caca_put_char(screen_list->cv, 1, i+3, ' '); 
     313                    caca_set_color_ansi(screen_list->cv, CACA_LIGHTGRAY, 
     314                                        CACA_BLUE); 
     315                    caca_put_char(screen_list->cv, 1, i + 3, ' '); 
    308316                } 
    309317                caca_printf(screen_list->cv, 
    310                             3, i+3, 
     318                            3, i + 3, 
    311319                            "%5d %s", 
    312                             process_list[i+start].pid, 
    313                             process_list[i+start].cmdline); 
     320                            process_list[i + start].pid, 
     321                            process_list[i + start].cmdline); 
    314322            } 
    315323            caca_refresh_display(screen_list->dp); 
     
    317325        } 
    318326 
    319         if(!caca_get_event(screen_list->dp, 
    320                            CACA_EVENT_KEY_PRESS 
    321                            |CACA_EVENT_RESIZE 
    322                            |CACA_EVENT_QUIT, 
    323                            &ev, 10000)) 
     327        if (!caca_get_event(screen_list->dp, 
     328                            CACA_EVENT_KEY_PRESS 
     329                            | CACA_EVENT_RESIZE | CACA_EVENT_QUIT, &ev, 10000)) 
    324330            continue; 
    325331 
    326332        t = caca_get_event_type(&ev); 
    327333 
    328         if(t & CACA_EVENT_KEY_PRESS) 
     334        if (t & CACA_EVENT_KEY_PRESS) 
    329335        { 
    330336            unsigned int c = caca_get_event_key_ch(&ev); 
    331             switch(c) 
     337            switch (c) 
    332338            { 
    333339            case CACA_KEY_UP: 
    334                 if(current_line>1) 
     340                if (current_line > 1) 
    335341                    current_line--; 
    336                 if(current_line < start && start > 0) 
     342                if (current_line < start && start > 0) 
    337343                    start--; 
    338344                break; 
    339345            case CACA_KEY_DOWN: 
    340                 if(current_line<nb_process) 
     346                if (current_line < nb_process) 
    341347                    current_line++; 
    342                 if(current_line > start + caca_get_canvas_height(screen_list->cv)-3) 
     348                if (current_line > 
     349                    start + caca_get_canvas_height(screen_list->cv) - 3) 
    343350                    start++; 
    344351                break; 
    345352            case CACA_KEY_RETURN: 
    346                 ret = process_list[current_line-1].pid; 
     353                ret = process_list[current_line - 1].pid; 
    347354                goto end; 
    348355                break; 
     
    355362            refresh = 1; 
    356363        } 
    357         else if(t & CACA_EVENT_RESIZE) 
     364        else if (t & CACA_EVENT_RESIZE) 
    358365        { 
    359366            refresh = 1; 
    360367        } 
    361         else if(t & CACA_EVENT_QUIT) 
     368        else if (t & CACA_EVENT_QUIT) 
    362369            goto end; 
    363370    } 
    364371 
    365 end: 
    366     if(screen_list->dp) 
     372  end: 
     373    if (screen_list->dp) 
    367374    { 
    368375        caca_free_display(screen_list->dp); 
    369376        screen_list->dp = NULL; 
    370377    } 
    371     if(screen_list->cv) 
     378    if (screen_list->cv) 
    372379    { 
    373380        caca_free_canvas(screen_list->cv); 
    374381        screen_list->cv = NULL; 
    375382    } 
    376     if(nb_process > 0) 
    377     { 
    378         for(i=0; i<nb_process; i++) 
     383    if (nb_process > 0) 
     384    { 
     385        for (i = 0; i < nb_process; i++) 
    379386        { 
    380387            free(process_list[i].cmdline); 
     
    384391    return ret; 
    385392} 
    386  
  • neercs/trunk/src/screensaver.c

    r3942 r3954  
    123123        flying_toaster->toaster[i] = caca_create_canvas(0, 0); 
    124124        flying_toaster->mask[i] = caca_create_canvas(0, 0); 
    125         caca_import_memory(flying_toaster->toaster[i], 
     125        caca_import_canvas_from_memory(flying_toaster->toaster[i], 
    126126                           toaster_text[i], 
    127127                           strlen(toaster_text[i]), "utf8"); 
    128         caca_import_memory(flying_toaster->mask[i], 
     128        caca_import_canvas_from_memory(flying_toaster->mask[i], 
    129129                           toaster_mask[i], 
    130130                           strlen(toaster_mask[i]), "utf8"); 
  • neercs/trunk/src/server.c

    r3948 r3954  
    181181        sprintf(buf2, "REFRESH %10d %10d", caca_get_cursor_x(screen_list->cv), 
    182182                caca_get_cursor_y(screen_list->cv)); 
    183         write(screen_list->socket[SOCK_CLIENT], buf2, strlen(buf2) + 1); 
     183        /* FIXME check value of r */ 
     184        int r = 
     185            write(screen_list->socket[SOCK_CLIENT], buf2, strlen(buf2) + 1); 
     186        (void)r; 
    184187#if defined HAVE_CACA_DIRTY_RECTANGLES 
    185188        caca_clear_dirty_rect_list(screen_list->cv); 
     
    502505                /* Normal key, convert it if needed */ 
    503506                str = convert_input_ansi(&c, &size); 
    504                 write(screen_list->screen[screen_list->pty]->fd, str, size); 
     507                /* FIXME check value of r */ 
     508                int r = write(screen_list->screen[screen_list->pty]->fd, str, 
     509                              size); 
     510                (void)r; 
    505511                break; 
    506512            } 
Note: See TracChangeset for help on using the changeset viewer.