/* convert a RGBA color to a color index usable in graphic primitives */staticunsignedintvga_get_color(DisplayState*ds,unsignedintrgba){unsignedintr,g,b,color;switch(ds->depth){#if0case8:r=(rgba>>16)&0xff;g=(rgba>>8)&0xff;b=(rgba)&0xff;color=(rgb_to_index[r]*6*6)+(rgb_to_index[g]*6)+(rgb_to_index[b]);break;#endifcase15:r=(rgba>>16)&0xff;g=(rgba>>8)&0xff;b=(rgba)&0xff;color=((r>>3)<<10)|((g>>3)<<5)|(b>>3);break;case16:r=(rgba>>16)&0xff;g=(rgba>>8)&0xff;b=(rgba)&0xff;color=((r>>3)<<11)|((g>>2)<<5)|(b>>3);break;case32:default:color=rgba;break;}returncolor;}staticvoidvga_fill_rect(DisplayState*ds,intposx,intposy,intwidth,intheight,uint32_tcolor){uint8_t*d,*d1;intx,y,bpp;bpp=(ds->depth+7)>>3;d1=ds->data+ds->linesize*posy+bpp*posx;for(y=0;y<height;y++){d=d1;switch(bpp){case1:for(x=0;x<width;x++){*((uint8_t*)d)=color;d++;}break;case2:for(x=0;x<width;x++){*((uint16_t*)d)=color;d+=2;}break;case4:for(x=0;x<width;x++){*((uint32_t*)d)=color;d+=4;}break;}d1+=ds->linesize;}}/* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */staticvoidvga_bitblt(DisplayState*ds,intxs,intys,intxd,intyd,intw,inth){constuint8_t*s;uint8_t*d;intwb,y,bpp;bpp=(ds->depth+7)>>3;wb=w*bpp;if(yd<=ys){s=ds->data+ds->linesize*ys+bpp*xs;d=ds->data+ds->linesize*yd+bpp*xd;for(y=0;y<h;y++){memmove(d,s,wb);d+=ds->linesize;s+=ds->linesize;}}else{s=ds->data+ds->linesize*(ys+h-1)+bpp*xs;d=ds->data+ds->linesize*(yd+h-1)+bpp*xd;for(y=0;y<h;y++){memmove(d,s,wb);d-=ds->linesize;s-=ds->linesize;}}}/***********************************************************//* basic char display */#defineFONT_HEIGHT16#defineFONT_WIDTH8#include"vgafont.h"#definecbswap_32(__x)\((uint32_t)(\(((uint32_t)(__x)&(uint32_t)0x000000ffUL)<<24)|\(((uint32_t)(__x)&(uint32_t)0x0000ff00UL)<<8)|\(((uint32_t)(__x)&(uint32_t)0x00ff0000UL)>>8)|\(((uint32_t)(__x)&(uint32_t)0xff000000UL)>>24)))#ifdefWORDS_BIGENDIAN#definePAT(x)x#else#definePAT(x)cbswap_32(x)#endifstaticconstuint32_tdmask16[16]={PAT(0x00000000),PAT(0x000000ff),PAT(0x0000ff00),PAT(0x0000ffff),PAT(0x00ff0000),PAT(0x00ff00ff),PAT(0x00ffff00),PAT(0x00ffffff),PAT(0xff000000),PAT(0xff0000ff),PAT(0xff00ff00),PAT(0xff00ffff),PAT(0xffff0000),PAT(0xffff00ff),PAT(0xffffff00),PAT(0xffffffff),};staticconstuint32_tdmask4[4]={PAT(0x00000000),PAT(0x0000ffff),PAT(0xffff0000),PAT(0xffffffff),};
staticuint32_tcolor_table[2][8];enumcolor_names{COLOR_BLACK=0,COLOR_RED=1,COLOR_GREEN=2,COLOR_YELLOW=3,COLOR_BLUE=4,COLOR_MAGENTA=5,COLOR_CYAN=6,COLOR_WHITE=7};staticconstuint32_tcolor_table_rgb[2][8]={{/* dark */
QEMU_RGB(0x00,0x00,0x00),/* black */QEMU_RGB(0xaa,0x00,0x00),/* red */QEMU_RGB(0x00,0xaa,0x00),/* green */QEMU_RGB(0xaa,0xaa,0x00),/* yellow */QEMU_RGB(0x00,0x00,0xaa),/* blue */QEMU_RGB(0xaa,0x00,0xaa),/* magenta */QEMU_RGB(0x00,0xaa,0xaa),/* cyan */QEMU_RGB(0xaa,0xaa,0xaa),/* white */
QEMU_RGB(0x00,0x00,0x00),/* black */QEMU_RGB(0xff,0x00,0x00),/* red */QEMU_RGB(0x00,0xff,0x00),/* green */QEMU_RGB(0xff,0xff,0x00),/* yellow */QEMU_RGB(0x00,0x00,0xff),/* blue */QEMU_RGB(0xff,0x00,0xff),/* magenta */QEMU_RGB(0x00,0xff,0xff),/* cyan */QEMU_RGB(0xff,0xff,0xff),/* white */
/*Setconsoleattributesdependingonthecurrentescapecodes.*NOTE:Iknowthiscodeisnotveryefficient(checkingeverycolorforit*self)butitismorereadableandbettermaintainable.*/staticvoidconsole_handle_escape(TextConsole*s){inti;for(i=0;i<s->nb_esc_params;i++){switch(s->esc_params[i]){case0:/* reset all console attributes to default */s->t_attrib=s->t_attrib_default;break;case1:s->t_attrib.bold=1;break;case4:s->t_attrib.uline=1;break;case5:s->t_attrib.blink=1;break;case7:s->t_attrib.invers=1;break;case8:s->t_attrib.unvisible=1;break;case22:s->t_attrib.bold=0;break;case24:s->t_attrib.uline=0;break;case25:s->t_attrib.blink=0;break;case27:s->t_attrib.invers=0;break;case28:s->t_attrib.unvisible=0;break;/* set foreground color */case30:s->t_attrib.fgcol=COLOR_BLACK;break;case31:s->t_attrib.fgcol=COLOR_RED;break;case32:s->t_attrib.fgcol=COLOR_GREEN;break;case33:s->t_attrib.fgcol=COLOR_YELLOW;break;case34:s->t_attrib.fgcol=COLOR_BLUE;break;case35:s->t_attrib.fgcol=COLOR_MAGENTA;break;case36:s->t_attrib.fgcol=COLOR_CYAN;break;case37:s->t_attrib.fgcol=COLOR_WHITE;break;/* set background color */case40:s->t_attrib.bgcol=COLOR_BLACK;break;case41:s->t_attrib.bgcol=COLOR_RED;break;case42:s->t_attrib.bgcol=COLOR_GREEN;break;case43:s->t_attrib.bgcol=COLOR_YELLOW;break;case44:s->t_attrib.bgcol=COLOR_BLUE;break;case45:s->t_attrib.bgcol=COLOR_MAGENTA;break;case46:s->t_attrib.bgcol=COLOR_CYAN;break;case47:s->t_attrib.bgcol=COLOR_WHITE;break;}}}
case'A':/* move cursor up */if(s->esc_params[0]==0){s->esc_params[0]=1;}s->y-=s->esc_params[0];if(s->y<0){s->y=0;}break;case'B':/* move cursor down */if(s->esc_params[0]==0){s->esc_params[0]=1;}s->y+=s->esc_params[0];if(s->y>=s->height){s->y=s->height-1;}
case'D':/* move cursor left */if(s->esc_params[0]==0){s->esc_params[0]=1;}s->x-=s->esc_params[0];if(s->x<0){s->x=0;}break;case'G':/* move cursor to column */s->x=s->esc_params[0]-1;if(s->x<0){s->x=0;}break;case'f':case'H':/* move cursor to row, column */s->x=s->esc_params[1]-1;if(s->x<0){s->x=0;}s->y=s->esc_params[0]-1;if(s->y<0){s->y=0;}break;case'J':switch(s->esc_params[0]){case0:/* clear to end of screen */for(y=s->y;y<s->height;y++){for(x=0;x<s->width;x++){if(y==s->y&&x<s->x){continue;}console_clear_xy(s,x,y);}}break;case1:/* clear from beginning of screen */for(y=0;y<=s->y;y++){for(x=0;x<s->width;x++){if(y==s->y&&x>s->x){break;}console_clear_xy(s,x,y);}}break;case2:/* clear entire screen */for(y=0;y<=s->height;y++){for(x=0;x<s->width;x++){console_clear_xy(s,x,y);}}break;}
case1:/* clear from beginning of line */for(x=0;x<=s->x;x++){console_clear_xy(s,x,s->y);}break;case2:/* clear entire line */for(x=0;x<s->width;x++){console_clear_xy(s,x,s->y);}
case'n':/* report cursor position *//* TODO: send ESC[row;colR */break;case's':/* save cursor position */s->x_saved=s->x;s->y_saved=s->y;break;case'u':/* restore cursor position */s->x=s->x_saved;s->y=s->y_saved;break;default:#ifdefDEBUG_CONSOLEfprintf(stderr,"unhandled escape character '%c'\n",ch);#endifbreak;}break;
/* called when an ascii key is pressed */voidkbd_put_keysym(intkeysym){TextConsole*s;uint8_tbuf[16],*q;intc;s=active_console;if(!s||!s->text_console)return;switch(keysym){caseQEMU_KEY_CTRL_UP:console_scroll(-1);break;caseQEMU_KEY_CTRL_DOWN:console_scroll(1);break;caseQEMU_KEY_CTRL_PAGEUP:console_scroll(-10);break;caseQEMU_KEY_CTRL_PAGEDOWN:console_scroll(10);break;default:
/* convert the QEMU keysym to VT100 key string */q=buf;if(keysym>=0xe100&&keysym<=0xe11f){*q++='\033';*q++='[';c=keysym-0xe100;if(c>=10)*q++='0'+(c/10);*q++='0'+(c%10);*q++='~';}elseif(keysym>=0xe120&&keysym<=0xe17f){*q++='\033';*q++='[';*q++=keysym&0xff;}else{
s->text_console=text;if(text){consoles[nb_consoles++]=s;}else{/* HACK: Put graphical consoles before text consoles. */for(i=nb_consoles;i>0;i--){if(!consoles[i-1]->text_console)break;consoles[i]=consoles[i-1];}consoles[i]=s;}returns;}TextConsole*graphic_console_init(DisplayState*ds,vga_hw_update_ptrupdate,vga_hw_invalidate_ptrinvalidate,vga_hw_screen_dump_ptrscreen_dump,void*opaque){TextConsole*s;s=new_console(ds,0);if(!s)returnNULL;s->hw_update=update;s->hw_invalidate=invalidate;s->hw_screen_dump=screen_dump;s->hw=opaque;
/* Set text attribute defaults */s->t_attrib_default.bold=0;s->t_attrib_default.uline=0;s->t_attrib_default.blink=0;s->t_attrib_default.invers=0;s->t_attrib_default.unvisible=0;s->t_attrib_default.fgcol=COLOR_WHITE;s->t_attrib_default.bgcol=COLOR_BLACK;/* set current text attributes to default */s->t_attrib=s->t_attrib_default;