⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdl.c

📁 运行在sdl上的rdesktop(远程桌面)
💻 C
字号:
/*   rdesktop: A Remote Desktop Protocol client.   User interface services - X-Windows   Copyright (C) Matthew Chapman 1999-2001      This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.      This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.      You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "rdesktop.h"#include <SDL.h>#include <errno.h>extern int width;extern int height;extern BOOL sendmotion;extern BOOL fullscreen;static SDL_Surface *screen;static int need_update;static SDL_Rect update_rect;static SDL_Rect clip_rect;static void add_update_rect(int x, int y, int w, int h){	if (need_update) {		int x1 = x < update_rect.x ? x : update_rect.x;		int y1 = y < update_rect.y ? y : update_rect.y;		int x2 = x + w > update_rect.x + update_rect.w ?			x + w :			update_rect.x + update_rect.w;		int y2 = y + h > update_rect.y + update_rect.h ?			y + h :			update_rect.y + update_rect.h;		update_rect.x = x1;		update_rect.y = y1;		update_rect.w = x2 - x1;		update_rect.h = y2 - y1;	} else {		SDL_Rect newrect = {x, y, w, h};		update_rect = newrect;		need_update = 1;	}}BOOLui_create_window(char *title){	unsigned int flags = 0;		SDL_Init(SDL_INIT_VIDEO);	if (fullscreen)		flags |= SDL_FULLSCREEN;		screen = SDL_SetVideoMode(width, height, 8, flags);	if (!screen) {		error("ui_create_window: unable to set video mode");		return False;	}	// set title	SDL_WM_SetCaption(title, NULL);		return True;}voidui_destroy_window(){	SDL_QuitSubSystem(SDL_INIT_VIDEO);	screen = NULL;}static uint8sdl_translate_key(SDL_keysym key){	DEBUG(("KEY(code=0x%lx)\n", key.unicode));	if ((key.scancode > 8) && (key.scancode <= 0x60))		return (key.scancode - 8);	switch (key.sym)	{		case SDLK_HOME:	/* home */			return 0x47 | 0x80;		case SDLK_UP:	/* up arrow */			return 0x48 | 0x80;		case SDLK_PAGEUP:	/* page up */			return 0x49 | 0x80;		case SDLK_LEFT:	/* left arrow */			return 0x4b | 0x80;		case SDLK_RIGHT:	/* right arrow */			return 0x4d | 0x80;		case SDLK_END:	/* end */			return 0x4f | 0x80;		case SDLK_DOWN:	/* down arrow */			return 0x50 | 0x80;		case SDLK_PAGEDOWN:	/* page down */			return 0x51 | 0x80;		case SDLK_INSERT:	/* insert */			return 0x52 | 0x80;		case SDLK_DELETE:	/* delete */			return 0x53 | 0x80;		case SDLK_KP_ENTER:	/* keypad enter */			return 0x1c | 0x80;		case SDLK_RCTRL:	/* right ctrl */			return 0x1d | 0x80;			//case SDLK_:	/* ctrl - print screen */			//return 0x37 | 0x80;		case SDLK_KP_DIVIDE:	/* keypad '/' */			return 0x35 | 0x80;		case SDLK_RALT:	/* right alt */			return 0x38 | 0x80;			//case 0x72:	/* ctrl break */			//return 0x46 | 0x80;			//case 0x73:	/* left window key */			//return 0xff;	/* real scancode is 5b */			//case 0x74:	/* right window key */			//return 0xff;	/* real scancode is 5c */			//case 0x75:	/* menu key */			//return 0x5d | 0x80;	}	return 0;}static uint16sdl_translate_mouse(unsigned long button){	return		button == SDL_BUTTON_LEFT ? MOUSE_FLAG_BUTTON1 :		button == SDL_BUTTON_RIGHT ? MOUSE_FLAG_BUTTON2 :		button == SDL_BUTTON_MIDDLE ? MOUSE_FLAG_BUTTON3 : 0;}static voidsdl_process_events(){	uint32 ev_time;	SDL_Event ev;	int scancode, button;	int mm_motion = 0, mm_x = -1, mm_y;	//	puts("process_events");	//	if (display == NULL)	//return;	while (SDL_PollEvent(&ev)) {		ev_time = SDL_GetTicks();		switch (ev.type) {		case SDL_KEYDOWN:			puts("keydown");			scancode = sdl_translate_key(ev.key.keysym);			if (scancode == 0)				break;						rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,				       scancode, 0);			break;		case SDL_KEYUP:			scancode = sdl_translate_key(ev.key.keysym);			if (scancode == 0)				break;			rdp_send_input(ev_time, RDP_INPUT_SCANCODE,				       KBD_FLAG_DOWN | KBD_FLAG_UP,				       scancode, 0);			break;		case SDL_MOUSEBUTTONDOWN:			button = sdl_translate_mouse(ev.button.button);			if (button == 0)				break;						rdp_send_input(ev_time, RDP_INPUT_MOUSE,				       button | MOUSE_FLAG_DOWN,				       ev.button.x,				       ev.button.y);			break;		case SDL_MOUSEBUTTONUP:			button = sdl_translate_mouse(ev.button.button);			if (button == 0)				break;			rdp_send_input(ev_time, RDP_INPUT_MOUSE,				       button,				       ev.button.x, ev.button.y);				       			break;		case SDL_MOUSEMOTION:			mm_motion = 1;			mm_x = ev.motion.x;			mm_y = ev.motion.y;			break;/*					case EnterNotify:		XGrabKeyboard(display, wnd, True, GrabModeAsync,		GrabModeAsync, CurrentTime);		break;		case LeaveNotify:		XUngrabKeyboard(display, CurrentTime);		break;				case Expose:		XCopyArea(display, backstore, wnd, gc,		event.xexpose.x, event.xexpose.y,		event.xexpose.width, event.xexpose.height,		event.xexpose.x, event.xexpose.y);		break;*/		}	}	if (mm_motion) {		rdp_send_input(ev_time, RDP_INPUT_MOUSE,			       MOUSE_FLAG_MOVE,			       mm_x, mm_y);	}}voidui_select(int rdp_socket){	struct timeval tv;	if (need_update) {		SDL_UpdateRects(screen, 1, &update_rect);		need_update = 0;	}		// TODO: update display here	while (True) {		fd_set rfds;				FD_ZERO(&rfds);		FD_SET(rdp_socket, &rfds);		tv.tv_sec = 0;		tv.tv_usec = 0;				switch (select(rdp_socket+1, &rfds, NULL, NULL, &tv)) {			case -1:				error("select: %s\n", strerror(errno));		}		sdl_process_events();				if (FD_ISSET(rdp_socket, &rfds))			return;	}}voidui_move_pointer(int x, int y){	SDL_WarpMouse(x, y);}HBITMAPui_create_bitmap(int width, int height, uint8 *data){// puts("FIXME: create_bitmap");	return SDL_CreateRGBSurfaceFrom(data, width, height, 4, width,					0, 0, 0, 0);}voidui_paint_bitmap(int x, int y, int cx, int cy,		int width, int height, uint8 *data){	SDL_Rect srcrect = {0, 0, cx, cy};	SDL_Rect destrect = {x, y, cx, cy};	SDL_Surface *s		= SDL_CreateRGBSurfaceFrom(data, width, height, 8, width,					   0, 0, 0, 0);	SDL_SetPalette(s, SDL_LOGPAL,		       screen->format->palette->colors,		       0,screen->format->palette->ncolors);		SDL_BlitSurface(s, &srcrect, screen, &destrect);	SDL_FreeSurface(s);	add_update_rect(x, y, cx, cy);	//puts("FIXME: paint_bitmap");}voidui_destroy_bitmap(HBITMAP bmp){	//puts("FIXME: destroy_bitmap");	SDL_FreeSurface((SDL_Surface *) bmp);}HGLYPHui_create_glyph(int width, int height, uint8 *data){	unsigned char *glyph;	int x, y;	int bit = 7;	int i = 0;	//printf("new glyph: %i, %i\n", width, height);		glyph = malloc(width * height);	// bit packed, msb is the first pixel, then shift down to get	// the next pixel		for (y=0; y<height; ++y) {		for (x=0; x<width; ++x) {			glyph[i++] = (*data & (1 << bit)) != 0;						//printf("%c", glyph->data[i] ? 'x' : ' ');			bit--;			if (bit < 0) {				bit = 7;				++data;			}		}		// new lines start on byte boundaries		//puts("");				if (bit < 7) {			bit = 7;			++data;		}	}		return glyph;	}voidui_destroy_glyph(HGLYPH glyph){	free(glyph);}HCURSORui_create_cursor(unsigned int x, unsigned int y, int width,		 int height, uint8 *andmask, uint8 *xormask){	puts("FIXME: create_cursor");}voidui_set_cursor(HCURSOR cursor){	puts("FIXME: set_cursor");}voidui_destroy_cursor(HCURSOR cursor){	puts("FIXME: destroy_cursor");}HCOLOURMAPui_create_colourmap(COLOURMAP *colours){	SDL_Palette *pal = malloc(sizeof(*pal));	int i;	pal->ncolors = colours->ncolours;	pal->colors = malloc(sizeof(*pal->colors) * pal->ncolors);	for (i=0; i<pal->ncolors; ++i) {		pal->colors[i].r = colours->colours[i].red;		pal->colors[i].g = colours->colours[i].green;		pal->colors[i].b = colours->colours[i].blue;	}	return pal;}voidui_destroy_colourmap(HCOLOURMAP map){	SDL_Palette *pal = (SDL_Palette *) map;	free(pal->colors);	free(pal);}voidui_set_colourmap(HCOLOURMAP map){	SDL_Palette *pal = (SDL_Palette *) map;	SDL_SetPalette(screen, SDL_PHYSPAL, pal->colors, 0, pal->ncolors);}voidui_set_clip(int x, int y, int cx, int cy){		clip_rect.x = x;	clip_rect.y = y;	clip_rect.w = cx;	clip_rect.h = cy;	SDL_SetClipRect(screen, &clip_rect);}voidui_reset_clip(){	clip_rect.x = clip_rect.y = 0;	clip_rect.w = screen->w;	clip_rect.h = screen->h;		SDL_SetClipRect(screen, NULL);}voidui_bell(){	printf("\a");}// this is brokenvoidui_destblt(uint8 opcode,	   /* dest */ int x, int y, int cx, int cy){	SDL_Rect rect = {x, y, cx, cy};	puts("FIXME: destblt");	printf("opcode: %i\n", opcode);	SDL_FillRect(screen, &rect, 255);	add_update_rect(x, y, cx, cy);}static inline void ui_patblt_pattern(int x, int y, int cx, int cy,				     int fgcolour, int bgcolour,				     unsigned char *pattern){	int x1, y1;	unsigned char *data;	unsigned int bit;		SDL_LockSurface(screen);	data = screen->pixels + y * screen->pitch + x;	for (y1=0; y1<cy; ++y1) {		unsigned char patbyte = pattern[(y+y1) % 8];		unsigned char *data2 = data;		bit = ~x & 7;				for (x1=0; x1<cx; ++x1) {			if (patbyte & (1 << bit))				*data2++ = bgcolour;			else				*data2++ = fgcolour;			bit = (bit - 1) & 7;		}		data += screen->pitch;	}		     	SDL_UnlockSurface(screen);}// this is brokenvoidui_patblt(uint8 opcode,	  /* dest */ int x, int y, int cx, int cy,	  /* brush */ BRUSH *brush, int bgcolour, int fgcolour){	SDL_Rect rect = {x, y, cx, cy};	puts("FIXME: patblt");	switch (brush->style) {	case 0: /* solid */		SDL_FillRect(screen, &rect, fgcolour);		break;	case 3: /* pattern */		ui_patblt_pattern(x, y, cx, cy, fgcolour, bgcolour,				  brush->pattern);		break;	default:		printf("ui_patblt: %i not implemented!\n",		       brush->style);	}		add_update_rect(x, y, cx, cy);}voidui_screenblt(uint8 opcode,	     /* dest */ int x, int y, int cx, int cy,	     /* src */ int srcx, int srcy){	SDL_Rect srcrect = {srcx, srcy, cx, cy};	SDL_Rect destrect = {x, y, cx, cy};	SDL_BlitSurface(screen, &srcrect, screen, &destrect);	add_update_rect(x, y, cx, cy);}voidui_memblt(uint8 opcode,	  /* dest */ int x, int y, int cx, int cy,	  /* src */ HBITMAP src, int srcx, int srcy){	puts("FIXME: memblt");}voidui_triblt(uint8 opcode,	  /* dest */ int x, int y, int cx, int cy,	  /* src */ HBITMAP src, int srcx, int srcy,	  /* brush */ BRUSH *brush, int bgcolour, int fgcolour){	/* This is potentially difficult to do in general. Until someone	   comes up with a more efficient way of doing it I am using cases. */	puts("FIXME: triblt");}voidui_line(uint8 opcode,	/* dest */ int startx, int starty, int endx, int endy,	/* pen */ PEN *pen){	int dx = abs(startx-endx), dy = abs(starty-endy);	puts("FIXME: line");}voidui_rect( /* dest */ int x, int y, int cx, int cy,	 /* brush */ int colour){	SDL_Rect rect = {x, y, cx, cy};		SDL_FillRect(screen, &rect, colour);	add_update_rect(x, y, cx, cy);}voidui_draw_glyph(int mixmode,	      /* dest */ int x, int y, int cx, int cy,	      /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,	      int fgcolour){	unsigned char *data;	unsigned char *glyphdata = glyph;		int x1, y1;//	puts("FIXME: draw_glyph");	if (srcx || srcy) {		puts("ui_draw_glyph: fixme: expecting srcx, srcy to be 0\n");		return;	}	// check it is inside the clip area		if (x + cx < clip_rect.x || x > clip_rect.x + clip_rect.w	    || y + cy< clip_rect.y || y > clip_rect.y + clip_rect.h)		return;		//	printf("%i, %i, %i, %i, (%i, %i)\n", x, y, cx, cy);		SDL_LockSurface(screen);	data = screen->pixels + y * screen->pitch + x;	if (mixmode == MIX_TRANSPARENT) {		for (y1=0; y1<cy; ++y1) {			unsigned char *data2 = data;						for (x1=0; x1<cx; ++x1) {				if (*glyphdata++)					*data2 = fgcolour;				++data2;			}						data += screen->pitch;		}	} else {		for (y1=0; y1<cy; ++y1) {			unsigned char *data2 = data;						for (x1=0; x1<cx; ++x1) {				*data2++ = *glyphdata++ ? fgcolour : bgcolour;			}						data += screen->pitch;		}	}				SDL_UnlockSurface(screen);}voidui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,	     int clipx, int clipy, int clipcx, int clipcy,	     int boxx, int boxy, int boxcx, int boxcy,	     int bgcolour, int fgcolour, uint8 *text, uint8 length){	FONTGLYPH *glyph;	SDL_Rect rect;	int i, offset;	if (boxcx > 1)	{		SDL_Rect rect = {boxx, boxy, boxcx, boxcy};		SDL_FillRect(screen, &rect, bgcolour);	}	else if (mixmode == MIX_OPAQUE)	{		SDL_Rect rect = {clipx, clipy, clipcx, clipcy};		SDL_FillRect(screen, &rect, bgcolour);	}	/* Paint text, character by character */	for (i = 0; i < length; i++)	{		glyph = cache_get_font(font, text[i]);		if (!(flags & TEXT2_IMPLICIT_X))		{			offset = text[++i];			if (offset & 0x80)				offset = ((offset & 0x7f) << 8) | text[++i];			if (flags & TEXT2_VERTICAL)				y += offset;			else				x += offset;		}		if (glyph != NULL)		{			ui_draw_glyph(mixmode, x + (short) glyph->offset,				      y + (short) glyph->baseline,				      glyph->width, glyph->height,				      glyph->pixmap, 0, 0,				      bgcolour, fgcolour);			if (flags & TEXT2_IMPLICIT_X)				x += glyph->width;		}	}}voidui_desktop_save(uint32 offset, int x, int y, int cx, int cy){	char *p;	printf("save %i %i %i %i %i\n", offset, x, y, cx, cy);		SDL_LockSurface(screen);	p = screen->pixels + y * screen->pitch + x;		cache_put_desktop(offset, cx, cy, screen->pitch,			  1, p);		SDL_UnlockSurface(screen);}voidui_desktop_restore(uint32 offset, int x, int y, int cx, int cy){	char *data, *p;	int y1;		printf("restore %i, %i, %i, %i, %i\n", offset, x, y, cx, cy);	data = cache_get_desktop(offset, cx, cy, 1);	if (!data)		return;		SDL_LockSurface(screen);	p = screen->pixels + y * screen->pitch + x;	for (y1=cy; y1 > 0; --y1,		     p += screen->pitch,		     data += cx) {		memcpy(p, data, cx);	}	SDL_UnlockSurface(screen);	add_update_rect(x, y, cx, cy);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -