#include #include "VNConsole.h" #define DEBUG(x) unsigned char colourMap16[16*3]={ /* 0 black #000000 */ 0x00,0x00,0x00, /* 1 maroon #800000 */ 0x80,0x00,0x00, /* 2 green #008000 */ 0x00,0x80,0x00, /* 3 khaki #808000 */ 0x80,0x80,0x00, /* 4 navy #000080 */ 0x00,0x00,0x80, /* 5 purple #800080 */ 0x80,0x00,0x80, /* 6 aqua-green #008080 */ 0x00,0x80,0x80, /* 7 light grey #c0c0c0 */ 0xc0,0xc0,0xc0, /* 8 dark grey #808080 */ 0x80,0x80,0x80, /* 9 red #ff0000 */ 0xff,0x00,0x00, /* a light green #00ff00 */ 0x00,0xff,0x00, /* b yellow #ffff00 */ 0xff,0xff,0x00, /* c blue #0000ff */ 0x00,0x00,0xff, /* d pink #ff00ff */ 0xff,0x00,0xff, /* e light blue #00ffff */ 0x00,0xff,0xff, /* f white #ffffff */ 0xff,0xff,0xff }; void MakeColourMap16(vncConsolePtr c) { int i,j; rfbColourMap* colourMap=&(c->rfbScreen->colourMap); if(colourMap->count) free(colourMap->data.bytes); colourMap->data.bytes=malloc(16*3); for(i=0;i<16;i++) for(j=0;j<3;j++) colourMap->data.bytes[i*3+2-j]=colourMap16[i*3+j]; colourMap->count=16; colourMap->is16=FALSE; c->rfbScreen->rfbServerFormat.trueColour=FALSE; } void vcDrawOrHideCursor(vncConsolePtr c) { int i,j,w=c->rfbScreen->paddedWidthInBytes; char *b=c->rfbScreen->frameBuffer+c->y*c->cHeight*w+c->x*c->cWidth; for(j=c->cy1;jcy2;j++) for(i=c->cx1;icx2;i++) b[j*w+i]^=0x0f; rfbMarkRectAsModified(c->rfbScreen, c->x*c->cWidth+c->cx1,c->y*c->cHeight+c->cy1, c->x*c->cWidth+c->cx2,c->y*c->cHeight+c->cy2); c->cursorIsDrawn=c->cursorIsDrawn?FALSE:TRUE; } void vcDrawCursor(vncConsolePtr c) { rfbDrawCursor(c->rfbScreen); if(c->cursorActive && !c->cursorIsDrawn && c->yheight && c->xwidth) { /* fprintf(stderr,"DrawCursor: %d,%d\n",c->x,c->y); */ vcDrawOrHideCursor(c); } } void vcHideCursor(vncConsolePtr c) { rfbUndrawCursor(c->rfbScreen); if(c->currentlyMarking) vcUnmark(c); if(c->cursorIsDrawn) { /* fprintf(stderr,"HideCursor: %d,%d\n",c->x,c->y); */ vcDrawOrHideCursor(c); } } void vcMakeSureCursorIsDrawn(rfbClientPtr cl) { vncConsolePtr c=(vncConsolePtr)cl->screen->screenData; if(!c->dontDrawCursor) vcDrawCursor(c); } vncConsolePtr vcGetConsole(int *argc,char **argv, int width,int height,rfbFontDataPtr font #ifdef USE_ATTRIBUTE_BUFFER ,Bool withAttributes #endif ) { vncConsolePtr c=(vncConsolePtr)malloc(sizeof(vncConsole)); c->font=font; c->width=width; c->height=height; c->screenBuffer=(char*)malloc(width*height); memset(c->screenBuffer,' ',width*height); #ifdef USE_ATTRIBUTE_BUFFER if(withAttributes) { c->attributeBuffer=(char*)malloc(width*height); memset(c->attributeBuffer,0x07,width*height); } else c->attributeBuffer=NULL; #endif c->x=0; c->y=0; c->wrapBottomToTop=FALSE; c->cursorActive=TRUE; c->cursorIsDrawn=FALSE; c->dontDrawCursor=FALSE; c->inputBuffer=(char*)malloc(1024); c->inputSize=1024; c->inputCount=0; c->selection=0; c->selectTimeOut=40000; /* 40 ms */ c->doEcho=TRUE; c->wasRightButtonDown=FALSE; c->currentlyMarking=FALSE; rfbWholeFontBBox(font,&c->xhot,&c->cHeight,&c->cWidth,&c->yhot); c->cWidth-=c->xhot; c->cHeight=-c->cHeight-c->yhot; /* text cursor */ c->cx1=c->cWidth/8; c->cx2=c->cWidth*7/8; c->cy2=c->cHeight-1-c->yhot+c->cHeight/16; if(c->cy2>=c->cHeight) c->cy2=c->cHeight-1; c->cy1=c->cy2-c->cHeight/8; if(c->cy1<0) c->cy2=0; c->rfbScreen= rfbGetScreen(argc,argv,c->cWidth*c->width,c->cHeight*c->height,8,1,1); c->rfbScreen->screenData=(void*)c; c->rfbScreen->displayHook=vcMakeSureCursorIsDrawn; c->rfbScreen->frameBuffer= (char*)malloc(c->rfbScreen->width*c->rfbScreen->height); memset(c->rfbScreen->frameBuffer,c->backColour, c->rfbScreen->width*c->rfbScreen->height); c->rfbScreen->kbdAddEvent=vcKbdAddEventProc; c->rfbScreen->ptrAddEvent=vcPtrAddEventProc; c->rfbScreen->setXCutText=vcSetXCutTextProc; MakeColourMap16(c); c->foreColour=0x7; c->backColour=0; rfbInitServer(c->rfbScreen); return(c); } #include "rfbregion.h" /* before using this function, hide the cursor */ void vcScroll(vncConsolePtr c,int lineCount) { int y1,y2; rfbScreenInfoPtr s=c->rfbScreen; if(lineCount==0) return; /* fprintf(stderr,"begin scroll\n"); */ vcHideCursor(c); c->dontDrawCursor=TRUE; if(lineCount>=c->height || lineCount<=-c->height) { y1=0; y2=s->height; } else if(lineCount>0) { y1=s->height-lineCount*c->cHeight; y2=s->height; rfbDoCopyRect(s,0,0,s->width,y1,0,-lineCount*c->cHeight); memmove(c->screenBuffer, c->screenBuffer+(c->height-lineCount)*c->width, (c->height-lineCount)*c->width); #ifdef USE_ATTRIBUTE_BUFFER memmove(c->attributeBuffer, c->attributeBuffer+(c->height-lineCount)*c->width, (c->height-lineCount)*c->width); #endif } else { y1=0; y2=-lineCount*c->cHeight; rfbDoCopyRect(s,0,y2,s->width,s->height,0,-lineCount*c->cHeight); memmove(c->screenBuffer-lineCount*c->width, c->screenBuffer, (c->height+lineCount)*c->width); #ifdef USE_ATTRIBUTE_BUFFER memmove(c->attributeBuffer-lineCount*c->width, c->attributeBuffer, (c->height+lineCount)*c->width); #endif } c->dontDrawCursor=FALSE; memset(s->frameBuffer+y1*s->width,c->backColour,(y2-y1)*s->width); rfbMarkRectAsModified(s,0,y1-c->cHeight,s->width,y2); memset(c->screenBuffer+y1/c->cHeight*c->width,' ', (y2-y1)/c->cHeight*c->width); #ifdef USE_ATTRIBUTE_BUFFER memset(c->attributeBuffer+y1/c->cHeight*c->width,0x07, (y2-y1)/c->cHeight*c->width); #endif /* fprintf(stderr,"end scroll\n"); */ } void vcCheckCoordinates(vncConsolePtr c) { if(c->x>=c->width) { c->x=0; c->y++; } if(c->y>=c->height) { if(c->wrapBottomToTop) c->y=0; else { vcScroll(c,c->y+1-c->height); c->y=c->height-1; } } } void vcPutChar(vncConsolePtr c,unsigned char ch) { #ifdef USE_ATTRIBUTE_BUFFER if(c->attributeBuffer) { unsigned char colour=c->attributeBuffer[c->x+c->y*c->width]; vcPutCharColour(c,ch,colour&0x7,colour>>4); } else #endif vcPutCharColour(c,ch,c->foreColour,c->backColour); } void vcPutCharColour(vncConsolePtr c,unsigned char ch,unsigned char foreColour,unsigned char backColour) { rfbScreenInfoPtr s=c->rfbScreen; int j,x,y; vcHideCursor(c); if(ch<' ') { switch(ch) { case 7: case 13: break; case 8: /* BackSpace */ if(c->x>0) { c->x--; vcPutChar(c,' '); c->x--; } break; case 10: /* return */ c->x=0; c->y++; vcCheckCoordinates(c); break; case 9: /* tabulator */ do { vcPutChar(c,' '); } while(c->x%8); break; default: fprintf(stderr,"putchar of unknown character: %c(%d).\n",ch,ch); vcPutChar(c,' '); } } else { #ifdef USE_ATTRIBUTE_BUFFER if(c->attributeBuffer) c->attributeBuffer[c->x+c->y*c->width]=foreColour|(backColour<<4); #endif x=c->x*c->cWidth; y=c->y*c->cHeight; for(j=y+c->cHeight-1;j>=y;j--) memset(s->frameBuffer+j*s->width+x,backColour,c->cWidth); rfbDrawChar(s,c->font, x-c->xhot+(c->cWidth-rfbWidthOfChar(c->font,ch))/2, y+c->cHeight-c->yhot-1, ch,foreColour); c->screenBuffer[c->y*c->width+c->x]=ch; c->x++; rfbMarkRectAsModified(s,x,y-c->cHeight+1,x+c->cWidth,y+c->cHeight+1); vcCheckCoordinates(c); } } void vcPrint(vncConsolePtr c,unsigned char* str) { while(*str) { vcPutChar(c,*str); str++; } } void vcPrintColour(vncConsolePtr c,unsigned char* str,unsigned char foreColour,unsigned char backColour) { while(*str) { vcPutCharColour(c,*str,foreColour,backColour); str++; } } void vcPrintF(vncConsolePtr c,char* format,...) { va_list args; char buf[4096]; va_start(args, format); vsprintf(buf, format, args); vcPrint(c,buf); va_end(args); } void vcPrintFColour(vncConsolePtr c,unsigned char foreColour,unsigned char backColour,char* format,...) { va_list args; char buf[4096]; va_start(args, format); vsprintf(buf, format, args); vcPrintColour(c,buf,foreColour,backColour); va_end(args); } char vcGetCh(vncConsolePtr c) { if(c->inputCount>0) { char ch; ch=c->inputBuffer[0]; c->inputCount--; if(c->inputCount>0) memmove(c->inputBuffer,c->inputBuffer+1,c->inputCount); return(ch); } else return(0); } char vcGetChar(vncConsolePtr c) { while(c->inputCount==0) vcProcessEvents(c); return(vcGetCh(c)); } char *vcGetString(vncConsolePtr c,char *buffer,int bufferSize) { char *bufferBackup=c->inputBuffer; int i,count=bufferSize-1; if(count>c->inputCount) count=c->inputCount; for(i=1;iinputCount-=i; memmove(bufferBackup,bufferBackup+i+2,c->inputCount); return(buffer); } memcpy(buffer,bufferBackup,c->inputCount); count=c->inputSize; c->inputSize=bufferSize; c->inputBuffer=buffer; while(c->inputCountinputCount-1]!='\n') vcProcessEvents(c); buffer[c->inputCount]=0; c->inputBuffer=bufferBackup; c->inputSize=count; c->inputCount=0; return(buffer); } void vcKbdAddEventProc(Bool down,KeySym keySym,rfbClientPtr cl) { vncConsolePtr c=(vncConsolePtr)cl->screen->screenData; if(down) { if(c->inputCountinputSize) { if(keySym<0 || keySym>0xff) { if(keySym==XK_Return) keySym='\n'; else if(keySym==XK_BackSpace) keySym=8; else if(keySym==XK_Tab) keySym=9; else keySym=0; } if(keySym>0) { if(keySym==8) { if(c->inputCount>0) c->inputCount--; } else c->inputBuffer[c->inputCount++]=(char)keySym; if(c->doEcho) vcPutChar(c,(unsigned char)keySym); } } } } void vcPtrAddEventProc(int buttonMask,int x,int y,rfbClientPtr cl) { vncConsolePtr c=(vncConsolePtr)cl->screen->screenData; rfbUndrawCursor(c->rfbScreen); if(c->wasRightButtonDown) { if((buttonMask&4)==0) { if(c->selection) { char* s; for(s=c->selection;*s;s++) { c->rfbScreen->kbdAddEvent(1,*s,cl); c->rfbScreen->kbdAddEvent(0,*s,cl); } } c->wasRightButtonDown=0; } } else if(buttonMask&4) c->wasRightButtonDown=1; if(buttonMask&1) { int cx=x/c->cWidth,cy=y/c->cHeight,pos; if(cx<0) cx=0; else if(cx>=c->width) cx=c->width-1; if(cy<0) cy=0; else if(cy>=c->height) cy=c->height-1; pos=cy*c->width+cx; // mark if(!c->currentlyMarking) { c->currentlyMarking=TRUE; c->markStart=pos; c->markEnd=pos; vcToggleMarkCell(c,pos); } else { DEBUG(fprintf(stderr,"markStart: %d, markEnd: %d, pos: %d\n", c->markStart,c->markEnd,pos)); if(c->markEnd!=pos) { if(c->markEndmarkEnd; cy=pos; } else { cx=pos; cy=c->markEnd; } if(cxmarkStart) { if(cymarkStart) cy--; } else cx++; while(cx<=cy) { vcToggleMarkCell(c,cx); cx++; } c->markEnd=pos; } } } else if(c->currentlyMarking) { int i,j; if(c->markStartmarkEnd) { i=c->markStart; j=c->markEnd+1; } else { i=c->markEnd; j=c->markStart; } if(c->selection) free(c->selection); c->selection=(char*)malloc(j-i+1); memcpy(c->selection,c->screenBuffer+i,j-i); c->selection[j-i]=0; vcUnmark(c); rfbGotXCutText(c->rfbScreen,c->selection,j-i); } defaultPtrAddEvent(buttonMask,x,y,cl); } void vcSetXCutTextProc(char* str,int len, struct _rfbClientRec* cl) { vncConsolePtr c=(vncConsolePtr)cl->screen->screenData; if(c->selection) free(c->selection); c->selection=(char*)malloc(len+1); memcpy(c->selection,str,len); c->selection[len]=0; } void vcToggleMarkCell(vncConsolePtr c,int pos) { int x=(pos%c->width)*c->cWidth, y=(pos/c->width)*c->cHeight; int i,j; rfbScreenInfoPtr s=c->rfbScreen; char *b=s->frameBuffer+y*s->width+x; for(j=0;jcHeight;j++) for(i=0;icWidth;i++) b[j*s->width+i]^=0x0f; rfbMarkRectAsModified(c->rfbScreen,x,y,x+c->cWidth,y+c->cHeight); } void vcUnmark(vncConsolePtr c) { int i,j; c->currentlyMarking=FALSE; if(c->markStartmarkEnd) { i=c->markStart; j=c->markEnd+1; } else { i=c->markEnd; j=c->markStart; } for(;irfbScreen,c->selectTimeOut); }