📄 svgalib.c
字号:
*/static void show_mouse(void){ get_mouse_background(background_buffer); background_x=mouse_x; background_y=mouse_y; memcpy(mouse_buffer,background_buffer,bmpixelsize*arrow_area); render_mouse_arrow(); place_mouse();}/* Doesn't draw anything into the screen */static void put_and_clip_background_buffer_over_mouse_buffer(void){ unsigned char *bbufptr=background_buffer, *mbufptr=mouse_buffer; int left=background_x-mouse_x; int top=background_y-mouse_y; int right,bottom; int bmpixelsizeL=bmpixelsize; int number_of_bytes; int byte_skip; right=left+arrow_width; bottom=top+arrow_height; if (left<0){ bbufptr-=left*bmpixelsizeL; left=0; } if (right>arrow_width) right=arrow_width; if (top<0){ bbufptr-=top*bmpixelsizeL*arrow_width; top=0; } if (bottom>arrow_height) bottom=arrow_height; mbufptr+=bmpixelsizeL*(left+arrow_width*top); byte_skip=arrow_width*bmpixelsizeL; number_of_bytes=bmpixelsizeL*(right-left); for (;top<bottom;top++){ memcpy(mbufptr,bbufptr,number_of_bytes); mbufptr+=byte_skip; bbufptr+=byte_skip; }}/* This draws both the contents of background_buffer and mouse_buffer in a scan * way (left-right, top-bottom), so the flicker is reduced. */static inline void place_mouse_composite(void){ int mouse_left=mouse_x; int mouse_top=mouse_y; int background_left=background_x; int background_top=background_y; int mouse_right=mouse_left+arrow_width; int mouse_bottom=mouse_top+arrow_height; int background_right=background_left+arrow_width; int background_bottom=background_top+arrow_height; int skip=arrow_width*bmpixelsize; int background_length,mouse_length; unsigned char *mouse_ptr=mouse_buffer,*background_ptr=background_buffer; int yend; /* First let's sync to the beam - wait for the beginning of vertical retrace * (it would be better to wait for the beginning of the blank, however, * svgalib doesn't provide it as VGA and SVGA cards don't provide it */ /* This will probably not make any good anyway. if (vga_colors>=256) vga_waitretrace(); */ if (mouse_bottom>ysize) mouse_bottom=ysize; if (background_bottom>ysize) background_bottom=ysize; SYNC /* We have to sync because mouse_drawscansegment does not wait for * the accelerator to finish. But we never waste time here because * mouse_drawscansegment is never accelerated. */ /* Let's do the top part */ if (background_top<mouse_top){ /* Draw the background */ background_length=background_right>xsize?xsize-background_left :arrow_width; for (;background_top<mouse_top;background_top++){ mouse_drawscansegment(background_ptr,background_left ,background_top,background_length*bmpixelsize); background_ptr+=skip; } }else if (background_top>mouse_top){ /* Draw the mouse */ mouse_length=mouse_right>xsize ?xsize-mouse_left:arrow_width; for (;mouse_top<background_top;mouse_top++){ mouse_drawscansegment(mouse_ptr,mouse_left,mouse_top,mouse_length*bmpixelsize); mouse_ptr+=skip; } } /* Let's do the middle part */ yend=mouse_bottom<background_bottom?mouse_bottom:background_bottom; if (background_left<mouse_left){ /* Draw background, mouse */ mouse_length=mouse_right>xsize?xsize-mouse_left:arrow_width; for (;mouse_top<yend;mouse_top++){ mouse_drawscansegment(background_ptr,background_left,mouse_top ,(mouse_left-background_left)*bmpixelsize); mouse_drawscansegment(mouse_ptr,mouse_left,mouse_top,mouse_length*bmpixelsize); mouse_ptr+=skip; background_ptr+=skip; } }else{ int l1, l2, l3; /* Draw mouse, background */ mouse_length=mouse_right>xsize?xsize-mouse_left:arrow_width; background_length=background_right-mouse_right; if (background_length+mouse_right>xsize) background_length=xsize-mouse_right; l1=mouse_length*bmpixelsize; l2=(mouse_right-background_left)*bmpixelsize; l3=background_length*bmpixelsize; for (;mouse_top<yend;mouse_top++){ mouse_drawscansegment(mouse_ptr,mouse_left,mouse_top,l1); if (background_length>0) mouse_drawscansegment( background_ptr +l2, mouse_right,mouse_top ,l3); mouse_ptr+=skip; background_ptr+=skip; } } if (background_bottom<mouse_bottom){ /* Count over bottoms! tops will be invalid! */ /* Draw mouse */ mouse_length=mouse_right>xsize?xsize-mouse_left :arrow_width; for (;background_bottom<mouse_bottom;background_bottom++){ mouse_drawscansegment(mouse_ptr,mouse_left,background_bottom ,mouse_length*bmpixelsize); mouse_ptr+=skip; } }else{ /* Draw background */ background_length=background_right>xsize?xsize-background_left :arrow_width; for (;mouse_bottom<background_bottom;mouse_bottom++){ mouse_drawscansegment(background_ptr,background_left,mouse_bottom ,background_length*bmpixelsize); background_ptr+=skip; } }}/* This moves the mouse a sophisticated way when the old and new position of the * cursor overlap. */static inline void redraw_mouse_sophisticated(void){ int new_background_x, new_background_y; get_mouse_background(mouse_buffer); put_and_clip_background_buffer_over_mouse_buffer(); memcpy(new_background_buffer,mouse_buffer,bmpixelsize*arrow_area); new_background_x=mouse_x; new_background_y=mouse_y; render_mouse_arrow(); place_mouse_composite(); memcpy(background_buffer,new_background_buffer,bmpixelsize*arrow_area); background_x=new_background_x; background_y=new_background_y;}static void redraw_mouse(void){ if (flags) return; /* We are not drawing */ if (mouse_x!=background_x||mouse_y!=background_y){ if (RECTANGLES_INTERSECT( background_x, background_x+arrow_width, mouse_x, mouse_x+arrow_width, background_y, background_y+arrow_height, mouse_y, mouse_y+arrow_height)){ redraw_mouse_sophisticated(); }else{ /* Do a normal hide/show */ get_mouse_background(mouse_buffer); memcpy(new_background_buffer, mouse_buffer,arrow_area*bmpixelsize); render_mouse_arrow(); hide_mouse(); place_mouse(); memcpy(background_buffer,new_background_buffer ,arrow_area*bmpixelsize); background_x=mouse_x; background_y=mouse_y; } }}static unsigned char *svga_get_driver_param(void){ return svga_driver_param;}static void generate_palette_outer(void){ if (vga_colors==16||vga_colors==256){ struct irgb *palette; palette=mem_alloc(vga_colors*sizeof(*palette)); generate_palette(palette); set_palette(palette); mem_free(palette); /* Palette in SVGAlib will be always color cube */ }}/* This is to be called after vga_setmode and sets up accelerator, * svgalib functions */static void setup_mode(int mode){ vga_modeinfo *i; int sig; accel_avail=vga_ext_set(VGA_EXT_AVAILABLE,VGA_AVAIL_ACCEL); if (vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_SET)&VGA_CLUT8){ vga_ext_set(VGA_EXT_SET,VGA_CLUT8); palette_depth=8; }else palette_depth=6; i=vga_getmodeinfo(mode); vga_bytes=i->bytesperpixel; bmpixelsize=vga_bytes?vga_bytes:1; vga_misordered=!!(i->flags&RGB_MISORDERED); mode_x=!!(i->flags&IS_MODEX); vga_linear=!!(i->flags&IS_LINEAR); /* if (!vga_linear && i->flags&CAPABLE_LINEAR && 0<=vga_setlinearaddressing()) vga_linear=1; */ my_graph_mem=vga_getgraphmem(); svga_driver.x = xsize=i->width; svga_driver.y = ysize=i->height; aspect_native=(196608*xsize+(ysize<<1))/(ysize<<2); aspect=aspect_native*bfu_aspect+0.5; vga_colors=i->colors; if (xsize==320&&ysize==200&&vga_colors==256) vga_linear=1; /* The mode does not need to page :-) */ vga_linewidth=i->linewidth; if (!vga_linear){ vga_page=-1; } vga_misordered=!!i->flags&RGB_MISORDERED; /*dump_mode_info_into_file(i);*/ svga_driver.depth=0; svga_driver.depth|=vga_misordered<<8; switch (vga_colors){ case 16: sig=4; break; case 256: sig=8; break; case 32768: sig=15; break; case 65536: sig=16; break; case 16777216: sig=24; break; default: sig=0; /* Only to suppress warning */ break; } svga_driver.depth|=sig<<3; svga_driver.depth|=bmpixelsize; /* setup_functions uses depth. */ setup_functions(); generate_palette_outer();}#ifndef __SPAD__static void vtswitch_handler(void * nothing){ int oktowrite; nothing=nothing; vga_unlockvc(); vga_lockvc(); oktowrite=vga_oktowrite(); if (!oktowrite&&!flags){ backup_virtual_device=current_virtual_device; current_virtual_device=NULL; } if (flags==1&&oktowrite) current_virtual_device=backup_virtual_device; flags=(flags&~1)|!oktowrite; svgalib_timer_id=install_timer(100,vtswitch_handler, NULL);}#endifstatic void svga_ctrl_c(struct itrm *i){ kbd_ctrl_c();}/* Param: one string which is to be compared with one from modes. * Copies the svga_driver into gr_driver. * Returns: 0 OK * 1 Passed mode unknown by svga_driver * 2 Passed mode unknown by svgalib * mikulas: Change: Returns: NULL: OK * non-null: poiner to string with error * description, string must be freed */static unsigned char *svga_init_driver(unsigned char *param, unsigned char *display){ int j; kbd_set_raw = 0; vga_init(); svga_driver.flags |= GD_NEED_CODEPAGE; j = 0; svga_driver_param=NULL; if (!param || !*param) goto not_found; svga_driver_param=stracpy(param); for (j=0;(size_t)j<sizeof(modes)/sizeof(*modes);j++) if (!strcasecmp(modes[j].name,param)) goto found; j = 1; not_found: { unsigned char *m = init_str(); int l = 0; int f = 0; if (j) { add_to_str(&m, &l, "Video mode "); add_to_str(&m, &l, param); add_to_str(&m, &l, " not supported by "); add_to_str(&m, &l, j == 2 ? "your video card" : "svgalib"); add_to_str(&m, &l, ".\n"); } else add_to_str(&m, &l, "There is no default video mode.\n"); for (j=0;(size_t)j<sizeof(modes)/sizeof(*modes);j++) if (vga_hasmode(modes[j].number)) { if (f) add_to_str(&m, &l, ", "); else f = 1, add_to_str(&m, &l, "The following modes are supported:\n"); add_to_str(&m, &l, modes[j].name); } if (f) add_to_str(&m, &l, "\nUse -mode switch to set video mode.\n"); else add_to_str(&m, &l, "There are no supported video modes. Links can't run on svgalib.\n"); if(svga_driver_param)mem_free(svga_driver_param),svga_driver_param=NULL; return m; } found: if (!vga_hasmode(modes[j].number)) { j = 2; goto not_found; } if (init_virtual_devices(&svga_driver, NUMBER_OF_DEVICES)) { if(svga_driver_param)mem_free(svga_driver_param),svga_driver_param=NULL; return stracpy("Allocation of virtual devices failed.\n"); } if ((vga_getmousetype()&MOUSE_TYPE_MASK)==MOUSE_NONE) { vga_setmousesupport(0); mouse_works=0; }else{ vga_setmousesupport(1); mouse_works=1; } vga_lockvc();#ifndef __SPAD__ svgalib_timer_id=install_timer(100,vtswitch_handler,NULL); if (vga_runinbackground_version()>=1) vga_runinbackground(1);#endif vga_setmode(vga_mode=modes[j].number); setup_mode(modes[j].number); handle_svgalib_keyboard((void (*)(void *, unsigned char *, int))svgalib_key_in); if (mouse_works){ if ((unsigned)arrow_area > (unsigned)MAXINT / bmpixelsize) overalloc(); mouse_buffer=mem_alloc(bmpixelsize*arrow_area); background_buffer=mem_alloc(bmpixelsize*arrow_area); new_background_buffer=mem_alloc(bmpixelsize*arrow_area); mouse_black=svga_driver.get_color(0); mouse_white=svga_driver.get_color(0xffffff); mouse_graphics_device=svga_driver.init_device(); virtual_devices[0] = NULL; global_mouse_hidden=1; background_x=mouse_x=xsize>>1; background_y=mouse_y=ysize>>1; show_mouse(); mouse_seteventhandler(mouse_event_handler); }else{ global_mouse_hidden=1; /* To ensure hide_mouse and show_mouse will do nothing */ } signal(SIGPIPE, SIG_IGN); signal(SIGTSTP, SIG_IGN); install_signal_handler(SIGINT, (void (*)(void *))svga_ctrl_c, ditrm, 0); return NULL;}/* Return value: 0 alloced on heap * 1 alloced in vidram * 2 alloced in X server shm *//*static int svga_get_filled_bitmap(struct bitmap *dest, long color){ int n; if (dest->x && (unsigned)dest->x * (unsigned)dest->y / (unsigned)dest->x != (unsigned)dest->y) overalloc(); if ((unsigned)dest->x * (unsigned)dest->y > MAXINT / bmpixelsize) overalloc(); n=dest->x*dest->y*bmpixelsize; dest->data=mem_alloc(n); pixel_set(dest->data,n,&color); dest->skip=dest->x*bmpixelsize; dest->flags=0; return 0;}*//* Return value: 0 alloced on heap * 1 alloced in vidram * 2 alloced in X server shm */static int svga_get_empty_bitmap(struct bitmap *dest){ if (dest->x && (unsigned)dest->x * (unsigned)dest->y / (unsigned)dest->x != (unsigned)dest->y) overalloc(); if ((unsigned)dest->x * (unsigned)dest->y > (unsigned)MAXINT / bmpixelsize) overalloc(); dest->data=mem_alloc(dest->x*dest->y*bmpixelsize); dest->skip=dest->x*bmpixelsize; dest->flags=0; return 0;}static int vga_block(struct graphics_device *dev){ int overridden; overridden=(flags>>1)&1; if (!overridden){ if (!(flags&1)){ backup_virtual_device=current_virtual_device; current_virtual_device=NULL; } svgalib_block_itrm(ditrm); if (mouse_works){ hide_mouse(); /* mouse_close(); This is not necessary as it is handled by vga_setmode(TEXT). */ } vga_setmode(TEXT); } flags|=2; return overridden;}static int vga_unblock(struct graphics_device *dev){#ifdef DEBUG if (current_virtual_device) { internal("vga_unblock called without vga_block"); return 0; }#endif /* #ifdef DEBUG */ flags&=~2; if (!flags) current_virtual_device=backup_virtual_device; vga_setmousesupport(1); vga_setmode(vga_mode); setup_mode(vga_mode); if (mouse_works){ show_mouse(); mouse_seteventhandler(mouse_event_handler); } svgalib_unblock_itrm(ditrm); if (current_virtual_device) current_virtual_device->redraw_handler(current_virtual_device ,¤t_virtual_device->size); return 0;}static void *svga_prepare_strip(struct bitmap *bmp, int top, int lines){ return ((char *)bmp->data)+bmp->skip*top;}static void svga_commit_strip(struct bitmap *bmp, int top, int lines){ return;}/* This is a nasty hack */#undef selectint vga_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout){ int retval,i; if (drv != &svga_driver) return select(n, readfds, writefds, exceptfds, timeout); /* The second flag here is to suppress mouse wait * in blocked state */ retval=vga_waitevent((mouse_works&&!(flags&2) ? VGA_MOUSEEVENT : 0)#i
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -