1"""Mac-only module to find the home file of a resource."""
2
3from __future__ import print_function, division, absolute_import
4from fontTools.misc.py23 import *
5from fontTools.misc import sstruct
6import array
7import calldll
8import macfs, Res
9
10
11def HomeResFile(res):
12	"""Return a path to the file in which resource 'res' lives."""
13	return GetFileLocation(res.HomeResFile())
14
15
16def GetFileLocation(refNum):
17	"""Return a path to the open file identified with refNum."""
18	pb = ParamBlock(refNum)
19	return pb.getPath()
20
21#
22# Internal cruft, adapted from MoreFiles
23#
24
25_InterfaceLib = calldll.getlibrary("InterfaceLib")
26GetVRefNum = calldll.newcall(_InterfaceLib.GetVRefNum, "None", "InShort", "OutShort")
27_getInfo = calldll.newcall(_InterfaceLib.PBGetFCBInfoSync, "Short", "InLong")
28
29
30_FCBPBFormat = """
31	qLink:        l
32	qType:        h
33	ioTrap:       h
34	ioCmdAddr:    l
35	ioCompletion: l
36	ioResult:     h
37	ioNamePtr:    l
38	ioVRefNum:    h
39	ioRefNum:     h
40	filler:       h
41	ioFCBIndx:    h
42	filler1:      h
43	ioFCBFINm:    l
44	ioFCBFlags:   h
45	ioFCBStBlk:   h
46	ioFCBEOF:     l
47	ioFCBPLen:    l
48	ioFCBCrPs:    l
49	ioFCBVRefNum: h
50	ioFCBClpSiz:  l
51	ioFCBParID:   l
52"""
53
54class ParamBlock(object):
55
56	"""Wrapper for the very low level FCBPB record."""
57
58	def __init__(self, refNum):
59		self.__fileName = array.array("c", "\0" * 64)
60		sstruct.unpack(_FCBPBFormat,
61				"\0" * sstruct.calcsize(_FCBPBFormat), self)
62		self.ioNamePtr = self.__fileName.buffer_info()[0]
63		self.ioRefNum = refNum
64		self.ioVRefNum = GetVRefNum(refNum)
65		self.__haveInfo = 0
66
67	def getInfo(self):
68		if self.__haveInfo:
69			return
70		data = sstruct.pack(_FCBPBFormat, self)
71		buf = array.array("c", data)
72		ptr = buf.buffer_info()[0]
73		err = _getInfo(ptr)
74		if err:
75			raise Res.Error("can't get file info", err)
76		sstruct.unpack(_FCBPBFormat, buf.tostring(), self)
77		self.__haveInfo = 1
78
79	def getFileName(self):
80		self.getInfo()
81		data = self.__fileName.tostring()
82		return data[1:byteord(data[0])+1]
83
84	def getFSSpec(self):
85		self.getInfo()
86		vRefNum = self.ioVRefNum
87		parID = self.ioFCBParID
88		return macfs.FSSpec((vRefNum, parID, self.getFileName()))
89
90	def getPath(self):
91		return self.getFSSpec().as_pathname()
92
93
94if __name__ == "__main__":
95	fond = Res.GetNamedResource("FOND", "Helvetica")
96	print(HomeResFile(fond))
97