📄 svgalib.c
字号:
{ memcpy(&dev->clip, r, sizeof(struct rect)); if (dev->clip.x1>=dev->clip.x2||dev->clip.y2<=dev->clip.y1||dev->clip.y2<=0||dev->clip.x2<=0||dev->clip.x1>=xsize ||dev->clip.y1>=ysize){ /* Empty region */ dev->clip.x1=dev->clip.x2=dev->clip.y1=dev->clip.y2=0; }else{ if (dev->clip.x1<0) dev->clip.x1=0; if (dev->clip.x2>xsize) dev->clip.x2=xsize; if (dev->clip.y1<0) dev->clip.y1=0; if (dev->clip.y2>ysize) dev->clip.y2=ysize; }}/* For modes where video memory is not directly accessible through svgalib */static inline void fill_area_drawscansegment(struct graphics_device *dev, int left, int top, int right, int bottom, long color){ int xs; int col=*(unsigned char *)&color; FILL_CLIP_PREFACE SYNC xs=right-left; memset(scroll_buffer,col,xs); for (;top<bottom;top++){ vga_drawscansegment(scroll_buffer,left,top,xs); } END_MOUSE}/* Emulates horizontal line by calling fill_area */static void draw_hline_fill_area(struct graphics_device *dev, int left, int y, int right, long color){ dev->drv->fill_area(dev,left,y,right,y+1,color);}/* Emulates vline by fill_area */static void draw_vline_fill_area(struct graphics_device *dev, int x, int top, int bottom, long color){ dev->drv->fill_area(dev,x,top,x+1,bottom, color);}/* This does no clipping and is used only by the mouse code * length is in bytes, not in pixels */static int drawscansegment_linear(unsigned char *colors, int x, int y, int length){ unsigned char *ptr=my_graph_mem+vga_linewidth*y+vga_bytes*x; memcpy (ptr,colors,length); return 0;}/* This does no clipping and is used only by the mouse code * length is in bytes, not in pixels */static int getscansegment_linear(unsigned char *colors, int x, int y, int length){ unsigned char *ptr=my_graph_mem+vga_linewidth*y+vga_bytes*x; memcpy (colors, ptr, length); return 0;}/* This does no clipping and is used only by the mouse code * length is in bytes, not in pixels */static int drawscansegment_paged(unsigned char *colors, int x, int y, int length){ int lina=vga_linewidth*y+vga_bytes*x; paged_memcpy(lina, colors, length); return 0;}/* This does no clipping and is used only by the mouse code * length is in the bytes, not in pixels */static int getscansegment_paged(unsigned char *colors, int x, int y, int length){ int lina=vga_linewidth*y+vga_bytes*x; get_row(colors, lina, length); return 0;}static void svga_draw_bitmaps(struct graphics_device *dev, struct bitmap **hndls, int n ,int x, int y){ void (*draw_b)(struct graphics_device *, struct bitmap *, int, int); TEST_INACTIVITY if (x>=xsize||y>ysize) return; while(x+(*hndls)->x<=0&&n){ x+=(*hndls)->x; n--; hndls++; } draw_b = dev->drv->draw_bitmap; while(n&&x<=xsize){ draw_b(dev, *hndls, x, y); x+=(*hndls)->x; n--; hndls++; } }static void alloc_scroll_buffer(void){ if (!scroll_buffer) { if ((unsigned)xsize > (unsigned)MAXINT / bmpixelsize) overalloc(); scroll_buffer=mem_alloc(xsize*bmpixelsize); }}static void setup_functions(void){ if (accel_avail&ACCELFLAG_SETMODE){ do_sync=1; vga_accel(ACCEL_SETMODE, BLITS_IN_BACKGROUND); }else do_sync=0; svga_driver.get_color=get_color_fn(svga_driver.depth); if (!svga_driver.get_color) internal("Unknown bit depth %x", svga_driver.depth); switch(vga_colors){ case 2: internal( "2-color modes are not supported by\ links as they are buggy in svgalib and incapable of colors"); case 16: alloc_scroll_buffer(); svga_driver.draw_bitmap=draw_bitmap_drawscansegment; svga_driver.hscroll=hscroll_scansegment; svga_driver.vscroll=vscroll_scansegment; svga_driver.flags |= GD_DONT_USE_SCROLL; svga_driver.fill_area=fill_area_drawscansegment; svga_driver.draw_hline=draw_hline_fill_area; svga_driver.draw_vline=draw_vline_fill_area; mouse_getscansegment=vga_getscansegment; mouse_drawscansegment=vga_drawscansegment; break; default: mouse_getscansegment=vga_getscansegment; mouse_drawscansegment=vga_drawscansegment; if (accel_avail&ACCELFLAG_PUTIMAGE){ svga_driver.draw_bitmap=draw_bitmap_accel; }else if (vga_linear){ svga_driver.draw_bitmap=draw_bitmap_linear; }else if (mode_x){ svga_driver.draw_bitmap=draw_bitmap_drawscansegment; }else{ svga_driver.draw_bitmap=draw_bitmap_paged; } if (accel_avail&ACCELFLAG_FILLBOX) svga_driver.fill_area=fill_area_accel_box; else if (accel_avail&ACCELFLAG_DRAWLINE) svga_driver.fill_area=fill_area_accel_lines; else if (vga_linear) svga_driver.fill_area=fill_area_linear; else if (mode_x) svga_driver.fill_area=fill_area_drawscansegment; else svga_driver.fill_area=fill_area_paged; if (accel_avail&ACCELFLAG_DRAWLINE){ svga_driver.draw_hline=draw_hline_accel_line; svga_driver.draw_vline=draw_vline_accel_line; }else if (accel_avail&ACCELFLAG_FILLBOX){ svga_driver.draw_hline=draw_hline_accel_box; svga_driver.draw_vline=draw_vline_accel_box; }else if (vga_linear){ svga_driver.draw_hline=draw_hline_linear; svga_driver.draw_vline=draw_vline_linear; }else if (mode_x){ svga_driver.draw_hline=draw_hline_fill_area; svga_driver.draw_vline=draw_vline_fill_area; }else{ /* Paged memory access */ svga_driver.draw_hline=draw_hline_paged; switch(vga_bytes) { case 1: svga_driver.draw_vline=draw_vline_paged_1; break;#ifdef t2c case 2: svga_driver.draw_vline=draw_vline_paged_2; break;#endif /* #ifdef t2c */#ifdef t4c case 4: svga_driver.draw_vline=draw_vline_paged_4; break;#endif /* #ifdef t4c */ default: if (vga_bytes&(vga_bytes-1)) svga_driver.draw_vline=draw_vline_paged; else svga_driver.draw_vline=draw_vline_paged_aligned; break; } } if (vga_colors>=256){ if (vga_linear){ mouse_drawscansegment=drawscansegment_linear; mouse_getscansegment=getscansegment_linear; }else if (!mode_x){ mouse_drawscansegment=drawscansegment_paged; mouse_getscansegment=getscansegment_paged; } } if (accel_avail&ACCELFLAG_SCREENCOPY){ svga_driver.hscroll=hscroll_accel; svga_driver.vscroll=vscroll_accel; }else if (vga_linear){ svga_driver.hscroll=hscroll_linear; svga_driver.vscroll=vscroll_linear; svga_driver.flags |= GD_DONT_USE_SCROLL; }else if (mode_x){ alloc_scroll_buffer(); svga_driver.hscroll=hscroll_scansegment; svga_driver.vscroll=vscroll_scansegment; svga_driver.flags |= GD_DONT_USE_SCROLL; }else{ alloc_scroll_buffer(); svga_driver.hscroll=hscroll_paged; svga_driver.vscroll=vscroll_paged; svga_driver.flags |= GD_DONT_USE_SCROLL; } }}#if 0void dump_mode_info_into_file(vga_modeinfo* i){ FILE *f; f=fopen(".links_svga_modeinfo","w"); if (!f) return; fprintf(f,"Resolution %d*%d\n",i->width,i->height); fprintf(f,"%d bytes per screen pixel\n",i->bytesperpixel); fprintf(f,"%d colors\n",i->colors); fprintf(f,"Linewidth %d bytes\n",i->linewidth); fprintf(f,"Maximum logical width %d bytes\n",i->maxlogicalwidth); fprintf(f,"Start address rangemask 0x%x\n",i->startaddressrange); fprintf(f,"Max. pixels per logical screen %d\n",i->maxpixels); fprintf(f,"bitblt %s\n",i->haveblit&HAVE_BITBLIT?"yes":"no"); fprintf(f,"fillblt %s\n",i->haveblit&HAVE_FILLBLIT?"yes":"no"); fprintf(f,"imageblt %s\n",i->haveblit&HAVE_IMAGEBLIT?"yes":"no"); fprintf(f,"hlinelistblt %s\n",i->haveblit&HAVE_HLINELISTBLIT?"yes":"no"); fprintf(f,"read/write page %s\n",i->flags&HAVE_RWPAGE?"yes":"no"); fprintf(f,"Interlaced %s\n",i->flags&IS_INTERLACED?"yes":"no"); fprintf(f,"Mode X layout %s\n",i->flags&IS_MODEX?"yes":"no"); fprintf(f,"Dynamically loaded %s\n",i->flags&IS_DYNAMICMODE?"yes":"no"); fprintf(f,"Linear: %s\n",vga_linear?"yes":"no"); fprintf(f,"Misordered %s\n",i->flags&RGB_MISORDERED?"yes":"no"); if (!i->flags&EXT_INFO_AVAILABLE){ fprintf(f,"Old svgalib, extended info is not available\n"); }else{ fprintf(f,"Chiptype 0x%x\n",i->chiptype); fprintf(f,"Memory %dKB\n",i->memory); fprintf(f,"Linewidth Unit %d\n",i->linewidth_unit); fprintf(f,"Aperture size %d\n",i->aperture_size); } fprintf(f,"Accelerated putimage: %s\n",svga_driver.draw_bitmap==draw_bitmap_accel?"yes":"no"); fclose(f);}#endifstatic void svgalib_key_in(void *p, struct event *ev, int size){ if (size != sizeof(struct event) || ev->ev != EV_KBD) return; if ((ev->y & KBD_ALT) && ev->x >= '0' && ev->x <= '9') { switch_virtual_device((ev->x - '1' + 10) % 10); return; } if (svga_driver.codepage!=utf8_table&&(ev->x)>=128&&(ev->x)<=255) if ((ev->x=cp2u(ev->x,svga_driver.codepage)) == -1) return; if (current_virtual_device && current_virtual_device->keyboard_handler) current_virtual_device->keyboard_handler(current_virtual_device, ev->x, ev->y);}#ifndef MOUSE_FOURTHBUTTON#define MOUSE_FOURTHBUTTON 0#endif#ifndef MOUSE_FIFTHBUTTON#define MOUSE_FIFTHBUTTON 0#endif#ifndef MOUSE_SIXTHBUTTON#define MOUSE_SIXTHBUTTON 0#endif#define BUTTON_MASK (MOUSE_RIGHTBUTTON | MOUSE_MIDDLEBUTTON | MOUSE_LEFTBUTTON | MOUSE_FOURTHBUTTON | MOUSE_FIFTHBUTTON /*| MOUSE_SIXTHBUTTON*/)static inline void mouse_aggregate_flush(void){ if (!mouse_aggregate_flag) return; mouse_aggregate_flag=0; if (!current_virtual_device) return; if (!current_virtual_device->mouse_handler) return; current_virtual_device->mouse_handler(current_virtual_device, mouse_x, mouse_y, mouse_aggregate_action);}/* Only calls appropriate callbacks, doesn't draw anything. */static void mouse_event_handler(int button, int dx, int dy, int dz, int drx, int dry, int drz){ int moved,old_mouse_x,old_mouse_y; void (*mh)(struct graphics_device *, int, int, int); struct graphics_device *cd=current_virtual_device; mh=cd?cd->mouse_handler:NULL; old_mouse_x=mouse_x; old_mouse_y=mouse_y; mouse_x+=dx; if (mouse_x>=xsize) mouse_x=xsize-1; else if (mouse_x<0) mouse_x=0; mouse_y+=dy; if (mouse_y>=ysize) mouse_y=ysize-1; else if (mouse_y<0) mouse_y=0; redraw_mouse(); moved=(old_mouse_x!=mouse_x||old_mouse_y!=mouse_y); /* Test movement without buttons */ if (!(mouse_buttons & BUTTON_MASK) && moved) { mouse_aggregate_flag=1; mouse_aggregate_action=B_MOVE; } /* Test presses */ if ((button&MOUSE_LEFTBUTTON)&&!(mouse_buttons&MOUSE_LEFTBUTTON)){ mouse_aggregate_flush(); if (mh) mh(cd,mouse_x, mouse_y,B_LEFT|B_DOWN); } if ((button&MOUSE_MIDDLEBUTTON)&&!(mouse_buttons&MOUSE_MIDDLEBUTTON)){ mouse_aggregate_flush(); if (mh) mh(cd,mouse_x, mouse_y,B_MIDDLE|B_DOWN); } if ((button&MOUSE_RIGHTBUTTON)&&!(mouse_buttons&MOUSE_RIGHTBUTTON)){ mouse_aggregate_flush(); if (mh) mh(cd,mouse_x, mouse_y,B_RIGHT|B_DOWN); } if ((button&MOUSE_FOURTHBUTTON)&&!(mouse_buttons&MOUSE_FOURTHBUTTON)){ mouse_aggregate_flush(); if (mh) mh(cd,mouse_x, mouse_y,B_RIGHT|B_FOURTH); } if ((button&MOUSE_FIFTHBUTTON)&&!(mouse_buttons&MOUSE_FIFTHBUTTON)){ mouse_aggregate_flush(); if (mh) mh(cd,mouse_x, mouse_y,B_RIGHT|B_FIFTH); } if ((button&MOUSE_SIXTHBUTTON)&&!(mouse_buttons&MOUSE_SIXTHBUTTON)){ mouse_aggregate_flush(); /*if (mh) mh(cd,mouse_x, mouse_y,B_RIGHT|B_SIXTH);*/ switch_virtual_device(VD_NEXT); } /* Test releases */ if (!(button&MOUSE_LEFTBUTTON)&&(mouse_buttons&MOUSE_LEFTBUTTON)){ mouse_aggregate_flush(); if (mh) mh(cd,mouse_x, mouse_y,B_LEFT|B_UP); } if (!(button&MOUSE_MIDDLEBUTTON)&&(mouse_buttons&MOUSE_MIDDLEBUTTON)){ mouse_aggregate_flush(); if (mh) mh(cd,mouse_x, mouse_y,B_MIDDLE|B_UP); } if (!(button&MOUSE_RIGHTBUTTON)&&(mouse_buttons&MOUSE_RIGHTBUTTON)){ mouse_aggregate_flush(); if (mh) mh(cd,mouse_x, mouse_y,B_RIGHT|B_UP); } if (!(button&MOUSE_FOURTHBUTTON)&&(mouse_buttons&MOUSE_FOURTHBUTTON)){ mouse_aggregate_flush(); if (mh) mh(cd,mouse_x, mouse_y,B_FOURTH|B_UP); } if (!(button&MOUSE_FIFTHBUTTON)&&(mouse_buttons&MOUSE_FIFTHBUTTON)){ mouse_aggregate_flush(); if (mh) mh(cd,mouse_x, mouse_y,B_FIFTH|B_UP); } if (!(button&MOUSE_SIXTHBUTTON)&&(mouse_buttons&MOUSE_SIXTHBUTTON)){ mouse_aggregate_flush(); /*if (mh) mh(cd,mouse_x, mouse_y,B_SIXTH|B_UP);*/ } if (drx < 0 && mh) mh(cd, mouse_x, mouse_y, B_MOVE | B_WHEELUP); if (drx > 0 && mh) mh(cd, mouse_x, mouse_y, B_MOVE | B_WHEELDOWN); if (dry < 0 && mh) mh(cd, mouse_x, mouse_y, B_MOVE | B_WHEELLEFT); if (dry > 0 && mh) mh(cd, mouse_x, mouse_y, B_MOVE | B_WHEELRIGHT); /* Test drag */ if (! ((button^mouse_buttons) & BUTTON_MASK ) && moved && (button & BUTTON_MASK)){ mouse_aggregate_flag=1; mouse_aggregate_action=( button&MOUSE_LEFTBUTTON?B_LEFT: button&MOUSE_RIGHTBUTTON?B_RIGHT: button&MOUSE_MIDDLEBUTTON?B_MIDDLE: button&MOUSE_FOURTHBUTTON?B_FOURTH: button&MOUSE_FIFTHBUTTON?B_FIFTH: /*button&MOUSE_SIXTHBUTTON?B_SIXTH:*/ 0) | B_DRAG; } mouse_buttons=button;}#undef BUTTON_MASK/* Flushes the background_buffer onscreen where it was originally taken from. */static void place_mouse_background(void){ struct bitmap bmp; bmp.x=arrow_width; bmp.y=arrow_height; bmp.skip=arrow_width*bmpixelsize; bmp.data=background_buffer; { struct graphics_device * current_virtual_device_backup; current_virtual_device_backup=current_virtual_device; current_virtual_device=mouse_graphics_device; svga_driver.draw_bitmap(mouse_graphics_device, &bmp, background_x, background_y); current_virtual_device=current_virtual_device_backup; }}/* Only when the old and new mouse don't interfere. Using it on interfering mouses would * cause a flicker. */static void hide_mouse(void){ global_mouse_hidden=1; place_mouse_background();}/* Gets background from the screen (clipping provided only right and bottom) to the * passed buffer. */static void get_mouse_background(unsigned char *buffer_ptr){ int width,height,skip,x,y; skip=arrow_width*bmpixelsize; x=mouse_x; y=mouse_y; width=bmpixelsize*(arrow_width+x>xsize?xsize-x:arrow_width); height=arrow_height+y>ysize?ysize-y:arrow_height; SYNC for (;height;height--){ mouse_getscansegment(buffer_ptr,x,y,width); buffer_ptr+=skip; y++; }}/* Overlays the arrow's image over the mouse_buffer * Doesn't draw anything into the screen */static void render_mouse_arrow(void){ int x,y, reg0, reg1; unsigned char *mouse_ptr=mouse_buffer; int *arrow_ptr=arrow; for (y=arrow_height;y;y--){ reg0=*arrow_ptr; reg1=arrow_ptr[1]; arrow_ptr+=2; for (x=arrow_width;x;) { int mask=1<<(--x); if (reg0&mask) memcpy (mouse_ptr, &mouse_black, bmpixelsize); else if (reg1&mask) memcpy (mouse_ptr, &mouse_white, bmpixelsize); mouse_ptr+=bmpixelsize; } }}static void place_mouse(void){ struct bitmap bmp; bmp.x=arrow_width; bmp.y=arrow_height; bmp.skip=arrow_width*bmpixelsize; bmp.data=mouse_buffer; { struct graphics_device * current_graphics_device_backup; current_graphics_device_backup=current_virtual_device; current_virtual_device=mouse_graphics_device; /* We do need to worry about SYNC because draw_bitmap already * does it (if necessary) */ svga_driver.draw_bitmap(mouse_graphics_device, &bmp, mouse_x, mouse_y); current_virtual_device=current_graphics_device_backup; } global_mouse_hidden=0;}/* Only when the old and the new mouse positions do not interfere. Using this routine * on interfering positions would cause a flicker.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -