Changeset b74959bd in mainline for uspace/srv/fb
- Timestamp:
- 2007-11-20T21:33:32Z (18 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 8498915
- Parents:
- 3209923
- Location:
- uspace/srv/fb
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fb/ega.c
r3209923 rb74959bd 83 83 int i; 84 84 85 for (i = 0; i < scr_width *scr_height; i++) {85 for (i = 0; i < scr_width * scr_height; i++) { 86 86 scr_addr[i * 2] = ' '; 87 87 scr_addr[i * 2 + 1] = style; … … 126 126 if (rows > 0) { 127 127 memcpy(scr_addr, ((char *) scr_addr) + rows * scr_width * 2, 128 scr_width * scr_height * 2 - rows * scr_width * 2);128 scr_width * scr_height * 2 - rows * scr_width * 2); 129 129 for (i = 0; i < rows * scr_width; i++) 130 130 (((short *) scr_addr) + scr_width * scr_height - rows * 131 scr_width)[i] = ((style << 8) + ' ');131 scr_width)[i] = ((style << 8) + ' '); 132 132 } else if (rows < 0) { 133 133 memcpy(((char *)scr_addr) - rows * scr_width * 2, scr_addr, 134 scr_width * scr_height * 2 + rows * scr_width * 2);134 scr_width * scr_height * 2 + rows * scr_width * 2); 135 135 for (i = 0; i < -rows * scr_width; i++) 136 136 ((short *)scr_addr)[i] = ((style << 8 ) + ' '); … … 153 153 scr_addr[i * 2] = data[i].character; 154 154 scr_addr[i * 2 + 1] = EGA_STYLE(data[i].style.fg_color, 155 data[i].style.bg_color);155 data[i].style.bg_color); 156 156 } 157 157 } … … 161 161 int i; 162 162 163 for (i =0; (i < MAX_SAVED_SCREENS) && (saved_screens[i].data); i++)163 for (i = 0; (i < MAX_SAVED_SCREENS) && (saved_screens[i].data); i++) 164 164 ; 165 165 if (i == MAX_SAVED_SCREENS) … … 176 176 if (saved_screens[i].data) 177 177 memcpy(scr_addr, saved_screens[i].data, 2 * scr_width * 178 scr_height);178 scr_height); 179 179 else 180 180 return EINVAL; … … 196 196 197 197 if (client_connected) { 198 ipc_answer_ fast(iid, ELIMIT, 0,0);198 ipc_answer_0(iid, ELIMIT); 199 199 return; 200 200 } 201 201 client_connected = 1; 202 ipc_answer_ fast(iid, 0, 0, 0); /* Accept connection */202 ipc_answer_0(iid, EOK); /* Accept connection */ 203 203 204 204 while (1) { … … 207 207 case IPC_M_PHONE_HUNGUP: 208 208 client_connected = 0; 209 ipc_answer_ fast(callid, 0, 0, 0);209 ipc_answer_0(callid, EOK); 210 210 return; /* Exit thread */ 211 211 case IPC_M_AS_AREA_SEND: … … 213 213 intersize = IPC_GET_ARG2(call); 214 214 if (intersize >= scr_width * scr_height * 215 sizeof(*interbuf)) {216 receive_comm_area(callid, &call, (void *)217 &interbuf);215 sizeof(*interbuf)) { 216 receive_comm_area(callid, &call, 217 (void *) &interbuf); 218 218 continue; 219 219 } … … 229 229 break; 230 230 case FB_GET_CSIZE: 231 ipc_answer_ fast(callid, 0, scr_height, scr_width);231 ipc_answer_2(callid, EOK, scr_height, scr_width); 232 232 continue; 233 233 case FB_CLEAR: … … 301 301 retval = ENOENT; 302 302 } 303 ipc_answer_ fast(callid, retval, 0, 0);303 ipc_answer_0(callid, retval); 304 304 } 305 305 } … … 319 319 320 320 physmem_map(ega_ph_addr, scr_addr, ALIGN_UP(sz, PAGE_SIZE) >> 321 PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE);321 PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE); 322 322 323 323 async_set_client_connection(ega_client_connection); -
uspace/srv/fb/fb.c
r3209923 rb74959bd 166 166 { 167 167 *((uint32_t *) dst) = BLUE(rgb, 8) << 16 | GREEN(rgb, 8) << 8 | 168 RED(rgb, 8);168 RED(rgb, 8); 169 169 } 170 170 … … 174 174 int color = *(uint32_t *)(src); 175 175 return ((color & 0xff) << 16) | (((color >> 8) & 0xff) << 8) | 176 ((color >> 16) & 0xff);176 ((color >> 16) & 0xff); 177 177 } 178 178 … … 209 209 /* 5-bit, 5-bits, 5-bits */ 210 210 *((uint16_t *)(dst)) = RED(rgb, 5) << 10 | GREEN(rgb, 5) << 5 | 211 BLUE(rgb, 5);211 BLUE(rgb, 5); 212 212 } 213 213 … … 218 218 int color = *(uint16_t *)(src); 219 219 return (((color >> 10) & 0x1f) << (16 + 3)) | 220 (((color >> 5) & 0x1f) << (8 + 3)) | ((color & 0x1f) << 3);220 (((color >> 5) & 0x1f) << (8 + 3)) | ((color & 0x1f) << 3); 221 221 } 222 222 … … 227 227 /* 5-bit, 6-bits, 5-bits */ 228 228 *((uint16_t *)(dst)) = RED(rgb, 5) << 11 | GREEN(rgb, 6) << 5 | 229 BLUE(rgb, 5);229 BLUE(rgb, 5); 230 230 } 231 231 … … 236 236 int color = *(uint16_t *)(src); 237 237 return (((color >> 11) & 0x1f) << (16 + 3)) | 238 (((color >> 5) & 0x3f) << (8 + 2)) | ((color & 0x1f) << 3);238 (((color >> 5) & 0x3f) << (8 + 2)) | ((color & 0x1f) << 3); 239 239 } 240 240 … … 252 252 int color = *(uint8_t *)src; 253 253 return (((color >> 5) & 0x7) << (16 + 5)) | 254 (((color >> 3) & 0x3) << (8 + 6)) | ((color & 0x7) << 5);254 (((color >> 3) & 0x3) << (8 + 6)) | ((color & 0x7) << 5); 255 255 } 256 256 … … 270 270 if (! (vport->paused && vport->dbdata)) 271 271 (*screen.rgb2scr)(&screen.fbaddress[POINTPOS(dx,dy)], 272 COLOR(color));272 COLOR(color)); 273 273 274 274 if (vport->dbdata) { … … 292 292 putpixel_mem(char *mem, unsigned int x, unsigned int y, int color) 293 293 { 294 (*screen.rgb2scr)(&mem[POINTPOS(x, y)], COLOR(color));294 (*screen.rgb2scr)(&mem[POINTPOS(x, y)], COLOR(color)); 295 295 } 296 296 … … 303 303 304 304 if (!tmpline) 305 tmpline = malloc(screen.scanline *screen.pixelbytes);305 tmpline = malloc(screen.scanline * screen.pixelbytes); 306 306 307 307 /* Clear first line */ … … 316 316 for (y = sy;y < sy+height; y++) 317 317 memcpy(&screen.fbaddress[POINTPOS(sx,y)], tmpline, 318 screen.pixelbytes * width);318 screen.pixelbytes * width); 319 319 } 320 320 if (vport->dbdata) { … … 322 322 int rline = (y + vport->dboffset) % vport->height; 323 323 int rpos = (rline * vport->width + sx) * 324 screen.pixelbytes;324 screen.pixelbytes; 325 325 memcpy(&vport->dbdata[rpos], tmpline, 326 screen.pixelbytes * width);326 screen.pixelbytes * width); 327 327 } 328 328 } … … 335 335 { 336 336 draw_rectangle(vport, 0, 0, vport->width, vport->height, 337 vport->style.bg_color);337 vport->style.bg_color); 338 338 } 339 339 … … 351 351 for (y = vport->y; y < vport->y+vport->height - lines; y++) 352 352 memcpy(&screen.fbaddress[POINTPOS(vport->x,y)], 353 &screen.fbaddress[POINTPOS(vport->x,y + lines)],354 screen.pixelbytes * vport->width);353 &screen.fbaddress[POINTPOS(vport->x,y + lines)], 354 screen.pixelbytes * vport->width); 355 355 draw_rectangle(vport, 0, vport->height - lines, vport->width, 356 lines, vport->style.bg_color);356 lines, vport->style.bg_color); 357 357 } else if (lines < 0) { 358 358 lines = -lines; 359 for (y = vport->y + vport->height-1; y >= vport->y + lines; 360 y--) 359 for (y = vport->y + vport->height-1; y >= vport->y + lines; y--) 361 360 memcpy(&screen.fbaddress[POINTPOS(vport->x,y)], 362 &screen.fbaddress[POINTPOS(vport->x,y - lines)],363 screen.pixelbytes * vport->width);361 &screen.fbaddress[POINTPOS(vport->x,y - lines)], 362 screen.pixelbytes * vport->width); 364 363 draw_rectangle(vport, 0, 0, vport->width, lines, 365 vport->style.bg_color);364 vport->style.bg_color); 366 365 } 367 366 } … … 381 380 382 381 memcpy(&screen.fbaddress[POINTPOS(dstx,dsty)], 383 &vport->dbdata[srcoff], 384 vport->width*screen.pixelbytes); 382 &vport->dbdata[srcoff], vport->width * screen.pixelbytes); 385 383 } 386 384 } … … 393 391 if (lines > 0) { 394 392 draw_rectangle(vport, 0, 0, vport->width, lines, 395 vport->style.bg_color);393 vport->style.bg_color); 396 394 vport->dboffset += lines; 397 395 vport->dboffset %= vport->height; 398 396 } else if (lines < 0) { 399 397 lines = -lines; 400 draw_rectangle(vport, 0, vport->height-lines, 401 vport->width, lines, 402 vport->style.bg_color); 398 draw_rectangle(vport, 0, vport->height-lines, vport->width, 399 lines, vport->style.bg_color); 403 400 404 401 if (vport->dboffset < lines) … … 442 439 */ 443 440 static void 444 draw_glyph(viewport_t *vport,uint8_t glyph, unsigned int sx, 445 unsigned int sy,style_t style, int transparent)441 draw_glyph(viewport_t *vport,uint8_t glyph, unsigned int sx, unsigned int sy, 442 style_t style, int transparent) 446 443 { 447 444 int i; … … 453 450 for (i = 0; i < 8; i++) { 454 451 if (glline & (1 << (7 - i))) 455 putpixel(vport, sx + i, sy + y, 456 style.fg_color); 452 putpixel(vport, sx + i, sy + y, style.fg_color); 457 453 else if (!transparent) 458 putpixel(vport, sx + i, sy + y, 459 style.bg_color); 454 putpixel(vport, sx + i, sy + y, style.bg_color); 460 455 } 461 456 } … … 472 467 for (y = 0; y < FONT_SCANLINES; y++) 473 468 invert_pixel(vport, col * COL_WIDTH + x, row * 474 FONT_SCANLINES + y);469 FONT_SCANLINES + y); 475 470 } 476 471 … … 631 626 632 627 draw_glyph(vport, c, col * COL_WIDTH, row * FONT_SCANLINES, style, 633 transparent);628 transparent); 634 629 635 630 vport->cur_col = col; … … 660 655 for (i = 0; i < vport->cols * vport->rows; i++) { 661 656 if (data[i].character == ' ' && style_same(data[i].style, 662 vport->style))657 vport->style)) 663 658 continue; 664 659 col = i % vport->cols; 665 660 row = i / vport->cols; 666 661 draw_glyph(vport, data[i].character, col * COL_WIDTH, row * 667 FONT_SCANLINES,data[i].style,668 style_same(data[i].style,vport->style));662 FONT_SCANLINES, data[i].style, style_same(data[i].style, 663 vport->style)); 669 664 } 670 665 cursor_print(vport); … … 712 707 713 708 ppm_draw(shm, size, 0, 0, pmap->width, pmap->height, 714 (putpixel_cb_t)putpixel_pixmap, (void *)pm);709 (putpixel_cb_t)putpixel_pixmap, (void *)pm); 715 710 716 711 return pm; … … 758 753 void *dest = as_get_mappable_page(IPC_GET_ARG2(*call)); 759 754 shm_size = IPC_GET_ARG2(*call); 760 if (!ipc_answer_ fast(callid, 0, (sysarg_t) dest, 0))755 if (!ipc_answer_1(callid, EOK, (sysarg_t) dest)) 761 756 shm = dest; 762 757 else … … 806 801 807 802 ppm_draw(shm, shm_size, IPC_GET_ARG1(*call), 808 IPC_GET_ARG2(*call), vport->width - x,809 vport->height - y,(putpixel_cb_t)putpixel, vport);803 IPC_GET_ARG2(*call), vport->width - x, vport->height - y, 804 (putpixel_cb_t)putpixel, vport); 810 805 break; 811 806 case FB_DRAW_TEXT_DATA: … … 815 810 } 816 811 if (intersize < vport->cols * vport->rows * 817 sizeof(*interbuffer)) {812 sizeof(*interbuffer)) { 818 813 retval = EINVAL; 819 814 break; … … 826 821 827 822 if (handled) 828 ipc_answer_ fast(callid, retval, 0, 0);823 ipc_answer_0(callid, retval); 829 824 return handled; 830 825 } … … 852 847 for (y = 0; y < realheight; y++) { 853 848 tmp = (vport->y + y) * screen.scanline + 854 vport->x * screen.pixelbytes;849 vport->x * screen.pixelbytes; 855 850 memcpy(pmap->data + srcrowsize * y, screen.fbaddress + tmp, 856 realrowsize);851 realrowsize); 857 852 } 858 853 } … … 913 908 for (y = 0; y < realheight; y++) { 914 909 tmp = (vport->y + y) * screen.scanline + 915 vport->x * screen.pixelbytes;910 vport->x * screen.pixelbytes; 916 911 memcpy(screen.fbaddress + tmp, pmap->data + y * srcrowsize, 917 realrowsize);912 realrowsize); 918 913 } 919 914 return 0; … … 934 929 for (i = 0; i < MAX_ANIMATIONS; i++) { 935 930 if (!animations[i].animlen || !animations[i].initialized || 936 !animations[i].enabled)931 !animations[i].enabled) 937 932 continue; 938 933 draw_pixmap(animations[i].vp, 939 animations[i].pixmaps[animations[i].pos]);934 animations[i].pixmaps[animations[i].pos]); 940 935 animations[i].pos = (animations[i].pos + 1) % 941 animations[i].animlen;936 animations[i].animlen; 942 937 } 943 938 } … … 963 958 if (pointer_vport == -1) { 964 959 pointer_vport = viewport_create(pointer_x, pointer_y, 965 pointer_width, pointer_height);960 pointer_width, pointer_height); 966 961 if (pointer_vport < 0) 967 962 return; … … 975 970 else 976 971 copy_vp_to_pixmap(&viewports[pointer_vport], 977 &pixmaps[pointer_pixmap]);972 &pixmaps[pointer_pixmap]); 978 973 979 974 /* Draw cursor */ … … 982 977 bytepos = i * ((pointer_width - 1) / 8 + 1) + j / 8; 983 978 visibility = pointer_mask_bits[bytepos] & 984 (1 << (j % 8));979 (1 << (j % 8)); 985 980 if (visibility) { 986 color = pointer_bits[bytepos] & (1 << (j % 8))987 ? 0 : 0xffffff;981 color = pointer_bits[bytepos] & 982 (1 << (j % 8)) ? 0 : 0xffffff; 988 983 if (pointer_x + j < screen.xres && pointer_y + 989 i < screen.yres)984 i < screen.yres) 990 985 putpixel(&viewports[0], pointer_x + j, 991 pointer_y + i, color);986 pointer_y + i, color); 992 987 } 993 988 } … … 1107 1102 } 1108 1103 if (handled) 1109 ipc_answer_ fast(callid, retval, 0, 0);1104 ipc_answer_0(callid, retval); 1110 1105 return handled; 1111 1106 } … … 1158 1153 1159 1154 if (handled) 1160 ipc_answer_ fast(callid, retval, 0, 0);1155 ipc_answer_0(callid, retval); 1161 1156 return handled; 1162 1157 … … 1180 1175 1181 1176 if (client_connected) { 1182 ipc_answer_ fast(iid, ELIMIT, 0,0);1177 ipc_answer_0(iid, ELIMIT); 1183 1178 return; 1184 1179 } 1185 1180 client_connected = 1; 1186 ipc_answer_ fast(iid, 0, 0, 0); /* Accept connection */1181 ipc_answer_0(iid, EOK); /* Accept connection */ 1187 1182 1188 1183 while (1) { … … 1223 1218 break; 1224 1219 } 1225 ipc_answer_ fast(callid, 0, 0, 0);1220 ipc_answer_0(callid, EOK); 1226 1221 1227 1222 draw_char(vport, c, row, col, vport->style, 1228 IPC_GET_METHOD(call) == FB_TRANS_PUTCHAR);1223 IPC_GET_METHOD(call) == FB_TRANS_PUTCHAR); 1229 1224 continue; /* msg already answered */ 1230 1225 case FB_CLEAR: … … 1253 1248 break; 1254 1249 case FB_GET_CSIZE: 1255 ipc_answer_ fast(callid, 0, vport->rows, vport->cols);1250 ipc_answer_2(callid, EOK, vport->rows, vport->cols); 1256 1251 continue; 1257 1252 case FB_SCROLL: … … 1275 1270 break; 1276 1271 } 1277 if (! viewports[i].initialized ) {1272 if (!viewports[i].initialized ) { 1278 1273 retval = EADDRNOTAVAIL; 1279 1274 break; … … 1281 1276 viewports[i].dboffset = 0; 1282 1277 if (IPC_GET_ARG2(call) == 1 && !viewports[i].dbdata) 1283 viewports[i].dbdata = malloc(screen.pixelbytes1284 * viewports[i].width*1285 viewports[i].height);1278 viewports[i].dbdata = 1279 malloc(screen.pixelbytes * 1280 viewports[i].width * viewports[i].height); 1286 1281 else if (IPC_GET_ARG2(call) == 0 && 1287 viewports[i].dbdata) {1282 viewports[i].dbdata) { 1288 1283 free(viewports[i].dbdata); 1289 1284 viewports[i].dbdata = NULL; … … 1309 1304 case FB_VIEWPORT_CREATE: 1310 1305 retval = viewport_create(IPC_GET_ARG1(call) >> 16, 1311 IPC_GET_ARG1(call) & 0xffff,1312 IPC_GET_ARG2(call) >> 16,1313 IPC_GET_ARG2(call) & 0xffff);1306 IPC_GET_ARG1(call) & 0xffff, 1307 IPC_GET_ARG2(call) >> 16, 1308 IPC_GET_ARG2(call) & 0xffff); 1314 1309 break; 1315 1310 case FB_VIEWPORT_DELETE: … … 1336 1331 break; 1337 1332 case FB_GET_RESOLUTION: 1338 ipc_answer_ fast(callid, 0, screen.xres,screen.yres);1333 ipc_answer_2(callid, EOK, screen.xres, screen.yres); 1339 1334 continue; 1340 1335 case FB_POINTER_MOVE: … … 1346 1341 retval = ENOENT; 1347 1342 } 1348 ipc_answer_ fast(callid,retval, 0, 0);1343 ipc_answer_0(callid, retval); 1349 1344 } 1350 1345 } … … 1376 1371 1377 1372 physmem_map(fb_ph_addr, fb_addr, ALIGN_UP(asz, PAGE_SIZE) >> 1378 PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE);1373 PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE); 1379 1374 1380 1375 if (screen_init(fb_addr, fb_width, fb_height, fb_scanline, fb_visual, 1381 fb_invert_colors))1376 fb_invert_colors)) 1382 1377 return 0; 1383 1378 -
uspace/srv/fb/main.c
r3209923 rb74959bd 45 45 46 46 dest = as_get_mappable_page(IPC_GET_ARG2(*call)); 47 if (ipc_answer_ fast(callid, 0, (sysarg_t) dest, 0) == 0) {47 if (ipc_answer_1(callid, EOK, (sysarg_t) dest) == 0) { 48 48 if (*area) 49 49 as_area_destroy(*area); -
uspace/srv/fb/sysio.c
r3209923 rb74959bd 118 118 119 119 if (client_connected) { 120 ipc_answer_ fast(iid, ELIMIT, 0,0);120 ipc_answer_0(iid, ELIMIT); 121 121 return; 122 122 } 123 123 124 124 client_connected = 1; 125 ipc_answer_ fast(iid, 0, 0, 0); /* Accept connection */125 ipc_answer_0(iid, EOK); /* Accept connection */ 126 126 while (1) { 127 127 callid = async_get_call(&call); 128 128 switch (IPC_GET_METHOD(call)) { 129 case IPC_M_PHONE_HUNGUP: 130 client_connected = 0; 131 ipc_answer_fast(callid, 0, 0, 0); 132 return; /* Exit thread */ 133 case FB_PUTCHAR: 134 c = IPC_GET_ARG1(call); 135 newrow = IPC_GET_ARG2(call); 136 newcol = IPC_GET_ARG3(call); 137 if ((lastcol != newcol) || (lastrow != newrow)) 138 curs_goto(newrow, newcol); 139 lastcol = newcol + 1; 140 lastrow = newrow; 141 sysput(c); 142 retval = 0; 129 case IPC_M_PHONE_HUNGUP: 130 client_connected = 0; 131 ipc_answer_0(callid, EOK); 132 return; /* Exit thread */ 133 case FB_PUTCHAR: 134 c = IPC_GET_ARG1(call); 135 newrow = IPC_GET_ARG2(call); 136 newcol = IPC_GET_ARG3(call); 137 if ((lastcol != newcol) || (lastrow != newrow)) 138 curs_goto(newrow, newcol); 139 lastcol = newcol + 1; 140 lastrow = newrow; 141 sysput(c); 142 retval = 0; 143 break; 144 case FB_CURSOR_GOTO: 145 newrow = IPC_GET_ARG1(call); 146 newcol = IPC_GET_ARG2(call); 147 curs_goto(newrow, newcol); 148 lastrow = newrow; 149 lastcol = newcol; 150 retval = 0; 151 break; 152 case FB_GET_CSIZE: 153 ipc_answer_2(callid, EOK, HEIGHT, WIDTH); 154 continue; 155 case FB_CLEAR: 156 clrscr(); 157 retval = 0; 158 break; 159 case FB_SET_STYLE: 160 fgcolor = IPC_GET_ARG1(call); 161 bgcolor = IPC_GET_ARG2(call); 162 if (fgcolor < bgcolor) 163 set_style(0); 164 else 165 set_style(7); 166 retval = 0; 167 break; 168 case FB_SCROLL: 169 i = IPC_GET_ARG1(call); 170 if ((i > HEIGHT) || (i < -HEIGHT)) { 171 retval = EINVAL; 143 172 break; 144 case FB_CURSOR_GOTO: 145 newrow = IPC_GET_ARG1(call); 146 newcol = IPC_GET_ARG2(call); 147 curs_goto(newrow, newcol); 148 lastrow = newrow; 149 lastcol = newcol; 150 retval = 0; 151 break; 152 case FB_GET_CSIZE: 153 ipc_answer_fast(callid, 0, HEIGHT, WIDTH); 154 continue; 155 case FB_CLEAR: 156 clrscr(); 157 retval = 0; 158 break; 159 case FB_SET_STYLE: 160 fgcolor = IPC_GET_ARG1(call); 161 bgcolor = IPC_GET_ARG2(call); 162 if (fgcolor < bgcolor) 163 set_style(0); 164 else 165 set_style(7); 166 retval = 0; 167 break; 168 case FB_SCROLL: 169 i = IPC_GET_ARG1(call); 170 if ((i > HEIGHT) || (i < -HEIGHT)) { 171 retval = EINVAL; 172 break; 173 } 174 scroll(i); 175 curs_goto(lastrow, lastcol); 176 retval = 0; 177 break; 178 default: 179 retval = ENOENT; 173 } 174 scroll(i); 175 curs_goto(lastrow, lastcol); 176 retval = 0; 177 break; 178 default: 179 retval = ENOENT; 180 180 } 181 181 182 ipc_answer_ fast(callid, retval, 0, 0);182 ipc_answer_0(callid, retval); 183 183 } 184 184 }
Note:
See TracChangeset
for help on using the changeset viewer.
