Plan 9 from Bell Labs’s /usr/web/sources/contrib/de0u/root/sys/src/cmd/squeak/Plan9/vm/sqPlan9io.c.bak

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


/*
 * Squeak IO function implementations for Plan9.
 *
 * Author: Alex Franchuk (alex.franchuk@gmail.com)
 */

#include "sq.h"
#include "p9iface.h"

#define _PLAN9_SOURCE

#define EVT_BUFFER_SIZE 256

#include <u.h>
#include <draw.h>
#include <event.h>
#include <cursor.h>
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>

static struct timeval start_time;
static Point          mouse_position;
static int            mouse_button_state = 0;
static sqInputEvent   evts[EVT_BUFFER_SIZE];
static int 			  evts_start = 0,
					  evts_end = 0;
static int            disp_prev_width,
					  disp_prev_height,
					  disp_prev_x,
					  disp_prev_y;
static int            event_semaphore_index;

int timeInit(void) {
	return gettimeofday(&start_time, 0);
}

/* Time */
sqInt ioMSecs(void) {
	struct timeval now;
	gettimeofday(&now, 0);

	if ((now.tv_usec -= start_time.tv_usec) < 0) {
	now.tv_usec += 1000000;
	now.tv_sec -= 1;
	}
	now.tv_sec -= start_time.tv_sec;
	return (now.tv_usec / 1000 + now.tv_sec * 1000);
}

sqInt ioMicroMSecs(void) {
	return ioMSecs();
}

/*sqLong ioMicroSeconds(void) {*/
	/*return 0;*/
/*}*/

/*sqInt ioUtcWithOffset(sqLong*, int*) {*/
	/*return 0;*/
/*}*/

sqInt ioSeconds(void) {
	return 0;
}

/* Miscellaneous */
sqInt ioBeep(void) {
	printf("beep\n");
	return 0;
}

sqInt ioExit(void) {
	return ioExitWithErrorCode(0);
}

sqInt ioExitWithErrorCode(int code) {
	printf("exit %d\n",code);
	return 0;
}

sqInt ioRelinquishProcessorForMicroseconds(sqInt microSeconds) {
	return 0;
}

sqInt ioDisablePowerManager(sqInt disableIfNonZero) {
	return true;
}

/* Display */
sqInt ioForceDisplayUpdate(void) {
	return true;
}

sqInt ioFormPrint(sqInt bitsAddr, sqInt width, sqInt height, sqInt depth,
		  double hScale, double vScale, sqInt landscapeFlag) {
	return 0;
}

sqInt ioSetFullScreen(sqInt fullScreen) {
	if (fullScreen) {
		ushort w = screen->r.max.x - screen->r.min.x;
		ushort h = screen->r.max.y - screen->r.min.y;
		disp_prev_x = screen->r.min.x;
		disp_prev_y = screen->r.min.y;
		disp_prev_width = w;
		disp_prev_height = h;
	}
	else {
		positionWindow(disp_prev_x, disp_prev_y);
	}
	return ioSetDisplayMode(disp_prev_width, disp_prev_height, screen->depth, fullScreen);
}

sqInt ioScreenSize(void) {
	ushort w = screen->r.max.x - screen->r.min.x;
	ushort h = screen->r.max.y - screen->r.min.y;
	return (w<<16)|h;
}

sqInt ioScreenDepth(void) {
	return 32;
}

sqInt ioSetCursor(sqInt cursorBitsIndex, sqInt offsetX, sqInt offsetY) {
	printf("setcursor\n");
	return 0;
}

sqInt ioSetCursorWithMask(sqInt cursorBitsIndex, sqInt cursorMaskIndex, sqInt offsetX, sqInt offsetY) {
	return 0;
}

sqInt ioSetCursorARGB(sqInt cursorBitsIndex, sqInt extentX, sqInt extentY, sqInt offsetX, sqInt offsetY) {
	return 0;
}

static void sqToP9Bits(uchar* sqBits, uchar* p9Bits, int width, int height) {
	for (int y = 0; y < height; y++)
		for (int x = 0; x < width; x++) {
			p9Bits[(y*width+x)*3] = sqBits[(y*width+x)*4+2];
			p9Bits[(y*width+x)*3+1] = sqBits[(y*width+x)*4+1];
			p9Bits[(y*width+x)*3+2] = sqBits[(y*width+x)*4];
		}
}

sqInt ioShowDisplay(sqInt dispBitsIndex, sqInt width, sqInt height, sqInt depth,
		    sqInt affectedL, sqInt affectedR, sqInt affectedT, sqInt affectedB) {
	Rectangle r;
	r.min.x = affectedL;
	r.max.x = affectedR;
	r.min.y = affectedT;
	r.max.y = affectedB;
	ulong chan;
	uchar* dispBits = (uchar*)pointerForOop(dispBitsIndex);
	uchar* buf = (uchar*)malloc(width*height*3);
	if (buf == 0)
		return 0;

	sqToP9Bits(dispBits, buf, width, height);

	switch (depth) {
		case 1:
			chan = GREY1;
			break;
		case 2:
			chan = GREY2;
			break;
		case 4:
			chan = CMAP8;
			break;
		case 8:
			chan = CMAP8;
			break;
		case 16:
			chan = RGB16;
			break;
		case 32:
			chan = RGB24;
			break;
		default:
			return -1;
	}
	Image* s = allocimage(display, r, chan, 0, DNofill);
	if (s == 0) {
		return -1;
	}
	Image* mask = allocimage(display, r, chan, 0, DOpaque);
	if (mask == 0) {
		freeimage(s);
		return -1;
	}

	//Offset by one to make _rgb become rgba
	loadimage(s, r, buf, width*height*4);

	Point e; e.x = -r.min.x; e.y = -r.min.y;
	draw(screen, screen->r, s, mask, e);

	freeimage(mask);
	freeimage(s);

	free(buf);

	return 1;
}

sqInt ioHasDisplayDepth(sqInt depth) {
	if (depth == 32)
		return 1;
	else return 0;
}

sqInt ioSetDisplayMode(sqInt width, sqInt height, sqInt depth, sqInt fullscreenFlag) {
	if (fullscreenFlag) {
		Rectangle ssize = display->image->r;
		positionWindow(ssize.min.x,ssize.min.y);
		width = ssize.max.x - ssize.min.x - 1;
		height = ssize.max.y - ssize.min.y - 1;
	}
	resizeWindow(width,height);
	eresized(1);
	return 0;
}

/* Mouse/Keyboard */
sqInt ioGetButtonState(void) {
	int left = mouse_button_state & 1;
	int middle = (mouse_button_state & 2) >> 1;
	int right = (mouse_button_state & 4) >> 2;
	return RedButtonBit*left | YellowButtonBit*middle | BlueButtonBit*right;
}

sqInt ioMousePoint(void) {
	return ((mouse_position.x & 0xFFFF) << 16) | (mouse_position.y & 0xFFFF);
}

sqInt ioGetKeystroke(void) {
	int k = evts_start;
	while (k < evts_end) {
		if (evts[k].type == EventTypeKeyboard) {
			evts_start = (k+1) % EVT_BUFFER_SIZE;
			return ((sqKeyboardEvent)evts[k]).charCode;
		}
		k = (k+1) % EVT_BUFFER_SIZE;
	}
	return 0;
}

sqInt ioPeekKeystroke(void) {
	int k = evts_start;
	while (k < evts_end) {
		if (evts[k].type == EventTypeKeyboard) {
			return ((sqKeyboardEvent)evts[k]).charCode;
		}
		k = (k+1) % EVT_BUFFER_SIZE;
	}
	return 0;
}

sqInt ioProcessEvents(void) {
	while (ecanmouse() || ecankbd()) {
		Event e;
		int key = event(&e);
		if (key & Emouse) {
			//Process mouse event
			mouse_position.x = e.mouse.xy.x - screen->r.min.x;
			mouse_position.y = e.mouse.xy.y - screen->r.min.y;
			mouse_button_state = e.mouse.buttons;
			if ((evts_end+2)%EVT_BUFFER_SIZE != evts_start) {
				sqMouseEvent* evt = (sqMouseEvent*)&evts[evts_end++];
				evt->type = EventTypeMouse;
				evt->timeStamp = ioMSecs();
				evt->x = mouse_position.x;
				evt->y = mouse_position.y;
				evt->buttons = ioGetButtonState();
				evt->modifiers = 0;
			}
			signalSemaphoreWithIndex(event_semaphore_index);
		}
		if (key & Ekeyboard) {
			//Process keyboard event
			if ((evts_end+2)%EVT_BUFFER_SIZE != evts_start) {
				sqKeyboardEvent* evt = (sqKeyboardEvent*)&evts[evts_end++];
				evt->type = EventTypeKeyboard;
				evt->timeStamp = ioMSecs();
				evt->charCode = e.kbdc;
				evt->pressCode = EventKeyChar;
				evt->modifiers = 0;
			}
			signalSemaphoreWithIndex(event_semaphore_index);
		}
	}
	
	return 0;
}

sqInt ioSetInputSemaphore(sqInt semaIndex) {
	if (semaIndex == 0) {
		success(0);
	}
	else {
		event_semaphore_index = semaIndex;
	}
	return true;
}

sqInt ioGetNextEvent(sqInputEvent *evt) {
	if (evts_start != evts_end) {
		memcpy(evt, &evts[evts_start++], sizeof(sqInputEvent));
		evts_start %= EVT_BUFFER_SIZE;
		return true;
	}
	return false;
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.