LinuxVNC.c 4.81 KB
Newer Older
1
#include <rfb/keysym.h>
dscho's avatar
dscho committed
2 3 4 5 6 7 8 9
#include "VNConsole.h"
#include "vga.h"
#include <fcntl.h>
#include <sys/ioctl.h>

static int tty=2;
static int tty_inject_device;

10
void do_key(rfbBool down,rfbKeySym keySym,rfbClientPtr cl)
dscho's avatar
dscho committed
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
{
  static char isControl=0;

  if(down) {
    /* if(keySym==XK_Escape)
      rfbCloseClient(cl);
    else */ if(keySym==XK_Control_L || keySym==XK_Control_R)
      isControl++;
    else if(tty_inject_device>=0) {
      if(keySym==XK_Escape)
	keySym=27;
      if(isControl) {
	if(keySym>='a' && keySym<='z')
	  keySym-='a'-1;
	else if(keySym>='A' && keySym<='Z')
	  keySym-='A'-1;
	else
	  keySym=0xffff;
      }

      if(keySym==XK_Tab)
	keySym='\t';
      else if(keySym==XK_Return)
	keySym='\r';
      else if(keySym==XK_BackSpace)
	keySym=8;
      else if(keySym==XK_Home || keySym==XK_KP_Home)
	keySym=1;
      else if(keySym==XK_End || keySym==XK_KP_End)
	keySym=5;
      else if(keySym==XK_Up || keySym==XK_KP_Up)
	keySym=16;
      else if(keySym==XK_Down || keySym==XK_KP_Down)
	keySym=14;
      else if(keySym==XK_Right || keySym==XK_KP_Right)
	keySym=6;
      else if(keySym==XK_Left || keySym==XK_KP_Left)
	keySym=2;

      if(keySym<0x100) {
	int ret;
	ret=ioctl(tty_inject_device,TIOCSTI,&keySym);
	if(ret<0) {
	  static char device[64];
	  close(tty_inject_device);
	  sprintf(device,"/dev/tty%d",tty);
	  tty_inject_device=open(device,O_WRONLY);
	  ret=ioctl(tty_inject_device,TIOCSTI,&keySym);
	  if(ret<0)
dscho's avatar
dscho committed
60
	    rfbErr("Couldn't reopen device %s!\n",device);
dscho's avatar
dscho committed
61 62 63 64
	}
      }
    }
  } else if(keySym==XK_Control_L || keySym==XK_Control_R)
65 66
    if(isControl>0)
      isControl--;
dscho's avatar
dscho committed
67 68
}

dscho's avatar
dscho committed
69 70 71 72 73 74 75 76 77 78 79
/* these colours are from linux kernel drivers/char/console.c */
unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
				       8,12,10,14, 9,13,11,15 };
/* the default colour table, for VGA+ colour systems */
int default_red[] = {0x00,0xaa,0x00,0xaa,0x00,0xaa,0x00,0xaa,
    0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff};
int default_grn[] = {0x00,0x00,0xaa,0x55,0x00,0x00,0xaa,0xaa,
    0x55,0x55,0xff,0xff,0x55,0x55,0xff,0xff};
int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa,
    0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff};

dscho's avatar
dscho committed
80 81 82 83 84 85 86 87 88 89 90 91
int main(int argc,char **argv)
{
  int width=80,height=25;
  char *buffer;
  vncConsolePtr console;
  char tty_device[64],title[128];
  int i;
  FILE* tty_file;
  struct winsize dimensions;

  if(argc>1) {
    if((tty=atoi(argv[1]))<1) {
dscho's avatar
dscho committed
92
      rfbErr("Usage: %s [tty_number [vnc args]]\n",argv[0]);
dscho's avatar
dscho committed
93 94 95 96 97 98 99 100 101 102 103
      exit(1);
    } else {
      argv++;
      argc--;
    }
  }

  /* getopt goes here! */

  sprintf(tty_device,"/dev/tty%d",tty);
  if((tty_inject_device=open(tty_device,O_WRONLY))<0) {
dscho's avatar
dscho committed
104
    rfbErr("Couldn't open tty device %s!\n",tty_device);
dscho's avatar
dscho committed
105 106
    exit(1);
  }
107
  rfbLog("Using device %s.\n",tty_device);
dscho's avatar
dscho committed
108 109 110 111 112 113 114 115 116

  if(ioctl(tty_inject_device,TIOCGWINSZ,&dimensions)>=0) {
    width=dimensions.ws_col;
    height=dimensions.ws_row;
  }

  sprintf(title,"LinuxVNC: /dev/tty%d",tty);

  /* console init */
117 118 119
  if(!(console=vcGetConsole(&argc,argv,width,height,&vgaFont,TRUE)))
    exit(1);

dscho's avatar
dscho committed
120
  for(i=0;i<16;i++) {
121 122 123
    console->screen->colourMap.data.bytes[i*3+0]=default_red[color_table[i]];
    console->screen->colourMap.data.bytes[i*3+1]=default_grn[color_table[i]];
    console->screen->colourMap.data.bytes[i*3+2]=default_blu[color_table[i]];
dscho's avatar
dscho committed
124
  }
125 126
  console->screen->desktopName=title;
  console->screen->kbdAddEvent=do_key;
dscho's avatar
dscho committed
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
  console->selectTimeOut=100000;
  console->wrapBottomToTop=TRUE;
#ifdef USE_OLD_VCS
  buffer=malloc(width*height);
  console->cursorActive=FALSE;
#else
  buffer=malloc(width*height*2+4);
  console->cursorActive=TRUE;
#endif
  /* memcpy(buffer,console->screenBuffer,width*height); */

#ifdef USE_OLD_VCS
  sprintf(tty_device,"/dev/vcs%d",tty);
#else
  sprintf(tty_device,"/dev/vcsa%d",tty);
#endif

dscho's avatar
dscho committed
144
  while(rfbIsActive(console->screen)) {
dscho's avatar
dscho committed
145 146 147
    if(!console->currentlyMarking) {
      tty_file=fopen(tty_device,"rb");
      if(!tty_file) {
dscho's avatar
dscho committed
148
	rfbErr("cannot open device \"%s\"\n",
dscho's avatar
dscho committed
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
		tty_device);
	exit(1);
      }
#ifdef USE_OLD_VCS
      fread(buffer,width,height,tty_file);
#else
      fread(buffer,width*height*2+4,1,tty_file);
      vcHideCursor(console);
#endif
      fclose(tty_file);

      for(i=0;i<console->width*console->height;i++) {
	if
#ifdef USE_OLD_VCS
	 (buffer[i]!=console->screenBuffer[i])
#else
	 (buffer[4+2*i]!=console->screenBuffer[i] ||
	  buffer[5+2*i]!=console->attributeBuffer[i])
#endif
	  {
	    console->x=(i%console->width);
	    console->y=(i/console->width);
	    /*
172
	      rfbLog("changes: %d,%d (%d!=%d || %d!=%d)\n",
dscho's avatar
dscho committed
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
	      console->x,console->y,
	      buffer[4+2*i],console->screenBuffer[i],
	      buffer[5+2*i],console->attributeBuffer[i]);
	    */
	    
#ifdef USE_OLD_VCS
	    vcPutChar(console,buffer[i]);
#else
	    vcPutCharColour(console,buffer[4+i*2],buffer[5+i*2]&0x7,buffer[5+i*2]>>4);
#endif
	  }
      }
      console->x=buffer[2];
      console->y=buffer[3];
    }
    vcProcessEvents(console);
  }
  return(0);
}