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

📄 x.c

📁 ELinks is an advanced and well-established feature-rich text mode web (HTTP/FTP/..) browser. ELinks
💻 C
📖 第 1 页 / 共 4 页
字号:
/* x.c * (c) 2002 Petr 'Brain' Kulhavy * This file is a part of the Links program, released under GPL. *//* Takovej mensi problemek se scrollovanim: *  * Mikulas a Xy zpusobili, ze scrollovani a prekreslovani je asynchronni. To znamena, ze * je v tom peknej bordylek. Kdyz BFU scrollne s oknem, tak se zavola funkce scroll. Ta * posle Xum XCopyArea (prekopiruje prislusny kus okna) a vygeneruje eventu * (GraphicsExpose) na postizenou (odkrytou) oblast. Funkce XCopyArea pripadne vygeneruje * dalsi GraphicsExpose eventu na postizenou oblast, ktera se muze objevit, kdyz je * linksove okno prekryto jinym oknem.  * * Funkce scroll skonci. V event handleru se nekdy v budoucnosti (treba za tyden) * zpracuji eventy od Xu, mezi nimi i GraphicsExpose - tedy prekreslovani postizenych * oblasti. * * Problem je v tom, ze v okamziku, kdy scroll skonci, neni obrazovka prekreslena do * konzistentniho stavu (misty je garbaz) a navic se muze volat dalsi scroll. Tedy * XCopyArea muze posunout garbaz nekam do cudu a az se dostane na radu prekreslovani * postizenych oblasti, garbaz se uz nikdy neprekresli. * * Ja jsem navrhoval udelat scrollovani synchronni, to znamena, ze v okamziku, kdy scroll * skonci, bude okno v konzistentnim stavu. To by znamenalo volat ze scrollu zpracovavani * eventu (alespon GraphicsExpose). To by ovsem nepomohlo, protoze prekreslovaci funkce * neprekresluje, ale registruje si bottom halfy a podobny ptakoviny a prekresluje az * nekdy v budoucnosti. Navic Mikulas rikal, ze prekreslovaci funkce muze generovat dalsi * prekreslovani (sice jsem nepochopil jak, ale hlavne, ze je vecirek), takze by to * neslo. * * Proto Mikulas vymyslel genialni tah - takzvany "genitah". Ve funkci scroll se projede * fronta eventu od Xserveru a vyberou se GraphicsExp(l)ose eventy a ulozi se do zvlastni * fronty. Ve funkci na zpracovani Xovych eventu se zpracuji eventy z teto fronty. Na * zacatku scrollovaci funkce se projedou vsechny eventy ve zvlastni fronte a updatuji se * jim souradnice podle prislusneho scrollu. *  * Na to jsem ja vymyslel uzasnou vymluvu: co kdyz 1. scroll vyrobi nejake postizene * oblasti a 2. scroll bude mit jinou clipovaci oblast, ktera bude tu postizenou oblast * zasahovat z casti. Tak to se bude jako ta postizena oblast stipat na casti a ty casti * se posunou podle toho, jestli jsou zasazene tim 2. scrollem? Tim jsem ho utrel, jak * zpoceny celo.  *  * Takze se to nakonec udela tak, ze ze scrollu vratim hromadu rectanglu, ktere se maji * prekreslit, a Mikulas si s tim udela, co bude chtit. Podobne jako ve svgalib, kde se * vrati 1 a Mikulas si prislusnou odkrytou oblast prekresli sam. Doufam jen, ze to je * posledni verze a ze nevzniknou dalsi problemy. * * Ve funkci scroll tedy pribude argument struct rect_set **. *//* Data od XImage se alokujou pomoci malloc. get_links_icon musi alokovat taky * pomoci malloc. *//* Pozor: po kazdem XSync se musi dat * register_bottom_half(x_process_events, NULL); * jinak to bude cekat na filedescriptoru, i kdyz to ma eventy uz ve fronte. *	-- mikulas */#include "cfg.h"#ifdef GRDRV_X/* #define X_DEBUG *//* #define SC_DEBUG */#if defined(X_DEBUG) || defined(SC_DEBUG)	#define MESSAGE(a) fprintf(stderr,"%s",a);#endif#ifdef TEXT#undef TEXT#endif#include "links.h"/* Mikulas je PRASE: definuje makro "format" a navrch to jeste nechce vopravit */#ifdef format   	#undef format#endif#include <stdlib.h>#include <stdio.h>#include <X11/Xlib.h>#include <X11/X.h>#include <X11/Xutil.h>#include <X11/Xlocale.h>#include <X11/Xatom.h>#ifndef XK_MISCELLANY	#define XK_MISCELLANY#endif#ifndef XK_LATIN1	#define XK_LATIN1#endif#include <X11/keysymdef.h>#ifdef HAVE_LANGINFO_H#include <langinfo.h>#endif#define X_BORDER_WIDTH 4#define X_HASH_TABLE_SIZE 64#define XPIXMAPP(a) ((struct x_pixmapa*)(a))int x_default_window_width;int x_default_window_height;long (*x_get_color_function)(int);void selection_request(XEvent *event);int x_fd;    /* x socket */Display *x_display;   /* display */int x_screen;   /* screen */int x_display_height,x_display_width;   /* screen dimensions */int x_black_pixel,x_white_pixel;  /* white and black pixel */int x_depth,x_bitmap_bpp;   /* bits per pixel and bytes per pixel */int x_bitmap_scanline_pad; /* bitmap scanline_padding in bytes */int x_colors;  /* colors in the palette (undefined when there's no palette) */int x_have_palette;int x_input_encoding;	/* locales encoding */int x_bitmap_bit_order;Window x_root_window, fake_window;GC x_normal_gc,x_copy_gc,x_drawbitmap_gc,x_scroll_gc;Colormap x_colormap;Atom x_delete_window_atom, x_wm_protocols_atom, x_sel_atom, x_targets_atom;Visual* x_default_visual;Pixmap x_icon;extern struct graphics_driver x_driver;static unsigned char *x_driver_param=NULL;static int n_wins;	/* number of windows */#define X_TYPE_PIXMAP 1#define X_TYPE_IMAGE 2struct x_pixmapa{	unsigned char type;	union	{		XImage *image;		Pixmap *pixmap;	}data;};struct{	unsigned char count;	struct graphics_device **pointer;}x_hash_table[X_HASH_TABLE_SIZE];/* string in clipboard is in x_input_encoding */static unsigned char * x_my_clipboard=NULL;/*----------------------------------------------------------------------*//* Tyhle opicarny tu jsou pro zvyseni rychlosti. Flush se nedela pri kazde operaci, ale * rekne se, ze je potreba udelat flush, a zaregistruje se bottom-half, ktery flush * provede. Takze jakmile se vrati rizeni do select smycky, tak se provede flush. */static int flush_in_progress=0;/* prototypes */unsigned char * x_set_palette(void);int x_hscroll(struct graphics_device *, struct rect_set **, int);int x_vscroll(struct graphics_device *, struct rect_set **, int);void *x_prepare_strip(struct bitmap *, int, int);void x_commit_strip(struct bitmap *, int, int);void x_set_window_title(struct graphics_device *, unsigned char *);int x_exec(unsigned char *, int);void x_clear_clipboard(void);static void x_wait_for_event(void){	fd_set rfds;	FD_ZERO(&rfds);	FD_SET(x_fd, &rfds);	select(x_fd+1, &rfds, NULL, NULL, NULL);}static void x_do_flush(void *ignore){	/* kdyz budu mit zaregistrovanej bottom-half na tuhle funkci a nekdo mi	 * tipne Xy, tak se nic nedeje, maximalne se zavola XFlush na blbej	 * display, ale Xy se nepodelaj */	ignore=ignore;	XFlush(x_display);	flush_in_progress=0;}static inline void X_FLUSH(void){	if (!flush_in_progress)	{		register_bottom_half(x_do_flush,NULL);		flush_in_progress=1;	}}static void x_process_events(void *data);static int (*old_error_handler)(Display *, XErrorEvent *) = NULL;static int failure_happened;static int failure_handler(Display *d, XErrorEvent *e){	failure_happened = 1;	return 0;}static void x_prepare_for_failure(void){	if (old_error_handler)		internal("x_prepare_for_failure: double call");	failure_happened = 0;	old_error_handler = XSetErrorHandler(failure_handler);}static int x_test_for_failure(void){	XSync(x_display, 0);	register_bottom_half(x_process_events, NULL);	XSetErrorHandler(old_error_handler);	old_error_handler = NULL;	return failure_happened;}/* suppose l<h */static void x_clip_number(int *n,int l,int h){	if ((*n)<l)*n=l;	if ((*n)>h)*n=h;}unsigned char * x_set_palette(void){	XColor color;	int a,r,g,b;	int tbl0[4]={0,21845,43690,65535};	int tbl1[8]={0,9362,18724,28086,37449,46811,56173,65535};	x_colormap=XCreateColormap(x_display,x_root_window,x_default_visual,AllocAll);	XInstallColormap(x_display,x_colormap);	switch(x_depth)	{		case 4:		for (a=0;a<16;a++)		{			color.red=(a&8)?65535:0;			color.green=tbl0[(a>>1)&3];			color.blue=(a&1)?65535:0;			color.pixel=a;			color.flags=DoRed|DoGreen|DoBlue;			XStoreColor(x_display,x_colormap,&color);		}		break;		case 8:		for (a=0;a<256;a++)		{			color.red=tbl1[(a>>5)&7];			color.green=tbl1[(a>>2)&7];			color.blue=tbl0[a&3];			color.pixel=a;			color.flags=DoRed|DoGreen|DoBlue;			XStoreColor(x_display,x_colormap,&color);		}		break;		case 15:                for (a=0;a<32768;a++){                       	color.red=((a>>10)&31)*(65535/31);                        color.green=((a>>5)&31)*(65535/31);       	                color.blue=(a&31)*(65535/31);			color.pixel=a;			color.flags=DoRed|DoGreen|DoBlue;			XStoreColor(x_display,x_colormap,&color);                }		break;		case 16:                for (a=0;a<65536;a++){                       	color.red=((a>>11)&31)*(65535/31);                        color.green=((a>>5)&63)*(65535/63);       	                color.blue=(a&31)*(65535/31);			color.pixel=a;			color.flags=DoRed|DoGreen|DoBlue;			XStoreColor(x_display,x_colormap,&color);                }		break;		case 24:		for (r=0;r<256;r++)			for (g=0;g<256;g++)				for (b=0;b<256;b++)				{                       			color.red=r<<8;		                        color.green=g<<8;       			                color.blue=b<<8;					color.pixel=(r<<16)+(g<<8)+(b);					color.flags=DoRed|DoGreen|DoBlue;					XStoreColor(x_display,x_colormap,&color);	       		         }					break;	}		X_FLUSH();	return NULL;}static inline int trans_key(unsigned char * str, int table){	if (table==utf8_table){int a; GET_UTF_8(str,a);return a;}	if (*str<128)return *str;	return cp2u(*str,table);}/* translates X keys to links representation *//* return value: 1=valid key, 0=nothing */static int x_translate_key(XKeyEvent *e,int *key,int *flag){	KeySym ks;	static XComposeStatus comp = { NULL, 0 };	static char str[16];	int table=x_input_encoding<0?drv->codepage:x_input_encoding;	int len;	len=XLookupString(e,str,15,&ks,&comp);	str[len>15?15:len]=0;	if (!len) str[0]=ks, str[1]=0;	*flag=0;	*key=0;	/* alt, control, shift ... */	if (e->state&ShiftMask)*flag|=KBD_SHIFT;	if (e->state&ControlMask)*flag|=KBD_CTRL;	if (e->state&Mod1Mask)*flag|=KBD_ALT;	/* alt-f4 */	if (((*flag)&KBD_ALT)&&(ks==XK_F4)){*key=KBD_CTRL_C;*flag=0;return 1;}	/* ctrl-c */	if (((*flag)&KBD_CTRL)&&(ks==XK_c||ks==XK_C)){*key=KBD_CTRL_C;*flag=0;return 1;}		switch (ks)	{		case NoSymbol:		return 0;		case XK_Return:		*key=KBD_ENTER;break;		case XK_BackSpace:	*key=KBD_BS;break;		case XK_KP_Tab:		case XK_Tab:		*key=KBD_TAB;break;		case XK_Escape:		*key=KBD_ESC;break;		case XK_KP_Left:		case XK_Left:		*key=KBD_LEFT;break;		case XK_KP_Right:		case XK_Right:		*key=KBD_RIGHT;break;		case XK_KP_Up:		case XK_Up:		*key=KBD_UP;break;		case XK_KP_Down:		case XK_Down:		*key=KBD_DOWN;break;		case XK_KP_Insert:		case XK_Insert:		*key=KBD_INS;break;		case XK_KP_Delete:		case XK_Delete:		*key=KBD_DEL;break;		case XK_KP_Home:		case XK_Home:		*key=KBD_HOME;break;		case XK_KP_End:		case XK_End:		*key=KBD_END;break;		case XK_KP_Page_Up:		case XK_Page_Up:	*key=KBD_PAGE_UP;break;		case XK_KP_Page_Down:		case XK_Page_Down:	*key=KBD_PAGE_DOWN;break;		case XK_KP_F1:		case XK_F1:		*key=KBD_F1;break;		case XK_KP_F2:		case XK_F2:		*key=KBD_F2;break;		case XK_KP_F3:		case XK_F3:		*key=KBD_F3;break;		case XK_KP_F4:		case XK_F4:		*key=KBD_F4;break;		case XK_F5:		*key=KBD_F5;break;		case XK_F6:		*key=KBD_F6;break;		case XK_F7:		*key=KBD_F7;break;		case XK_F8:		*key=KBD_F8;break;		case XK_F9:		*key=KBD_F9;break;		case XK_F10:		*key=KBD_F10;break;		case XK_F11:		*key=KBD_F11;break;		case XK_F12:		*key=KBD_F12;break;		case XK_KP_Subtract:	*key='-';break;		case XK_KP_Decimal:	*key='.';break;		case XK_KP_Divide:	*key='/';break;		case XK_KP_Space:	*key=' ';break;		case XK_KP_Enter:	*key=KBD_ENTER;break;		case XK_KP_Equal:	*key='=';break;		case XK_KP_Multiply:	*key='*';break;		case XK_KP_Add:		*key='+';break;		case XK_KP_0:		*key='0';break;		case XK_KP_1:		*key='1';break;		case XK_KP_2:		*key='2';break;		case XK_KP_3:		*key='3';break;		case XK_KP_4:		*key='4';break;		case XK_KP_5:		*key='5';break;		case XK_KP_6:		*key='6';break;		case XK_KP_7:		*key='7';break;		case XK_KP_8:		*key='8';break;		case XK_KP_9:		*key='9';break;		default:							if (ks&0x8000)return 0;					*key=((*flag)&KBD_CTRL)?(int)ks&255:trans_key(str,table);					break;					/*		default:		*key=((*flag)&KBD_CTRL)?(int)ks&255:trans_key(str,table);(*flag)&=~KBD_SHIFT;break;		*/	}	return 1;}static void x_hash_table_init(void){	int a;	for (a=0;a<X_HASH_TABLE_SIZE;a++)	{		x_hash_table[a].count=0;		x_hash_table[a].pointer=NULL;	}}static void x_free_hash_table(void){	int a,b;	for (a=0;a<X_HASH_TABLE_SIZE;a++)	{		for (b=0;b<x_hash_table[a].count;b++)			mem_free(x_hash_table[a].pointer[b]);		if (x_hash_table[a].pointer)			mem_free(x_hash_table[a].pointer);	}}/* returns graphics device structure which belonging to the window */static struct graphics_device * x_find_gd(Window *win){	int a,b;	a=(*win)&(X_HASH_TABLE_SIZE-1);	if (!x_hash_table[a].count)return 0;	for (b=0;b<x_hash_table[a].count;b++)	{		if ((*(Window*)((x_hash_table[a].pointer[b])->driver_data))==(*win))		return x_hash_table[a].pointer[b];	}	return 0;}static void x_update_driver_param(int w, int h){	int l=0;	if (n_wins!=1)return;		x_default_window_width=w;	x_default_window_height=h;		if (x_driver_param)mem_free(x_driver_param);	x_driver_param=init_str();	add_num_to_str(&x_driver_param,&l,x_default_window_width);	add_to_str(&x_driver_param,&l,"x");	add_num_to_str(&x_driver_param,&l,x_default_window_height);}/* adds graphics device to hash table */static int x_add_to_table(struct graphics_device* gd){	int a=(*((Window*)(gd->driver_data)))&(X_HASH_TABLE_SIZE-1);	int c=x_hash_table[a].count;	if (!c) {		x_hash_table[a].pointer=mem_alloc(sizeof(struct graphics_device *));	} else {		if ((unsigned)c > MAXINT / sizeof(struct graphics_device *) - 1) overalloc();		x_hash_table[a].pointer=mem_realloc(x_hash_table[a].pointer,(c+1)*sizeof(struct graphics_device *));	}	x_hash_table[a].pointer[c]=gd;	x_hash_table[a].count++;	return 0;}/* removes graphics device from table */static void x_remove_from_table(Window *win){	int a=(*win)&(X_HASH_TABLE_SIZE-1);	int b;	for (b=0;b<x_hash_table[a].count;b++)		if ((*(Window*)((x_hash_table[a].pointer[b])->driver_data))==(*win))		{			memmove(x_hash_table[a].pointer+b,x_hash_table[a].pointer+b+1,(x_hash_table[a].count-b-1)*sizeof(struct graphics_device *));			x_hash_table[a].count--;			x_hash_table[a].pointer=mem_realloc(x_hash_table[a].pointer,x_hash_table[a].count*sizeof(struct graphics_device*));		}}void x_clear_clipboard(void){    if(x_my_clipboard)    {        mem_free(x_my_clipboard);        x_my_clipboard=NULL;    }}static void x_process_events(void *data){	XEvent event;	XEvent last_event;	struct graphics_device *gd;	int last_was_mouse;	int replay_event = 0;

⌨️ 快捷键说明

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