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

📄 pmshell.c

📁 ELinks is an advanced and well-established feature-rich text mode web (HTTP/FTP/..) browser. ELinks
💻 C
📖 第 1 页 / 共 2 页
字号:
/* pmshell.c * PMShell graphics driver * (c) 2002 Mikulas Patocka * This file is a part of the Links program, released under GPL. */#include "cfg.h"#if 0#define debug_call(x) printf x; fflush(stdout);#else#define debug_call(x)#endif#ifdef GRDRV_PMSHELL#include "links.h"extern struct graphics_driver pmshell_driver;#define INCL_DOS#define INCL_GPI#define INCL_WIN#include <os2.h>#include <process.h>#include <sys/builtin.h>#include <sys/fmutex.h>_fmutex pm_mutex;#define pm_lock_init	_fmutex_create(&pm_mutex, 0)#define pm_lock		_fmutex_request(&pm_mutex, _FMR_IGNINT)#define pm_unlock	_fmutex_release(&pm_mutex)unsigned char *pm_class_name = "links";unsigned char *pm_msg_class_name = "links.msg";ULONG pm_frame = (FCF_TITLEBAR | FCF_SYSMENU | FCF_SIZEBORDER | FCF_MINMAX | FCF_SHELLPOSITION | FCF_TASKLIST | FCF_NOBYTEALIGN);ULONG pm_msg_frame = 0;MRESULT EXPENTRY pm_window_proc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);MRESULT EXPENTRY pm_msg_proc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);#define E_KEY		1#define E_MOUSE		2#define E_REDRAW	3#define E_RESIZE	4struct pm_event {	struct pm_event *next;	struct pm_event *prev;	int type;	int x1, y1, x2, y2;};struct pm_window {	struct pm_window *next;	struct pm_window *prev;	int x, y;	int in;	struct pm_window *nxt;	struct pm_window **prv;	HPS ps;	HWND h;	HWND hc;	struct graphics_device *dev;	int button;	unsigned lastpos;	struct list_head queue;};#define WIN_HASH	64struct pm_window *pm_windows[WIN_HASH];static void pm_hash_window(struct pm_window *win){	int pos = win->hc & (WIN_HASH - 1);	win->prv = &pm_windows[pos];	if ((win->nxt = pm_windows[pos])) pm_windows[pos]->prv = &win->nxt;	pm_windows[pos] = win;}static void pm_unhash_window(struct pm_window *win){	if (win->nxt) win->nxt->prv = win->prv;	*win->prv = win->nxt;}static inline struct pm_window *pm_lookup_window(HWND h){	struct pm_window *win;	for (win = pm_windows[h & (WIN_HASH - 1)]; win && win->hc != h; win = win->nxt) ;	return win;}#define pm_win(dev) ((struct pm_window *)dev->driver_data)int pm_pipe[2];HEV pm_sem;ULONG pm_sem_dummy;#define pm_wait	do {					\	DosWaitEventSem(pm_sem, SEM_INDEFINITE_WAIT);	\	DosResetEventSem(pm_sem, &pm_sem_dummy);	\} while (0)#define pm_signal DosPostEventSem(pm_sem)unsigned char *pm_not_ses = "Not in a pmshell session.\n";unsigned char *pm_status;HAB hab_disp;HAB hab;HMQ hmq;HWND hwnd_msg;HPS hps_msg;HDC hdc_mem;HPS hps_mem;int pm_cp;struct list_head pm_event_windows = { &pm_event_windows, &pm_event_windows };static void pm_send_event(struct pm_window *win, int t, int x1, int y1, int x2, int y2){	/* must be called with pm_lock */	struct pm_event *ev;	if ((ev = malloc(sizeof(struct pm_event)))) {		ev->type = t;		ev->x1 = x1, ev->y1 = y1;		ev->x2 = x2, ev->y2 = y2;		if (!win->in) {			if (list_empty(pm_event_windows)) write(pm_pipe[1], "x", 1);			add_to_list(pm_event_windows, win);			win->in = 1;		}		add_to_list(win->queue, ev);	}}static void pm_send_mouse_event(struct pm_window *win, int x1, int y1, int b){	if (!list_empty(win->queue)) {		struct pm_event *last = win->queue.next;		if (last->type == E_MOUSE && last->x2 == b) {			last->x1 = x1;			last->y1 = y1;			return;		}	}	pm_send_event(win, E_MOUSE, x1, y1, b, 0);}static void pm_cancel_event(struct pm_window *win, int t, struct pm_event **pev){	struct pm_event *ev;	if (pev) *pev = NULL;	foreachback(ev, win->queue) if (ev->type == t) {		if (pev) *pev = ev;		else {			del_from_list(ev);			free(ev);		}		return;	}}static void pm_resize(struct pm_window *win, RECTL *r){	struct pm_event *ev;	win->x = r->xRight;	win->y = r->yTop;	pm_cancel_event(win, E_REDRAW, NULL);	pm_cancel_event(win, E_RESIZE, &ev);	if (ev) {		ev->x2 = r->xRight;		ev->y2 = r->yTop;	} else pm_send_event(win, E_RESIZE, 0, 0, r->xRight, r->yTop);}static void pm_redraw(struct pm_window *win, RECTL *r){	struct pm_event *ev;	pm_cancel_event(win, E_RESIZE, &ev);	if (ev) return;	pm_cancel_event(win, E_REDRAW, &ev);	if (ev) {		if (r->xLeft < ev->x1) ev->x1 = r->xLeft;		if (r->xRight > ev->x2) ev->x2 = r->xRight;		if (win->y - r->yTop < ev->y1) ev->y1 = win->y - r->yTop;		if (win->y - r->yBottom > ev->y2) ev->y2 = win->y - r->yBottom;		return;	}	pm_send_event(win, E_REDRAW, r->xLeft, win->y - r->yTop, r->xRight, win->y - r->yBottom);}#define N_VK	0x42struct os2_key pm_vk_table[N_VK] = {	{0, 0}, {0, 0}, {0, 0}, {0, 0}, {KBD_CTRL_C, 0}, {KBD_BS, 0}, {KBD_TAB, 0}, {KBD_TAB, KBD_SHIFT},	{KBD_ENTER, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {KBD_ESC, 0},	{' ', 0}, {KBD_PAGE_UP, 0}, {KBD_PAGE_DOWN, 0}, {KBD_END, 0}, {KBD_HOME, 0}, {KBD_LEFT, 0}, {KBD_UP, 0}, {KBD_RIGHT, 0},	{KBD_DOWN, 0}, {0, 0}, {KBD_INS, 0}, {KBD_DEL, 0}, {0, 0}, {0, 0}, {KBD_ENTER, 0}, {0, 0},	{KBD_F1, 0}, {KBD_F2, 0}, {KBD_F3, 0}, {KBD_F4, 0}, {KBD_F5, 0}, {KBD_F6, 0}, {KBD_F7, 0}, {KBD_F8, 0},	{KBD_F9, 0}, {KBD_F10, 0}, {KBD_F11, 0}, {KBD_F12, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},	{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},	{0, 0}, {KBD_DEL, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},	{0, 0}, {0, 0}};MRESULT EXPENTRY pm_window_proc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2){	int k_usch, k_usvk, k_fsflags;	int scancode;	int key, flags;	struct pm_window *win;	RECTL wr, ur;	/*fprintf(stderr, "%08x %08x %08x\n", (int)msg, (int)mp1, (int)mp2);*/	switch (msg) {		case WM_PAINT:			pm_lock;			WinQueryUpdateRect(hwnd, &ur);			WinQueryWindowRect(hwnd, &wr);			WinValidateRect(hwnd, &ur, FALSE);			if (!(win = pm_lookup_window(hwnd))) {				pm_unlock;				return 0;			}			if (wr.xRight != win->x || wr.yTop != win->y) pm_resize(win, &wr);			else pm_redraw(win, &ur);			pm_unlock;			return 0;		case WM_CLOSE:		case WM_QUIT:			pm_lock;			if (!(win = pm_lookup_window(hwnd))) {				pm_unlock;				return 0;			}			pm_send_event(win, E_KEY, KBD_CTRL_C, 0, 0, 0);			pm_unlock;			return 0;		case WM_CHAR:			k_fsflags = (int)mp1;			scancode = ((unsigned long)mp1 >> 24) & 0xff;			if (k_fsflags & (KC_KEYUP | KC_DEADKEY | KC_INVALIDCOMP)) return 0;			k_usch = (int)mp2 & 0xffff;			k_usvk = ((int)mp2 >> 16) & 0xffff;			/*printf("%08x, %08x\n", mp1, mp2);fflush(stdout);*/			flags = (k_fsflags & KC_SHIFT ? KBD_SHIFT : 0) | (k_fsflags & KC_CTRL ? KBD_CTRL : 0) | (k_fsflags & KC_ALT ? KBD_ALT : 0);			if (k_fsflags & KC_ALT && ((scancode >= 0x47 && scancode <= 0x49) || (scancode >= 0x4b && scancode <= 0x4d) || (scancode >= 0x4f && scancode <= 0x52))) return 0;			if ((k_fsflags & (KC_VIRTUALKEY | KC_CHAR)) == KC_VIRTUALKEY) {				if (k_usvk < N_VK && (key = pm_vk_table[k_usvk].x)) {					flags |= pm_vk_table[k_usvk].y;					if (key == KBD_CTRL_C) flags &= ~KBD_CTRL;					goto s;				}			}			if (k_usch & 0xff) {				key = k_usch & 0xff;				if (!(flags & KBD_CTRL)) {					if (key == 0x0d) key = KBD_ENTER;					if (key == 0x08) key = KBD_BS;					if (key == 0x09) key = KBD_TAB;					if (key == 0x1b) key = KBD_ESC;				}				if (key >= 0 && key < ' ') key += '@', flags |= KBD_CTRL;			} else key = os2xtd[k_usch >> 8].x, flags |= os2xtd[k_usch >> 8].y;			if ((key & 0xdf) == 'C' && (flags & KBD_CTRL)) key = KBD_CTRL_C, flags &= ~KBD_CTRL;			s:			if (!key) return 0;			/*if (key >= 0) flags &= ~KBD_SHIFT;*/			if (key >= 0x80 && pm_cp) {				if ((key = cp2u(key, pm_cp)) < 0) return 0;			}			pm_lock;			if (!(win = pm_lookup_window(hwnd))) {				pm_unlock;				return 0;			}			pm_send_event(win, E_KEY, key, flags, 0, 0);			pm_unlock;			return 0;		case WM_BUTTON1DOWN:			pm_lock;			if (!(win = pm_lookup_window(hwnd))) { pm_unlock; break; }			win->button |= 1 << B_LEFT;			win->lastpos = (unsigned)mp1;			pm_send_event(win, E_MOUSE, (unsigned)mp1 & 0xffff, win->y - ((unsigned)mp1 >> 16), B_DOWN | B_LEFT, 0);			pm_unlock;			break;		case WM_BUTTON2DOWN:			pm_lock;			if (!(win = pm_lookup_window(hwnd))) { pm_unlock; break; }			win->button |= 1 << B_RIGHT;			win->lastpos = (unsigned)mp1;			pm_send_event(win, E_MOUSE, (unsigned)mp1 & 0xffff, win->y - ((unsigned)mp1 >> 16), B_DOWN | B_RIGHT, 0);			pm_unlock;			break;		case WM_BUTTON3DOWN:			pm_lock;			if (!(win = pm_lookup_window(hwnd))) { pm_unlock; break; }			win->button |= 1 << B_MIDDLE;			win->lastpos = (unsigned)mp1;			pm_send_event(win, E_MOUSE, (unsigned)mp1 & 0xffff, win->y - ((unsigned)mp1 >> 16), B_DOWN | B_MIDDLE, 0);			pm_unlock;			break;		case WM_BUTTON1UP:		case WM_BUTTON1MOTIONEND:			pm_lock;			if (!(win = pm_lookup_window(hwnd))) { pm_unlock; break; }			if (win->button & (1 << B_LEFT)) pm_send_event(win, E_MOUSE, (unsigned)mp1 & 0xffff, win->y - ((unsigned)mp1 >> 16), B_UP | B_LEFT, 0);			win->button &= ~(1 << B_LEFT);			win->lastpos = (unsigned)mp1;			pm_unlock;			break;		case WM_BUTTON2UP:		case WM_BUTTON2MOTIONEND:			pm_lock;			if (!(win = pm_lookup_window(hwnd))) { pm_unlock; break; }			if (win->button & (1 << B_RIGHT)) pm_send_event(win, E_MOUSE, (unsigned)mp1 & 0xffff, win->y - ((unsigned)mp1 >> 16), B_UP | B_RIGHT, 0);			win->button &= ~(1 << B_RIGHT);			win->lastpos = (unsigned)mp1;			pm_unlock;			break;		case WM_BUTTON3UP:		case WM_BUTTON3MOTIONEND:			pm_lock;			if (!(win = pm_lookup_window(hwnd))) { pm_unlock; break; }			if (win->button & (1 << B_MIDDLE)) pm_send_event(win, E_MOUSE, (unsigned)mp1 & 0xffff, win->y - ((unsigned)mp1 >> 16), B_UP | B_MIDDLE, 0);			win->button &= ~(1 << B_MIDDLE);			win->lastpos = (unsigned)mp1;			pm_unlock;			break;		case WM_MOUSEMOVE:			pm_lock;			if (!(win = pm_lookup_window(hwnd))) { pm_unlock; break; }			if (win->lastpos == (unsigned)mp1) { pm_unlock; break; }			win->lastpos = (unsigned)mp1;			pm_send_mouse_event(win, (unsigned)mp1 & 0xffff, win->y - ((unsigned)mp1 >> 16), (win->button ? B_DRAG : B_MOVE) | (win->button & (1 << B_LEFT) ? B_LEFT : win->button & (1 << B_MIDDLE) ? B_MIDDLE : win->button & (1 << B_RIGHT) ? B_RIGHT : 0));			pm_unlock;			break;		case WM_VSCROLL:			pm_lock;			if (!(win = pm_lookup_window(hwnd))) { pm_unlock; break; }			if ((unsigned)mp2 == SB_LINEUP << 16 || (unsigned)mp2 == SB_LINEDOWN << 16) pm_send_event(win, E_MOUSE, win->lastpos & 0xffff, win->y - (win->lastpos >> 16), ((unsigned)mp2 == SB_LINEUP << 16 ? B_WHEELUP1 : B_WHEELDOWN1) | B_MOVE, 0);			pm_unlock;			break;		case WM_HSCROLL:			pm_lock;			if (!(win = pm_lookup_window(hwnd))) { pm_unlock; break; }			if ((unsigned)mp2 == SB_LINELEFT << 16 || (unsigned)mp2 == SB_LINERIGHT << 16) pm_send_event(win, E_MOUSE, win->lastpos & 0xffff, win->y - (win->lastpos >> 16), ((unsigned)mp2 == SB_LINELEFT << 16 ? B_WHEELLEFT1 : B_WHEELRIGHT1) | B_MOVE, 0);			pm_unlock;			break;	}	return WinDefWindowProc(hwnd, msg, mp1, mp2);}int pm_thread_shutdown;#define MSG_CREATE_WINDOW	1#define MSG_DELETE_WINDOW	2#define MSG_SET_WINDOW_TITLE	3#define MSG_SHUTDOWN_THREAD	4struct title_set {	struct pm_window *win;	unsigned char *text;};MRESULT EXPENTRY pm_msg_proc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2){	struct title_set *w;	if (msg == WM_USER) switch ((int)mp1) {		struct pm_window *win;		case MSG_CREATE_WINDOW:			win = mp2;			win->h = WinCreateStdWindow(HWND_DESKTOP, WS_VISIBLE, &pm_frame, pm_class_name, "Links", 0, 0, 0, &win->hc);			WinSetWindowPos(win->h, 0, 0, 0, 0, 0, SWP_ACTIVATE);			pm_lock;			pm_signal;			return 0;		case MSG_DELETE_WINDOW:			win = mp2;			WinDestroyWindow(win->h);			pm_lock;			pm_signal;			return 0;		case MSG_SET_WINDOW_TITLE:			w = mp2;			WinSetWindowText(w->win->h, w->text);			pm_lock;			pm_signal;			return 0;		case MSG_SHUTDOWN_THREAD:			pm_thread_shutdown = 1;			return 0;	}	return WinDefWindowProc(hwnd, msg, mp1, mp2);}static void pm_send_msg(int msg, void *param){	WinPostMsg(hwnd_msg, WM_USER, (MPARAM)msg, (MPARAM)param);	pm_wait;}static void pm_dispatcher(void *p){	QMSG msg;	pm_status = NULL;	/*DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 1, 0);*/	DosSetPriority(PRTYS_THREAD, PRTYC_NOCHANGE, 1, 0);	if ((hab_disp = WinInitialize(0)) == NULLHANDLE) {		pm_status = "WinInitialize failed in pm thread.\n";		goto fail;	}	if ((hmq = WinCreateMsgQueue(hab_disp, 0)) == NULLHANDLE) {		ERRORID e = WinGetLastError(hab_disp);		if ((e & 0xffff) == PMERR_NOT_IN_A_PM_SESSION) pm_status = pm_not_ses;		else pm_status = "WinCreateMsgQueue failed in pm thread.\n";		goto fail1;	}	if ((pm_cp = WinQueryCp(hmq))) {		unsigned char a[64];		snprint(a, 64, pm_cp);		if ((pm_cp = get_cp_index(a)) < 0 || is_cp_special(pm_cp)) pm_cp = 0;	}	/*{		ULONG cp_list[100];		int n, i;		debug("WinQueryCp: %d", WinQueryCp(hmq));		n = WinQueryCpList(hab_disp, 100, cp_list);		debug("%d", n);		for (i = 0; i < n; i++) fprintf(stderr, "%d, ", cp_list[i]);	}*/	if (WinRegisterClass(hab_disp, pm_class_name, pm_window_proc, CS_SIZEREDRAW, 0) == FALSE) {		pm_status = "WinRegisterClass failed for window.\n";		goto fail2;	}	if (WinRegisterClass(hab_disp, pm_msg_class_name, pm_msg_proc, 0, 0) == FALSE) {		pm_status = "WinRegisterClass failed for msg window.\n";		goto fail3;	}	if ((hwnd_msg = WinCreateStdWindow(HWND_DESKTOP, 0, &pm_msg_frame, pm_msg_class_name, NULL, 0, 0, 0, NULL)) == NULLHANDLE) {		pm_status = "Could not create msg window.\n";		goto fail4;	}	if ((hps_msg = WinGetPS(hwnd_msg)) == NULLHANDLE) {		pm_status = "Could not get msg window ps.\n";		goto fail5;	}	pm_signal;	while (!pm_thread_shutdown) {		WinGetMsg(hab_disp, &msg, 0L, 0, 0);		WinDispatchMsg(hab_disp, &msg);	}			WinReleasePS(hps_msg);	fail5:	WinDestroyWindow(hwnd_msg);	fail4:	fail3:	fail2:	WinDestroyMsgQueue(hmq);	fail1:	WinTerminate(hab);	fail:	pm_signal;	return;}static void pm_pipe_error(void *p){	error("exception on pm pipe");	set_handlers(pm_pipe[0], NULL, NULL, NULL, NULL);}static void pm_handler(void *p){	unsigned char c;	struct pm_window *win = NULL;	struct pm_event *ev = NULL;	pm_lock;	if (!list_empty(pm_event_windows)) {		win = pm_event_windows.prev;		if (!list_empty(win->queue)) {			ev = win->queue.prev;			del_from_list(ev);		}		if (list_empty(win->queue)) {			del_from_list(win);			win->in = 0;		}	}	if (list_empty(pm_event_windows)) {		if (read(pm_pipe[0], &c, 1) != 1) pm_pipe_error(NULL);	}	pm_unlock;	if (!ev) return;	switch (ev->type) {		struct rect r;		case E_KEY:			if (win->dev->keyboard_handler)				win->dev->keyboard_handler(win->dev, ev->x1, ev->y1);			break;		case E_MOUSE:			if (win->dev->mouse_handler)				win->dev->mouse_handler(win->dev, ev->x1, ev->y1, ev->x2);			break;		case E_REDRAW:			if (win->dev->redraw_handler) {				r.x1 = ev->x1; r.y1 = ev->y1;				r.x2 = ev->x2; r.y2 = ev->y2;				win->dev->redraw_handler(win->dev, &r);			}			break;		case E_RESIZE:			win->dev->size.x2 = ev->x2;			win->dev->size.y2 = ev->y2;			if (win->dev->resize_handler) {				win->dev->resize_handler(win->dev);			}	}	free(ev);}BITMAPINFO *pm_bitmapinfo;int pm_bitmap_count;pid_t pm_child_pid;static void pm_sigcld(void *p){	int st;	pid_t w;	if (!(w = waitpid(pm_child_pid, &st, WNOHANG))) return;	if (w > 0) exit(st);	else exit(RET_FATAL);}int pm_sin, pm_sout, pm_serr, pm_ip[2], pm_op[2], pm_ep[2];int pm_cons_ok = 0;	static void pm_setup_console(void)

⌨️ 快捷键说明

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