[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