--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tools/py2sis/ensymble/rscfile.py Tue Feb 16 10:07:05 2010 +0530
@@ -0,0 +1,202 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+##############################################################################
+# rscfile.py - Symbian OS compiled resource file (RSC) utilities
+# Copyright 2006, 2007 Jussi Ylänen
+#
+# This file is part of Ensymble developer utilities for Symbian OS(TM).
+#
+# Ensymble is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Ensymble is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ensymble; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+##############################################################################
+
+import struct
+
+import symbianutil
+
+
+##############################################################################
+# Module-level functions which are normally only used by this module
+##############################################################################
+
+def makeuidfromoffset(offset):
+ '''Convert a Symbian OS resource file offset to a UID.
+
+ ---- From rcomp v7.01 source ----
+ space: 0, A: 1, B: 2, ..., Z: 26
+
+ ABCD corresponds to the number 4321 which becomes
+ ((4*27 + 3) * 27 + 2) * 27 + 1.
+ ---- ----
+
+ The description above contains an error. The actual situation
+ is reversed: ABCD corresponds to the number 1234 which results in
+ ((1*27 + 2) * 27 + 3) * 27 + 4.
+ '''
+
+ if len(offset) not in range(1, 5):
+ raise ValueError("offset must be four characters or less")
+ uid = 0L
+ offset = offset.upper()
+ for c in offset:
+ try:
+ ordc = " ABCDEFGHIJKLMNOPQRSTUVWXYZ".index(c)
+ except ValueError:
+ raise ValueError("invalid character '%s' in offset" % c)
+ uid *= 27
+ uid += ordc
+ return uid
+
+
+##############################################################################
+# Resource class for containing binary fields
+##############################################################################
+
+class Resource(object):
+ '''A Symbian OS resource type
+
+ Limitations:
+
+ - Write only
+ - Available types are limited to BYTE, WORD, LONG, LLINK and LTEXT.
+ - Unicode compression is not supported.'''
+
+ def __init__(self, fieldtypes, *args):
+ self.fieldtypes = fieldtypes
+ self.fieldvalues = []
+
+ if len(self.fieldtypes) != len(args):
+ raise ValueError("invalid number of field values")
+
+ offset = 0
+ for n in xrange(len(args)):
+ ftype = self.fieldtypes[n]
+ fval = args[n]
+ if ftype == "BYTE":
+ if fval < 0:
+ fval += 0x100
+ if fval < 0 or fval > 255:
+ raise ValueError("byte integer too large")
+ self.fieldvalues.append(struct.pack("<B", fval))
+ offset += 1
+ elif ftype == "WORD":
+ if fval < 0:
+ fval += 0x10000
+ if fval < 0 or fval > 65535:
+ raise ValueError("word integer too large")
+ self.fieldvalues.append(struct.pack("<H", fval))
+ offset += 2
+ elif ftype == "LONG" or ftype == "LLINK":
+ if fval < 0:
+ fval += 0x100000000L
+ if fval < 0 or fval > 4294967295:
+ raise ValueError("long integer too large")
+ self.fieldvalues.append(struct.pack("<L", fval))
+ offset += 4
+ elif ftype == "LTEXT":
+ if len(fval) > 255:
+ raise ValueError("Unicode string too long")
+ self.fieldvalues.append(struct.pack("<B", len(fval)))
+ offset += 1
+ if len(fval) > 0:
+ if (offset & 1) != 0:
+ # Odd offset. Add padding byte (only if length > 0).
+ self.fieldvalues.append(struct.pack("B", 0xab))
+ offset += 1
+ fval_enc = fval.encode("UTF-16LE")
+ self.fieldvalues.append(fval_enc)
+ offset += len(fval_enc)
+
+ # TODO: Arrays, recursive structs
+ # TODO: TEXT, DOUBLE, BUF, BUF8, BUF<n>, LINK, SRLINK
+
+ def tostring(self):
+ return "".join(self.fieldvalues)
+
+ # TODO: fromstring()
+
+
+##############################################################################
+# RSCWriter class for creating Symbian OS compiled resource files (RSC)
+##############################################################################
+
+class RSCWriter(object):
+ '''A Symbian OS compiled resource file (RSC) file generator
+
+ Limitations:
+
+ - Output format is always "Compressed Unicode resource format".
+ - Despite the format name, nothing is compressed.'''
+
+ def __init__(self, uid2, uid3 = None, offset = None):
+ self.resources = []
+
+ if ((uid3 == None and offset == None) or
+ (uid3 != None and offset != None)):
+ raise AttributeError("one of uid3 or offset required, not both")
+
+ self.flags = 0x00
+ if offset != None:
+ try:
+ uid3 = makeuidfromoffset(offset)
+ except:
+ raise ValueError("invalid offset '%s'" % offset)
+ self.flags = 0x01
+
+ self.uid2 = uid2
+ self.uid3 = uid3
+
+ def addresource(self, resource):
+ self.addrawresource(resource.tostring())
+
+ def addrawresource(self, string):
+ self.resources.append(string)
+
+ def tostring(self):
+ # UIDs (UID1 always 0x101f4a6b)
+ fields = [symbianutil.uidstostring(0x101f4a6bL, self.uid2, self.uid3)]
+
+ # Flags
+ fields.append(struct.pack("<B", self.flags))
+
+ # Longest resource (to be updated)
+ fields.append("\0\0")
+
+ # Unicode compression bitmap (no compression)
+ fields.append("\0" * ((len(self.resources) + 7) / 8))
+
+ # Resource contents
+ offsets = []
+ foffset = len("".join(fields))
+ maxrlen = 0
+ for res in self.resources:
+ # Find longest resource.
+ rlen = len(res)
+ if rlen > maxrlen:
+ maxrlen = rlen
+ offsets.append(foffset)
+ fields.append(res)
+ foffset += rlen
+ offsets.append(foffset)
+
+ # Update longest resource.
+ fields[2] = struct.pack("<H", maxrlen)
+
+ # Resource index
+ for off in offsets:
+ fields.append(struct.pack("<H", off))
+
+ # TODO: Ineffiecient. Improve.
+ return "".join(fields)