[Vm-dev] [commit] r2573 - add Scratch, Unicode and WeDo plugins

commits at squeakvm.org commits at squeakvm.org
Mon Jul 30 22:05:14 UTC 2012


Author: piumarta
Date: 2012-07-30 15:05:14 -0700 (Mon, 30 Jul 2012)
New Revision: 2573

Added:
   trunk/platforms/unix/plugins/ScratchPlugin/
   trunk/platforms/unix/plugins/ScratchPlugin/unixScratchOps.c
   trunk/platforms/unix/plugins/ScratchPlugin/unixSeriaPort2Ops.c
   trunk/platforms/unix/plugins/UnicodePlugin/
   trunk/platforms/unix/plugins/UnicodePlugin/README.UnicodePlugin
   trunk/platforms/unix/plugins/UnicodePlugin/UnicodeOps-linux.c
   trunk/platforms/unix/plugins/UnicodePlugin/config.cmake
   trunk/platforms/unix/plugins/WeDoPlugin/
   trunk/platforms/unix/plugins/WeDoPlugin/WeDoLinux.c
   trunk/platforms/unix/plugins/WeDoPlugin/config.cmake
Log:
add Scratch, Unicode and WeDo plugins

Added: trunk/platforms/unix/plugins/ScratchPlugin/unixScratchOps.c
===================================================================
--- trunk/platforms/unix/plugins/ScratchPlugin/unixScratchOps.c	                        (rev 0)
+++ trunk/platforms/unix/plugins/ScratchPlugin/unixScratchOps.c	2012-07-30 22:05:14 UTC (rev 2573)
@@ -0,0 +1,98 @@
+/* unixScratchOps.c -- Scratch operations for unix based OSes.
+ *
+ * 
+ *   Copyright (C) 2011 Massachusetts Institute of Technology
+ *   All rights reserved.
+ *   
+ *   Permission is hereby granted, free of charge, to any person obtaining a
+ *   copy of this software and associated documentation files (the "Software"),
+ *   to deal in the Software without restriction, including without limitation
+ *   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ *   and/or sell copies of the Software, and to permit persons to whom the
+ *   Software is furnished to do so, subject to the following conditions:
+ * 
+ *   The above copyright notice and this permission notice shall be included in
+ *   all copies or substantial portions of the Software.
+ * 
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ *   DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "ScratchPlugin.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+void OpenURL(char *url) {
+	// Open a browser on the given URL.
+#ifdef I_REALLY_DONT_CARE_HOW_UNSAFE_THIS_IS
+	char cmd[1000] = "xdg-open ";
+ 	strcat( cmd, url); 
+ 	system(cmd);
+#else
+	// Implement a secure way here.
+	// IMHO it would be best to call a script that the user or
+	// package maintainer can customize. But in any case,
+	// DO NOT call system() with an unchecked URL. --bf
+#endif
+}
+
+void SetScratchWindowTitle(char *title) {
+	// Set the text in the window title bar. Not yet implemented.
+}
+
+void GetFolderPathForID(int folderID, char *path, int maxPath) {
+  // Get the full path for a special folder:
+	//  1 - user's home folder
+	//  2 - user's desktop folder
+	//  3 - user's document folder
+	//  4 - user's photos or pictures folder (does Linux have a convention for this?)
+	//  5 - user's music folder (does Linux have a convention for this?)
+	// path is filled in with a zero-terminated string of max length maxPath
+
+	char *s = NULL;
+
+	path[0] = 0;  // a zero-length path indicates failure
+	
+	// get the user's HOME directory
+	s = getenv("HOME");
+	if ((s == NULL) || (strlen(s) == 0)) return;
+
+	strncat(path, s, maxPath); // home folder
+
+	if (folderID == 1) return;
+	if (folderID == 2) strncat(path, "/Desktop", maxPath);
+	if (folderID == 4) strncat(path, "/Pictures", maxPath);
+	if (folderID == 5) strncat(path, "/Music", maxPath);
+	
+	if (folderID == 3) {
+		s = getenv("SUGAR_ACTIVITY_ROOT");
+		if (s != NULL) {
+			// On XO, return the writeable activity "data" directory
+			strncat(path, s, maxPath);
+			strncat(path, "/data", maxPath);
+		} else  {
+			strncat(path, "/Documents", maxPath);
+		}
+	}
+}
+
+int WinShortToLongPath(char *shortPath, char* longPath, int maxPath) {
+	return -1; // fail on non-Windows platforms
+}
+
+int IsFileOrFolderHidden(char *fullPath) {
+	// Always return false on Linux
+	return 0;
+}
+
+void SetUnicodePasteBuffer(short int *utf16, int count) {
+	// Store the given Unicode UTF16 string in the paste buffer.
+	// No longer needed; use clipboard methods in UnicodePlugin.
+}


Property changes on: trunk/platforms/unix/plugins/ScratchPlugin/unixScratchOps.c
___________________________________________________________________
Added: svn:executable
   + *

Added: trunk/platforms/unix/plugins/ScratchPlugin/unixSeriaPort2Ops.c
===================================================================
--- trunk/platforms/unix/plugins/ScratchPlugin/unixSeriaPort2Ops.c	                        (rev 0)
+++ trunk/platforms/unix/plugins/ScratchPlugin/unixSeriaPort2Ops.c	2012-07-30 22:05:14 UTC (rev 2573)
@@ -0,0 +1,356 @@
+/* unixSerialPort2Ops.c -- Scratch operations for unix based OSes. Support
+ * for SerialPort2 primitives under Unix, including OSX and Linux.
+ *
+ * 
+ *   Copyright (C) 2011 Massachusetts Institute of Technology
+ *   All rights reserved.
+ *   
+ *   Permission is hereby granted, free of charge, to any person obtaining a
+ *   copy of this software and associated documentation files (the "Software"),
+ *   to deal in the Software without restriction, including without limitation
+ *   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ *   and/or sell copies of the Software, and to permit persons to whom the
+ *   Software is furnished to do so, subject to the following conditions:
+ * 
+ *   The above copyright notice and this permission notice shall be included in
+ *   all copies or substantial portions of the Software.
+ * 
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ *   DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "ScratchPlugin.h"
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <unistd.h>
+
+// support for systems with a single hardware flow control bit
+// on such systems setting hardware handshaking for input sets it for output as well
+#ifndef CRTS_IFLOW
+# define CRTS_IFLOW CRTSCTS
+#endif
+#ifndef CCTS_OFLOW
+# define CCTS_OFLOW CRTSCTS
+#endif
+
+
+// globals
+#define PORT_COUNT 32
+static int gFileDescr[PORT_COUNT] = {			// file descriptors for open serial ports
+	-1, -1, -1, -1, -1, -1, -1, -1,				// the portNum kept by Squeak is an index
+	-1, -1, -1, -1, -1, -1, -1, -1,				// into this array. -1 marks unused entries.
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1};
+static struct termios gOrigTermios[PORT_COUNT]; // original termios settings for open ports
+
+#define PRIM_FAILED -1
+
+// helper function declarations
+int FileDescrForEntry(int portNum);
+int OpenPortNamed(const char *bsdPath, int baudRate, int entryIndex);
+int isPrefix(char *prefix, char *s);
+int isSerialPortDev(char *s);
+
+int SerialPortCount(void) {
+	DIR						*dirPtr;
+	struct dirent	*entryPtr;
+	int						cnt = 0;
+
+	if ((dirPtr = opendir("/dev")) == NULL) return 0;
+
+	while ((entryPtr = readdir(dirPtr)) != NULL) {
+		if (isSerialPortDev(entryPtr->d_name)) cnt++;
+	}
+
+	closedir(dirPtr);
+	return cnt;
+}
+
+// Find the name of the given port number. Fill in bsdPath if successful.
+// Otherwise, make bsdPath be the empty string.
+void SerialPortName(int portIndex, char *bsdPath, int maxPathSize) {
+	DIR						*dirPtr;
+	struct dirent	*entryPtr;
+	int						cnt = 0;
+
+	*bsdPath = '\0';	// result is the empty string if port not found
+
+	if (portIndex < 1) return;
+	if ((dirPtr = opendir("/dev")) == NULL) return;
+
+	while ((entryPtr = readdir(dirPtr)) != NULL) {
+		if (isSerialPortDev(entryPtr->d_name)) cnt++;
+		if (cnt == portIndex) {
+			strncat(bsdPath, "/dev/", maxPathSize);
+			strncat(bsdPath, entryPtr->d_name, maxPathSize);
+			closedir(dirPtr);
+			return;
+		}
+	}
+
+	closedir(dirPtr);
+}
+
+int SerialPortOpenPortNamed(char *portName, int baudRate) {
+	int entryIndex;
+
+	// scan for first free entry
+	for (entryIndex = 0; entryIndex < PORT_COUNT; entryIndex++) {
+		if (gFileDescr[entryIndex] == -1) break;
+	}
+	if (entryIndex >= PORT_COUNT) return PRIM_FAILED; // no free entry
+
+	if (!OpenPortNamed(portName, baudRate, entryIndex)) return PRIM_FAILED;
+	return entryIndex;
+}
+
+void SerialPortClose(int portNum) {
+	int fDescr;
+
+	if ((fDescr = FileDescrForEntry(portNum)) < 0) return; // already closed
+
+	// restore the serial port settings to their original state
+	tcsetattr(fDescr, TCSANOW, &gOrigTermios[portNum]);
+	close(fDescr);
+	gFileDescr[portNum] = -1;
+}
+
+int SerialPortIsOpen(int portNum) {
+	return FileDescrForEntry(portNum) != -1;
+}
+
+int SerialPortRead(int portNum, char *bufPtr, int bufSize) {
+	int fDescr, count = 0;
+
+	if ((fDescr = FileDescrForEntry(portNum)) < 0) return 0;
+
+	count = read(fDescr, bufPtr, bufSize);
+	if (count < 0) return 0; // read error
+	return count;
+}
+
+int SerialPortWrite(int portNum, char *bufPtr, int bufSize) {
+	int fDescr, count = 0;
+
+	if ((fDescr = FileDescrForEntry(portNum)) < 0) return 0;
+
+	count = write(fDescr, bufPtr, bufSize);
+	if (count < 0) return 0; // write error
+	return count;
+}
+
+// Port options for SetOption/GetOption:
+//	1. baud rate
+//	2. data bits
+//	3. stop bits
+//	4. parity type
+//	5. input flow control type
+//	6. output flow control type
+//	20-25: handshake line bits (DTR, RTS, CTS, DSR, CD, RD)
+
+int SerialPortSetOption(int portNum, int optionNum, int newValue) {
+	int fDescr, handshake;
+	struct termios options;
+
+	if ((fDescr = FileDescrForEntry(portNum)) < 0) return PRIM_FAILED;
+	if (tcgetattr(fDescr, &options) == -1) return PRIM_FAILED;
+
+	switch (optionNum) {
+	case 1: // baud rate
+		if (cfsetspeed(&options, newValue) == -1) return PRIM_FAILED;
+		break;
+	case 2: // # of data bits
+		switch(newValue) {
+		case 5:
+			options.c_cflag = (options.c_cflag & ~CSIZE) | CS5;
+			break;
+		case 6:
+			options.c_cflag = (options.c_cflag & ~CSIZE) | CS6;
+			break;
+		case 7:
+			options.c_cflag = (options.c_cflag & ~CSIZE) | CS7;
+			break;
+		case 8:
+			options.c_cflag = (options.c_cflag & ~CSIZE) | CS8;
+			break;
+		}
+		break;
+	case 3: // 1 or 2 stop bits
+		if (newValue > 1) options.c_cflag |= CSTOPB;		// two stop bits
+		else options.c_cflag &= ~CSTOPB;					// one stop bit
+		break;
+	case 4: // parity
+		options.c_cflag &= ~(PARENB | PARODD);						// no parity
+		if (newValue == 1) options.c_cflag |= (PARENB | PARODD);	// odd parity
+		if (newValue == 2) options.c_cflag |= PARENB;				// even parity
+		break;
+	case 5: // input flow control
+		options.c_iflag &= ~IXOFF;							// disable xoff input flow control
+		options.c_cflag &= ~CRTS_IFLOW;						// disable RTS (hardware) input flow control
+		if (newValue == 1) options.c_iflag |= IXOFF;		// enable xoff input flow control
+		if (newValue == 2) {
+			options.c_cflag |= CRTS_IFLOW;					// enable RTS (hardware) input flow control
+			if (CRTS_IFLOW == CCTS_OFLOW) {					// on systems with a single hardware flow control bit: 
+				options.c_iflag &= ~(IXON | IXOFF);			//   disable xon/xoff flow control
+			}
+		}
+		break;
+	case 6: // output flow control
+		options.c_iflag &= ~IXON;							// disable xon output flow control
+		options.c_cflag &= ~CCTS_OFLOW;						// disable CTS (hardware) output flow control
+		if (newValue == 1) options.c_iflag |= IXON;			// enable xon output flow control
+		if (newValue == 2) {
+			options.c_cflag |= CCTS_OFLOW;					// enable CTS (hardware) output flow control
+			if (CRTS_IFLOW == CCTS_OFLOW) {					// on systems with a single hardware flow control bit: 
+				options.c_iflag &= ~(IXON | IXOFF);			//   disable xon/xoff flow control
+			}
+		}
+		break;
+
+	case 20: // set DTR line state
+		if (ioctl(fDescr, TIOCMGET, &handshake) == -1) return PRIM_FAILED;
+		handshake = newValue ? (handshake | TIOCM_DTR) : (handshake & ~TIOCM_DTR);
+		if (ioctl(fDescr, TIOCMSET, &handshake) == -1) return PRIM_FAILED;
+		break;
+	case 21: // set RTS line state
+		if (ioctl(fDescr, TIOCMGET, &handshake) == -1) return PRIM_FAILED;
+		handshake = newValue ? (handshake | TIOCM_RTS) : (handshake & ~TIOCM_RTS);
+		if (ioctl(fDescr, TIOCMSET, &handshake) == -1) return PRIM_FAILED;
+		break;
+	}
+	if (tcsetattr(fDescr, TCSANOW, &options) == -1) return PRIM_FAILED;
+	return 0;
+}
+
+int SerialPortGetOption(int portNum, int optionNum) {
+	int fDescr, handshake = -1;
+	struct termios options;
+
+	if ((fDescr = FileDescrForEntry(portNum)) < 0) return PRIM_FAILED;
+	if (tcgetattr(fDescr, &options) == -1) return PRIM_FAILED;
+	if (ioctl(fDescr, TIOCMGET, &handshake) == -1) return PRIM_FAILED;
+
+	switch (optionNum) {
+	case 1: return (int) cfgetispeed(&options);
+	case 2:
+		if ((options.c_cflag & CSIZE) == CS5) return 5;
+		if ((options.c_cflag & CSIZE) == CS6) return 6;
+		if ((options.c_cflag & CSIZE) == CS7) return 7;
+		if ((options.c_cflag & CSIZE) == CS8) return 8;
+		return PRIM_FAILED;
+	case 3: return (options.c_cflag & CSTOPB) ? 2 : 1;
+	case 4:
+		if (!(options.c_cflag & PARENB)) return 0;
+		return (options.c_cflag & PARODD) ? 1 : 2;
+	case 5:
+		if (options.c_iflag & IXOFF) return 1;
+		if (options.c_cflag & CRTS_IFLOW) return 2;
+		return 0;
+	case 6:
+		if (options.c_iflag & IXON) return 1;
+		if (options.c_cflag & CCTS_OFLOW) return 2;
+		return 0;
+
+	case 20: return (handshake & TIOCM_DTR) > 0;
+	case 21: return (handshake & TIOCM_RTS) > 0;
+	case 22: return (handshake & TIOCM_CTS) > 0;
+	case 23: return (handshake & TIOCM_DSR) > 0;
+	case 24: return (handshake & TIOCM_CD) > 0;
+	case 25: return (handshake & TIOCM_RI) > 0;
+	}
+	return PRIM_FAILED;
+}
+
+// ***** helper functions *****
+
+// Return the file descriptor for the given entry or -1 if either the
+// given port number (index) is out of range or the port is not open.
+int FileDescrForEntry(int portNum) {
+	if ((portNum < 0) || (portNum >= PORT_COUNT)) return PRIM_FAILED;
+	return gFileDescr[portNum];
+}
+
+// Given the path to a serial device, open the device and configure it for
+// using given entryIndex. Answer 1 if the operation succeeds, 0 if it fails.
+int OpenPortNamed(const char *bsdPath, int baudRate, int entryIndex) {
+	int fDescr = -1;
+	struct termios options;
+
+	// open the serial port read/write with no controlling terminal; don't block
+	fDescr = open(bsdPath, O_RDWR | O_NOCTTY | O_NONBLOCK);
+	if (fDescr == -1) {
+		printf("Error opening serial port %s - %s(%d).\n", bsdPath, strerror(errno), errno);
+		goto error;
+	}
+
+	// request exclusive access to the port
+	if (ioctl(fDescr, TIOCEXCL) == -1) {
+		printf("Error setting TIOCEXCL on %s - %s(%d).\n", bsdPath, strerror(errno), errno);
+		goto error;
+	}
+
+	// save port settings so we can restore them later
+	if (tcgetattr(fDescr, &gOrigTermios[entryIndex]) == -1) {
+		printf("Error getting attributes %s - %s(%d).\n", bsdPath, strerror(errno), errno);
+		goto error;
+	}
+
+	// port settings are made by modifying a copy of the termios struct
+	// and then calling tcsetattr() to make those changes take effect.
+	options = gOrigTermios[entryIndex];
+
+	// set the baud rate
+	if (cfsetspeed(&options, baudRate) == -1) {
+		printf("Error setting speed %d %s - %s(%d).\n", baudRate, bsdPath, strerror(errno), errno);
+		goto error;
+	}
+
+	// set raw input (non-canonical) mode, with writes not blocking.
+	cfmakeraw(&options);
+	options.c_cc[VMIN] = 0;
+	options.c_cc[VTIME] = 0;
+
+	// install the new port settings
+	if (tcsetattr(fDescr, TCSANOW, &options) == -1) {
+		printf("Error setting attributes %s - %s(%d).\n", bsdPath, strerror(errno), errno);
+		goto error;
+	}
+	gFileDescr[entryIndex] = fDescr;
+	return 1; // success!
+
+error:
+	if (fDescr != -1) close(fDescr);
+	return 0;
+}
+
+int isSerialPortDev(char *s) {
+	return isPrefix("ttyusb", s);
+}
+
+int isPrefix(char *prefix, char *s) {
+	int prefixC, c;
+	while (1) {
+		prefixC = *prefix++;
+		c = *s++;
+		if (prefixC == 0) return 1; // match!
+		if (c == 0) return 0; // s is shorter than prefix
+		if (c != prefixC) {
+			if (('a' <= c) && (c <= 'z')) c -= 32;
+			if (('a' <= prefixC) && (prefixC <= 'z')) prefixC -= 32;
+			if (c != prefixC) return 0; // non-match
+		}
+	}
+}


Property changes on: trunk/platforms/unix/plugins/ScratchPlugin/unixSeriaPort2Ops.c
___________________________________________________________________
Added: svn:executable
   + *

Added: trunk/platforms/unix/plugins/UnicodePlugin/README.UnicodePlugin
===================================================================
--- trunk/platforms/unix/plugins/UnicodePlugin/README.UnicodePlugin	                        (rev 0)
+++ trunk/platforms/unix/plugins/UnicodePlugin/README.UnicodePlugin	2012-07-30 22:05:14 UTC (rev 2573)
@@ -0,0 +1 @@
+In order to build the Unicode plugin on Linux, you'll need a collection of Pango, Cairo, and glib header and library files. These can often be found in the GTK+ development package in the package repository for your version of Linux.


Property changes on: trunk/platforms/unix/plugins/UnicodePlugin/README.UnicodePlugin
___________________________________________________________________
Added: svn:executable
   + *

Added: trunk/platforms/unix/plugins/UnicodePlugin/UnicodeOps-linux.c
===================================================================
--- trunk/platforms/unix/plugins/UnicodePlugin/UnicodeOps-linux.c	                        (rev 0)
+++ trunk/platforms/unix/plugins/UnicodePlugin/UnicodeOps-linux.c	2012-07-30 22:05:14 UTC (rev 2573)
@@ -0,0 +1,280 @@
+/* UnicodeOps-linux.c
+ *
+ * 
+ *   Copyright (C) 2011 Massachusetts Institute of Technology
+ *   All rights reserved.
+ *   
+ *   Permission is hereby granted, free of charge, to any person obtaining a
+ *   copy of this software and associated documentation files (the "Software"),
+ *   to deal in the Software without restriction, including without limitation
+ *   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ *   and/or sell copies of the Software, and to permit persons to whom the
+ *   Software is furnished to do so, subject to the following conditions:
+ * 
+ *   The above copyright notice and this permission notice shall be included in
+ *   all copies or substantial portions of the Software.
+ * 
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ *   DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+
+#include <pango/pangocairo.h>
+#include <glib/gprintf.h>
+#include <string.h>
+
+/* entry points */
+
+int unicodeClipboardGet(unsigned short *utf16, int utf16Length);
+void unicodeClipboardPut(unsigned short *utf16, int utf16Length);
+int unicodeClipboardSize(void);
+void unicodeDrawString(char *utf8, int utf8Length, int *wPtr, int *hPtr, unsigned int *bitmapPtr);
+int unicodeGetFontList(char *str, int strLength);
+int unicodeGetXRanges(char *utf8, int utf8Length, int *resultPtr, int resultLength);
+void unicodeMeasureString(char *utf8, int utf8Length, int *wPtr, int *hPtr);
+void unicodeSetColors(int fgRed, int fgGreen, int fgBlue, int bgRed, int bgGreen, int bgBlue, int mapBGToTransparent);
+void unicodeSetFont(char *fontName, int fontSize, int boldFlag, int italicFlag, int antiAliasFlag);
+
+/* globals */
+
+PangoLayout *cachedLayout = NULL;  // used for measuring
+PangoFontDescription *fontDescr = NULL;
+cairo_font_options_t* fontOptions = NULL;
+
+int	g_bgRed = 255, g_bgGreen = 255, g_bgBlue = 255;
+int	g_fgRed = 0,   g_fgGreen = 0,   g_fgBlue = 0;
+int	g_bgRGB = 0; // Squeak format
+int	g_bgTransparent = 0;
+
+/* helper procedures */
+
+void computeLayout(PangoLayout *layout, char *utf8, int utf8Length, int *wPtr, int *hPtr, int *xOffsetPtr, int *yOffsetPtr, int *layoutDetailsPtr) {
+	PangoRectangle inkRect, logicalRect;
+	int left, top, right, bottom, baseline;
+	PangoLayoutIter *iter;
+
+	if (fontDescr == NULL) unicodeSetFont("Verdana", 18, 0, 0, 1);
+	pango_cairo_context_set_font_options(pango_layout_get_context(layout), fontOptions);
+	pango_layout_set_font_description(layout, fontDescr);
+	pango_layout_set_text(layout, utf8, utf8Length);
+	pango_layout_get_pixel_extents(layout, &inkRect, &logicalRect);
+
+	left = (inkRect.x < logicalRect.x) ? inkRect.x : logicalRect.x;
+	top = (inkRect.y < logicalRect.y) ? inkRect.y : logicalRect.y;
+	right = inkRect.x + inkRect.width;
+	if ((logicalRect.x + logicalRect.width) > right) right = logicalRect.x + logicalRect.width;
+	bottom = inkRect.y + inkRect.height;
+	if ((logicalRect.y + logicalRect.height) > bottom) bottom = logicalRect.y + logicalRect.height;
+
+	iter = pango_layout_get_iter(layout);
+	baseline = PANGO_PIXELS(pango_layout_iter_get_baseline(iter));
+	pango_layout_iter_free(iter);
+
+	if (left < 0) {
+		inkRect.x = inkRect.x - left;
+		logicalRect.x = logicalRect.x - left;
+	}
+	if (top < 0) {
+		inkRect.y = inkRect.y - top;
+		logicalRect.y = logicalRect.y - top;
+		baseline = baseline - top;
+	}
+
+	if (layoutDetailsPtr != NULL) {
+		layoutDetailsPtr[0] = inkRect.x;
+		layoutDetailsPtr[1] = inkRect.y;
+		layoutDetailsPtr[2] = inkRect.width;
+		layoutDetailsPtr[3] = inkRect.height;
+		
+		layoutDetailsPtr[4] = logicalRect.x;
+		layoutDetailsPtr[5] = logicalRect.y;
+		layoutDetailsPtr[6] = logicalRect.width;
+		layoutDetailsPtr[7] = logicalRect.height;
+
+		layoutDetailsPtr[8] = baseline;
+	}
+
+	*wPtr =  right - left;
+	*hPtr = bottom - top;
+	*xOffsetPtr = left < 0 ? -left : 0;
+	*yOffsetPtr =  top < 0 ? -top  : 0;
+}
+
+int unicodeLength(char *utf8, int utf8Length) {
+	int count, i, ch;
+
+	count = i = 0;
+	while (i < utf8Length) {
+		count++;
+		ch = utf8[i];
+		if ((ch & 0xE0) == 0xC0) i += 2;
+		else if ((ch & 0xF0) == 0xE0) i += 3;
+		else if ((ch & 0xF8) == 0xF0) i += 4;
+		else i += 1;
+	}
+	return count;
+}
+
+/* entry points */
+
+// Clipboard operations are not yet implemented
+int unicodeClipboardGet(unsigned short *utf16, int utf16Length) { return 0; }
+void unicodeClipboardPut(unsigned short *utf16, int utf16Length) { }
+int unicodeClipboardSize(void) { return 0; }
+
+int unicodeGetFontList(char *str, int strLength) {
+	PangoFontMap *fontMap;
+	PangoFontFamily **fontFomilies;
+	int count, i;
+
+	str[0] = '\0';
+
+	if (cachedLayout == NULL) {
+		cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_A8, 1, 1);
+		cairo_t *cr = cairo_create(surface);
+		cachedLayout = pango_cairo_create_layout(cr);
+	}
+
+	fontMap = pango_context_get_font_map(pango_layout_get_context(cachedLayout));
+	pango_font_map_list_families(fontMap, &fontFomilies, &count);
+
+	for (i = 0; i < count; i++) {
+		strncat(str, pango_font_family_get_name(fontFomilies[i]), strLength);
+		strncat(str, "\n", strLength);
+	}
+	g_free(fontFomilies);
+	return strlen(str);
+}
+
+void unicodeDrawString(char *utf8, int utf8Length, int *wPtr, int *hPtr, unsigned int *bitmapPtr) {
+	int w = *wPtr;
+	int h = *hPtr;
+	int pixelCount = w * h;
+	int offsetX, offsetY;
+	unsigned int *pixelPtr, *lastPtr;
+
+	cairo_surface_t *surface = cairo_image_surface_create_for_data((unsigned char *) bitmapPtr, CAIRO_FORMAT_RGB24, w, h, (4 * w));
+	cairo_t *cr = cairo_create(surface);
+	PangoLayout *layout = pango_cairo_create_layout(cr);
+
+	computeLayout(layout, utf8, utf8Length, wPtr, hPtr, &offsetX, &offsetY, NULL);
+
+	// fill with background color if not transparent
+	if (g_bgRGB != 0) {
+		cairo_set_source_rgb(cr, g_bgRed / 255.0, g_bgGreen / 255.0, g_bgBlue / 255.0);
+		cairo_paint(cr);
+	}
+
+	cairo_translate(cr, offsetX, offsetY);
+	cairo_set_source_rgb(cr, g_fgRed / 255.0, g_fgGreen / 255.0, g_fgBlue / 255.0);
+	pango_cairo_show_layout(cr, layout);
+
+	// map bg color pixels to transparent if so desired
+	if (g_bgTransparent) {
+		pixelPtr = bitmapPtr;
+		lastPtr = pixelPtr + pixelCount;
+		while (pixelPtr < lastPtr) {
+			if (*pixelPtr == g_bgRGB) *pixelPtr = 0;
+			pixelPtr++;
+		}
+	}
+
+	g_object_unref(layout);
+	cairo_destroy(cr);
+	cairo_surface_destroy(surface);
+}
+
+int unicodeGetXRanges(char *utf8, int utf8Length, int *resultPtr, int resultLength) {
+	int w, h, offsetX, offsetY;
+	int count, ch, i, j;
+	PangoRectangle rect;
+
+	count = unicodeLength(utf8, utf8Length);
+	if (resultLength < (2 * count)) return -1;
+
+	if (cachedLayout == NULL) {
+		cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_A8, 1, 1);
+		cairo_t *cr = cairo_create(surface);
+		cachedLayout = pango_cairo_create_layout(cr);
+	}
+
+	computeLayout(cachedLayout, utf8, utf8Length, &w, &h, &offsetX, &offsetY, NULL);
+
+	i = j = 0;
+	while ((i < utf8Length) && (j < (resultLength - 1))) {
+		pango_layout_index_to_pos(cachedLayout, i, &rect);
+		ch = utf8[i];
+		if ((ch & 0xE0) == 0xC0) i += 2;
+		else if ((ch & 0xF0) == 0xE0) i += 3;
+		else if ((ch & 0xF8) == 0xF0) i += 4;
+		else i += 1;
+		resultPtr[j] = PANGO_PIXELS(rect.x);
+		resultPtr[j + 1] = PANGO_PIXELS(rect.x + rect.width);
+		j += 2;
+	}
+
+	return count;
+}
+
+void unicodeMeasureString(char *utf8, int utf8Length, int *wPtr, int *hPtr) {
+	int offsetX, offsetY;
+
+	if (cachedLayout == NULL) {
+		cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_A8, 1, 1);
+		cairo_t *cr = cairo_create(surface);
+		cachedLayout = pango_cairo_create_layout(cr);
+	}
+
+	computeLayout(cachedLayout, utf8, utf8Length, wPtr, hPtr, &offsetX, &offsetY, NULL);
+}
+
+void unicodeSetColors(int fgRed, int fgGreen, int fgBlue, int bgRed, int bgGreen, int bgBlue, int mapBGToTransparent) {
+	g_fgRed   = fgRed & 255;
+	g_fgGreen = fgGreen & 255;
+	g_fgBlue  = fgBlue & 255;
+	g_bgRed   = bgRed & 255;
+	g_bgGreen = bgGreen & 255;
+	g_bgBlue  = bgBlue & 255;
+	g_bgRGB = (g_bgRed << 16) | (g_bgGreen << 8) | g_bgBlue;  // Squeak pixel format
+	g_bgTransparent = mapBGToTransparent;
+}
+
+void unicodeSetFont(char *fontName, int fontSize, int boldFlag, int italicFlag, int antiAliasFlag) {
+	char description[200];
+	g_sprintf(description, "%s, %s %s %dpx",
+		fontName,
+		(boldFlag ? "bold" : ""),
+		(italicFlag ? "italic" : ""),
+		fontSize);
+
+	if (fontDescr != NULL) pango_font_description_free(fontDescr);
+	fontDescr = pango_font_description_from_string(description);
+
+	if (fontOptions == NULL) {
+		fontOptions = cairo_font_options_create();
+		// Note: On Mac OS, the default hint style and metrics looked the best. Also, using
+		// the default allows the user to control the look via the OS settings.
+		/*
+		styles:
+			CAIRO_HINT_STYLE_DEFAULT		Use the default hint style for for font backend and target device
+			CAIRO_HINT_STYLE_NONE			Do not hint outlines
+			CAIRO_HINT_STYLE_SLIGHT			Hint outlines slightly to improve contrast while retaining good fidelity to the original shapes.
+			CAIRO_HINT_STYLE_MEDIUM			Hint outlines with medium strength giving a compromise between fidelity to the original shapes and contrast
+			CAIRO_HINT_STYLE_FULL			Hint outlines to maximize contrast
+		metrics:
+			CAIRO_HINT_METRICS_DEFAULT	Hint metrics in the default manner for the font backend and target device
+			CAIRO_HINT_METRICS_OFF			Do not hint font metrics
+			CAIRO_HINT_METRICS_ON			Hint font metrics
+		*/
+		cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_DEFAULT);
+		cairo_font_options_set_hint_metrics(fontOptions, CAIRO_HINT_METRICS_DEFAULT);
+	}
+
+	cairo_font_options_set_antialias(fontOptions, antiAliasFlag ? CAIRO_ANTIALIAS_GRAY : CAIRO_ANTIALIAS_NONE);
+}


Property changes on: trunk/platforms/unix/plugins/UnicodePlugin/UnicodeOps-linux.c
___________________________________________________________________
Added: svn:executable
   + *

Added: trunk/platforms/unix/plugins/UnicodePlugin/config.cmake
===================================================================
--- trunk/platforms/unix/plugins/UnicodePlugin/config.cmake	                        (rev 0)
+++ trunk/platforms/unix/plugins/UnicodePlugin/config.cmake	2012-07-30 22:05:14 UTC (rev 2573)
@@ -0,0 +1,3 @@
+PLUGIN_REQUIRE_PACKAGE (PANGOCAIRO pangocairo)
+PLUGIN_REQUIRE_PACKAGE (GLIB glib-2.0)
+

Added: trunk/platforms/unix/plugins/WeDoPlugin/WeDoLinux.c
===================================================================
--- trunk/platforms/unix/plugins/WeDoPlugin/WeDoLinux.c	                        (rev 0)
+++ trunk/platforms/unix/plugins/WeDoPlugin/WeDoLinux.c	2012-07-30 22:05:14 UTC (rev 2573)
@@ -0,0 +1,220 @@
+/* WeDoLinux.c -- Linux plugin for Lego WeDo
+ *
+ * Author: Derek O'Connell <doc at doconnel.f9.co.uk>
+ * 
+ *   Copyright (C) 2010 by MIT
+ *   All rights reserved.
+ *   
+ *   This file is part of Unix Squeak.
+ * 
+ *   Permission is hereby granted, free of charge, to any person obtaining a
+ *   copy of this software and associated documentation files (the "Software"),
+ *   to deal in the Software without restriction, including without limitation
+ *   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ *   and/or sell copies of the Software, and to permit persons to whom the
+ *   Software is furnished to do so, subject to the following conditions:
+ * 
+ *   The above copyright notice and this permission notice shall be included in
+ *   all copies or substantial portions of the Software.
+ * 
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ *   DEALINGS IN THE SOFTWARE.
+ *
+ * Last edited: 2010-06-20 16:23:00 by Derek O'Connell
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <linux/hiddev.h>
+
+
+#define true 1
+#define false 0
+
+#define NTEMPLATES  2
+#define MAXSTRLEN  64
+
+static char hiddevFileTemplates[NTEMPLATES][MAXSTRLEN] = {
+	"/dev/usb/hiddev0",
+	"/dev/hiddev0"
+};
+
+static char hiddevFileName[MAXSTRLEN];
+
+static int fdWeDo = 0;
+
+
+/* ================================================= */
+/* ============== FUNCTION PROTOTYPES ============== */
+/* ================================================= */
+
+
+/* LIBRARY CONSTRUCTOR/DESCTRUCTOR */
+void __attribute__ ((constructor)) libConWeDo(void);
+void __attribute__ ((destructor)) libDesWeDo(void);
+
+/* SQUEAK INTERFACE */
+int WeDoOpenPort(void);
+int WeDoClosePort(void);
+int WeDoRead(char *bufPtr, int bufSize);
+int WeDoWrite(char *bufPtr, int bufSize);
+
+
+/* ================================================= */
+/* ========== LIB CONSTRUCTOR/DESTRUCTOR =========== */
+/* ================================================= */
+
+
+void __attribute__ ((constructor)) 
+libConWeDo(void) {
+	/* NOTHING TO DO (YET) */
+}
+
+
+void __attribute__ ((destructor)) 
+libDesWeDo(void) {
+	WeDoClosePort();
+}
+
+
+/* ================================================= */
+/* =================== UTILITY ===================== */
+/* ================================================= */
+
+
+void 
+delay(int mS) {
+	int microsecs;
+	struct timeval tv;
+
+	microsecs=mS * 1000;
+	tv.tv_sec  = microsecs/1000000;
+	tv.tv_usec = microsecs%1000000;
+
+	select(0, NULL, NULL, NULL, &tv);
+}
+
+
+/* ================================================= */
+/* ================== WEDO UTILS =================== */
+/* ================================================= */
+
+
+int
+scanForWeDo(char *fileTemplate) { /* eg, "/dev/usb/hiddev0" */
+	int f, i;
+	struct hiddev_devinfo dinfo;
+	
+	f = 0;
+	for (i=0; i<10; i++) {
+		strcpy(hiddevFileName, fileTemplate); 
+		hiddevFileName[strlen(hiddevFileName)-1] = '0' + i;
+		if (-1 != (f = open(hiddevFileName, O_RDWR)))
+			if (-1 != ioctl(f, HIDIOCGDEVINFO, &dinfo))
+				if ((dinfo.vendor == 0x0694) & (dinfo.product == 0x0003))
+					return f;
+	}
+	return 0;
+}
+
+
+int
+isWeDoAvailable() {
+	struct stat st;
+
+	if (!fdWeDo) return false;
+
+	/* Required, catches device being unplugged... */
+	if (-1 == stat(hiddevFileName, &st)) {
+		WeDoClosePort();
+		return false;
+	}
+	
+	return true;
+}
+
+
+/* ================================================= */
+/* ================= SCRATCH I/F =================== */
+/* ================================================= */
+
+
+int 
+WeDoOpenPort(void) {
+	int i;
+
+	if (fdWeDo) return true;
+
+	fdWeDo = 0;
+	for (i=0; i<NTEMPLATES; i++)
+		if (fdWeDo = scanForWeDo(hiddevFileTemplates[i]))
+			break;
+	
+	if (!fdWeDo) return false;
+		
+	delay(100);
+	return true;
+}
+
+
+int 
+WeDoClosePort(void) {
+	if (!fdWeDo) return true;
+	close(fdWeDo);
+	fdWeDo = 0;
+	return true;
+}
+
+
+int 
+WeDoRead(char *bufPtr, int bufSize) {
+	int i;
+	struct hiddev_usage_ref uref;
+
+	if (!isWeDoAvailable()) return 8;
+	
+	for (i = 0; i < 8; i++)	{
+		uref.report_type = HID_REPORT_TYPE_INPUT;
+		uref.report_id = HID_REPORT_ID_FIRST;
+		uref.field_index = 0;
+		uref.usage_index = i;
+		uref.value = 0;
+		if (isWeDoAvailable())
+			if (ioctl(fdWeDo, HIDIOCGUCODE, &uref) < 0) continue;
+		if (isWeDoAvailable())
+			if (ioctl(fdWeDo, HIDIOCGUSAGE, &uref) < 0) continue;
+		*(bufPtr + i) = uref.value;
+	}
+	return 8;
+}
+
+
+int 
+WeDoWrite(char *bufPtr, int bufSize) {
+	int i;
+
+	if (!isWeDoAvailable()) return 8;
+	
+	for (i = 0; i < 8; i++)
+		if (isWeDoAvailable())
+			ioctl(fdWeDo, HIDIOCSUSAGE, (int []){HID_REPORT_TYPE_OUTPUT, 0, 0, i, 0, *(bufPtr + i)});
+	if (isWeDoAvailable())
+		ioctl(fdWeDo, HIDIOCSREPORT,(int []){HID_REPORT_TYPE_OUTPUT, 0, 1});
+	if (isWeDoAvailable())
+		ioctl(fdWeDo, HIDIOCSREPORT,(int []){HID_REPORT_TYPE_OUTPUT, 0, 1});
+
+	return 8;
+}
+

Added: trunk/platforms/unix/plugins/WeDoPlugin/config.cmake
===================================================================
--- trunk/platforms/unix/plugins/WeDoPlugin/config.cmake	                        (rev 0)
+++ trunk/platforms/unix/plugins/WeDoPlugin/config.cmake	2012-07-30 22:05:14 UTC (rev 2573)
@@ -0,0 +1,3 @@
+PLUGIN_REQUIRE_INCLUDE(HIDDEV linux/hiddev.h /usr/include)
+
+



More information about the Vm-dev mailing list