📄 vnc-out.c
字号:
*ptr++ = colorscheme[(b >> 0) & 0x01]; } break; } } else { memcpy_P(tmp, &ctk_vncfont[c * (FONT_WIDTH * FONT_HEIGHT)], FONT_WIDTH * FONT_HEIGHT); tmpptr = tmp; for(i = 0; i < FONT_HEIGHT * FONT_WIDTH; ++i) { *ptr++ = colorscheme[*tmpptr++]; } }}/*-----------------------------------------------------------------------------------*/voidvnc_out_new(struct vnc_server_state *vs){ u8_t i; vs->width = SCREEN_WIDTH; vs->height = SCREEN_HEIGHT; vs->x = vs->y = vs->x1 = vs->y1 = vs->x2 = vs->y2 = 0; vs->w = CHARS_WIDTH; vs->h = CHARS_HEIGHT; /* Initialize the linked list of updates. */ for(i = 0; i < VNC_SERVER_MAX_UPDATES - 1; ++i) { vs->updates_pool[i].next = &vs->updates_pool[i + 1]; } vs->updates_pool[VNC_SERVER_MAX_UPDATES].next = NULL; vs->updates_free = &vs->updates_pool[0]; vs->updates_pending = vs->updates_current = NULL;}/*-----------------------------------------------------------------------------------*/voidvnc_out_send_blank(struct vnc_server_state *vs){ struct rfb_fb_update *umsg; u8_t *ptr; u16_t len; u8_t msglen; vs->x = vs->y = 0; vs->x2 = vs->y2 = 0; umsg = (struct rfb_fb_update *)uip_appdata; umsg->type = RFB_FB_UPDATE; umsg->rects = HTONS(2); ptr = (u8_t *)umsg + sizeof(struct rfb_fb_update); len = sizeof(struct rfb_fb_update); msglen = vnc_server_draw_rect(ptr, 0, 0, HTONS(SCREEN_WIDTH), HTONS(SCREEN_HEIGHT), BORDER_COLOR); ptr += msglen; len += msglen; msglen = vnc_server_draw_rect(ptr, HTONS(SCREEN_X), HTONS(SCREEN_Y), HTONS(SCREEN_WIDTH - SCREEN_X * 2), HTONS(SCREEN_HEIGHT - SCREEN_Y * 2), SCREEN_COLOR); uip_send(uip_appdata, len + msglen); vs->sendmsg = SENT_BLANK;}/*-----------------------------------------------------------------------------------*/voidvnc_out_send_screen(struct vnc_server_state *vs){ vnc_out_send_update(vs);}/*-----------------------------------------------------------------------------------*/static short tmpbuf[30];voidvnc_out_send_update(struct vnc_server_state *vs){ u8_t x, y, x0; u8_t msglen; u16_t len, n; u8_t *ptr; struct rfb_fb_update *umsg; struct rfb_fb_update_rect_hdr *recthdr; struct rfb_rre_hdr *rrehdr; u8_t c, color, lastcolor; u8_t numblanks; /* First, check if we need to feed the update function with a new pending update. */ check_updates(vs); /* PRINTF(("Sending Update from (%d:%d) (%d:%d) to (%d:%d)\n", vs->x, vs->y, vs->x1, vs->y1, vs->x + vs->w, vs->y + vs->h));*/ umsg = (struct rfb_fb_update *)uip_appdata; umsg->type = RFB_FB_UPDATE; x0 = vs->x1; n = 0; msglen = 0; ptr = (u8_t *)umsg + sizeof(struct rfb_fb_update); len = sizeof(struct rfb_fb_update); /* Loop over all characters that are covered by this update. */ for(y = vs->y1; y < vs->y + vs->h; ++y) { for(x = x0; x < vs->x + vs->w; ++x) { /* First check if there are any blank space characters, and if so, find out how many of them there are in a row. Instead of sending the individual space characters as raw bitmaps, we can send the entire string of blanks as a single color rectangle instead. */ c = screen[x + y * CHARS_WIDTH]; numblanks = 0; lastcolor = color = colorscreen[x + y * CHARS_WIDTH]; /* If the character is a blank, we continue reading characters until we find one that has a different color, or one that is not a blank. We must keep within the update rectangle, so we make sure that the "x" variable does not increase beyond the edge. The "numblanks" variable is used to keep track of how many blank characters we have found. */ while(lastcolor == color && c == 0x20 && x < vs->x + vs->w) { ++numblanks; ++x; lastcolor = color; color = colorscreen[x + y * CHARS_WIDTH]; c = screen[x + y * CHARS_WIDTH]; } if(numblanks > 0) { /* PRINTF(("Found %d blanks (%d:%d -> %d:%d)\n", numblanks, x - numblanks, y, x, y));*/ /* There were one or more blank characters, so we send out a single color rectangle with the right width. But first we make sure that there is enough space in the current TCP segment to put the rectangle. If there isn't we have to backtrack the "x" variable to where we found the first blank character so that the next TCP segment will be able to update this area instead. */ msglen = sizeof(struct rfb_fb_update_rect_hdr) + /*sizeof(struct rfb_rre_hdr)*/5; if(msglen >= uip_mss() - len) { /* PRINTF(("Not enouch space for blanks (%d, left %d)\n", msglen, uip_mss() - len));*/ /* There is not enough space in the segment, so we remember where we were ... */ vs->x2 = x - numblanks; vs->y2 = y; /* ... and we break out of the loop. */ goto loopend; } /* We construct a rectangle with the right width and color. */ /* recthdr = (struct rfb_fb_update_rect_hdr *)ptr;*/ recthdr = (struct rfb_fb_update_rect_hdr *)tmpbuf; rrehdr = (struct rfb_rre_hdr *)((char *)recthdr + sizeof(struct rfb_fb_update_rect_hdr)); /* PRINTF(("Blankign (%d:%d) to (%d:%d)\n", (x - numblanks) * FONT_WIDTH, y * FONT_HEIGHT, FONT_WIDTH * numblanks, FONT_HEIGHT));*/ recthdr->rect.x = htons(SCREEN_X + (x - numblanks) * FONT_WIDTH); recthdr->rect.y = htons(SCREEN_Y + y * FONT_HEIGHT); recthdr->rect.w = htons(FONT_WIDTH * numblanks); recthdr->rect.h = HTONS(FONT_HEIGHT); recthdr->encoding[0] = recthdr->encoding[1] = recthdr->encoding[2] = 0; recthdr->encoding[3] = RFB_ENC_RRE; rrehdr->subrects[0] = rrehdr->subrects[1] = 0; rrehdr->bgpixel = colortheme[lastcolor][0]; --x; } else { /* So there were no blank characters. */ /* PRINTF(("An char at (%d:%d)\n", x, y));*/ /* First we must make sure that there is enough space in the outgoing TCP segment. */ msglen = sizeof(struct rfb_fb_update_rect_hdr) + FONT_HEIGHT * FONT_WIDTH; if(msglen >= uip_mss() - len) { /* PRINTF(("Not enouch space for char (%d, left %d)\n", msglen, uip_mss() - len));*/ /* There is not enough space in the segment, so we remember where we were ... */ vs->x2 = x; vs->y2 = y; /* ... and we break out of the loop. */ goto loopend; } /* PRINTF(("ptr %p\n",ptr);*/ /* recthdr = (struct rfb_fb_update_rect_hdr *)ptr;*/ recthdr = (struct rfb_fb_update_rect_hdr *)tmpbuf; recthdr->rect.x = htons(SCREEN_X + x * FONT_WIDTH); recthdr->rect.y = htons(SCREEN_Y + y * FONT_HEIGHT); recthdr->rect.w = HTONS(FONT_WIDTH); recthdr->rect.h = HTONS(FONT_HEIGHT); recthdr->encoding[0] = recthdr->encoding[1] = recthdr->encoding[2] = 0; recthdr->encoding[3] = RFB_ENC_RAW; makechar((u8_t *)recthdr + sizeof(struct rfb_fb_update_rect_hdr), x, y); } memcpy(ptr, tmpbuf, msglen); PRINTF(("Msglen %d (%d:%d)\n", msglen, x, y)); len += msglen; ptr += msglen; ++n; } x0 = vs->x; } loopend: umsg->rects = htons(n); if(y == vs->y + vs->h && x == vs->x + vs->w) { vs->x2 = vs->y2 = 0; } if(n > 0) { /* printf("Sending %d rects, %d bytes (%p, %p, %p)\n", n, len, uip_appdata, umsg, ptr);*/ uip_send(uip_appdata, len); }}/*-----------------------------------------------------------------------------------*/#define NUMKEYS 20static char keys[NUMKEYS];static int firstkey, lastkey;charvnc_out_keyavail(void){ return firstkey != lastkey;}charvnc_out_getkey(void){ char key; key = keys[firstkey]; if(firstkey != lastkey) { ++firstkey; if(firstkey >= NUMKEYS) { firstkey = 0; } } return key; }voidvnc_out_key_event(struct vnc_server_state *vs){ struct rfb_key_event *ev; ev = (struct rfb_key_event *)uip_appdata; if(ev->down != 0) { if(vs->sendmsg == SEND_NONE) { vs->sendmsg = SEND_UPDATE; } if(ev->key[2] == 0 || (ev->key[2] == 0xff && (ev->key[3] == CH_HOME || ev->key[3] == CH_TAB || ev->key[3] == CH_ESC || ev->key[3] == CH_DEL || ev->key[3] == CH_ENTER || ev->key[3] == CH_CURS_LEFT || ev->key[3] == CH_CURS_UP || ev->key[3] == CH_CURS_RIGHT || ev->key[3] == CH_CURS_DOWN))) { keys[lastkey] = ev->key[3]; ++lastkey; if(lastkey >= NUMKEYS) { lastkey = 0; } } } check_updates(vs);}/*-----------------------------------------------------------------------------------*/voidvnc_out_pointer_event(struct vnc_server_state *vs){ struct rfb_pointer_event *ev; u16_t evx, evy; ev = (struct rfb_pointer_event *)uip_appdata; evx = htons(ev->x); evy = htons(ev->y); if(evx > SCREEN_X && evx < SCREEN_WIDTH - 2 * SCREEN_X && evy > SCREEN_Y && evy < SCREEN_HEIGHT - 2 * SCREEN_Y) { mouse_button = ev->buttonmask & RFB_BUTTON_MASK1; mouse_x = evx - SCREEN_X; mouse_y = evy - SCREEN_Y; check_updates(vs); } }/*-----------------------------------------------------------------------------------*/voidvnc_out_acked(struct vnc_server_state *vs){ if(vs->state != VNC_RUNNING) { return; } if(vs->sendmsg == SENT_BLANK) { init_send_screen(vs); } else if(vs->sendmsg == SEND_BLANK) { /* Do nothing until sendmsg == SENT_BLANK. */ } else if(vs->sendmsg == SEND_SCREEN) { /* When the screen has been fully drawn, ->x2 and ->y2 are both set to 0 to indicate this.*/ if(vs->x2 == 0 && vs->y2 == 0) { vs->sendmsg = SEND_NONE; /* If there was an updaterequest for the entire screen, we can clear that flag now. */ if(vs->updates_current != NULL) { vnc_server_update_free(vs, vs->updates_current); vs->updates_current = NULL; } check_updates(vs); } else { vs->x1 = vs->x2; vs->y1 = vs->y2; } } else if(vs->sendmsg == SEND_UPDATE) { if(vs->x2 == 0 && vs->y2 == 0) { /* So, we have updated the area that we needed. We now check if there have been any recent full screen update requests. If so, we need to go to the SEND_SCREEN state. Else, we see if there were more areas that needed to be updated and if so, we'll continue with those. */ vs->sendmsg = SEND_NONE; if(vs->updates_current != NULL) { vnc_server_update_free(vs, vs->updates_current); vs->updates_current = NULL; } check_updates(vs);#if 0 if(vs->updaterequest == VNC_SERVER_UPDATE_FULL) { check_updates(vs); } else { vs->updatesptr2 = (vs->updatesptr2 + 1) % VNC_SERVER_MAX_UPDATES; /* If there are no more updates to do, we'll go back to the SEND_NONE state. */ if(vs->updatesptr2 == vs->updatesptr) { vs->updatetype = VNC_SERVER_UPDATE_NONE; } else { /* Otherwise, we continue to update the next area. */ vs->updaterequest = VNC_SERVER_UPDATE_PARTS; check_updates(vs); } }#endif /* 0 */ } else { vs->x1 = vs->x2; vs->y1 = vs->y2; } } else { vs->sendmsg = SEND_NONE; }}/*-----------------------------------------------------------------------------------*/voidvnc_out_poll(struct vnc_server_state *vs){ /* PRINTF(("vs->state %d, sendmsg %d, updatetype %d, updatereq %d\n", vs->state, vs->sendmsg, vs->updatetype, vs->updaterequest);*/ if(vs->state == VNC_RUNNING && vs->sendmsg == SEND_NONE) { check_updates(vs); vnc_server_send_data(vs); }}/*-----------------------------------------------------------------------------------*/voidctk_mouse_init(void){}/*-----------------------------------------------------------------------------------*/unsigned shortctk_mouse_x(void){ return mouse_x;}/*-----------------------------------------------------------------------------------*/unsigned shortctk_mouse_y(void){ return mouse_y;}/*-----------------------------------------------------------------------------------*/unsigned charctk_mouse_xtoc(unsigned short x){ return x / FONT_WIDTH;}/*-----------------------------------------------------------------------------------*/unsigned charctk_mouse_ytoc(unsigned short y){ return y / FONT_HEIGHT;}/*-----------------------------------------------------------------------------------*/unsigned charctk_mouse_button(void){ return mouse_button;}/*-----------------------------------------------------------------------------------*/voidctk_mouse_hide(void){}/*-----------------------------------------------------------------------------------*/voidctk_mouse_show(void){}/*-----------------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -