1/*
2 * Several methods of NSBezierPath cannot be handled automaticly because the
3 * size of a C-style array depends on the value of another argument.
4 */
5
6static PyObject*
7call_NSBezierPath_elementAtIndex_associatedPoints_(
8	PyObject* method,
9	PyObject* self, PyObject* arguments)
10{
11	PyObject* result;
12	PyObject* v;
13	struct objc_super super;
14	NSInteger    idx;
15	int    pointCount;
16	NSPoint points[3];
17	NSBezierPathElement res;
18
19	if  (!PyArg_ParseTuple(arguments, Py_ARG_NSInteger, &idx)) {
20		return NULL;
21	}
22
23	PyObjC_DURING
24		if (PyObjCIMP_Check(method)) {
25			res = ((NSBezierPathElement(*)(id,SEL,NSInteger,NSPoint*))
26			   PyObjCIMP_GetIMP(method))(
27			   	PyObjCObject_GetObject(self),
28				PyObjCIMP_GetSelector(method),
29				idx,
30				points
31			   );
32		} else {
33			PyObjC_InitSuper(&super,
34				PyObjCSelector_GetClass(method),
35				PyObjCObject_GetObject(self));
36
37
38			res = ((NSBezierPathElement(*)(struct objc_super*, SEL, NSInteger, NSPoint*))objc_msgSendSuper)(&super,
39				PyObjCSelector_GetSelector(method),
40				idx,
41				points);
42		}
43	PyObjC_HANDLER
44		PyObjCErr_FromObjC(localException);
45	PyObjC_ENDHANDLER
46
47	if (PyErr_Occurred()) {
48		return NULL;
49	}
50
51	switch (res) {
52	case NSMoveToBezierPathElement: pointCount = 1; break;
53	case NSLineToBezierPathElement: pointCount = 1; break;
54	case NSCurveToBezierPathElement: pointCount = 3; break;
55	case NSClosePathBezierPathElement: pointCount = 0; break;
56	default:
57		PyErr_SetString(PyExc_ValueError,
58			"ObjC returned illegal value");
59		return NULL;
60	}
61
62	result = PyTuple_New(2);
63	if (result == NULL) return NULL;
64
65	v = PyObjC_ObjCToPython(@encode(NSBezierPathElement), &res);
66	if (v == NULL) {
67		Py_DECREF(result);
68		return NULL;
69	}
70
71	PyTuple_SET_ITEM(result, 0, v);
72
73	v = PyObjC_CArrayToPython(@encode(NSPoint), points, pointCount);
74	if (v == NULL) {
75		Py_DECREF(result);
76		return NULL;
77	}
78	PyTuple_SET_ITEM(result, 1, v);
79
80	return result;
81}
82
83static PyObject*
84call_NSBezierPath_setAssociatedPoints_atIndex_(
85	PyObject* method,
86	PyObject* self, PyObject* arguments)
87{
88	PyObject* result;
89	struct objc_super super;
90	NSInteger    idx;
91	NSPoint points[3];
92	PyObject* pointList;
93	PyObject* seq;
94	int i, len;
95
96	if  (!PyArg_ParseTuple(arguments, "O" Py_ARG_NSInteger,
97				&pointList, &idx)) {
98		return NULL;
99	}
100
101	memset(points, 0, sizeof(points));
102
103	seq = PySequence_Fast(pointList, "points is not a sequence");
104	if (seq == NULL) {
105		return NULL;
106	}
107
108	len = PySequence_Fast_GET_SIZE(seq);
109	if (len > 3) {
110		Py_DECREF(seq);
111		PyErr_SetString(PyExc_ValueError, "Need at most 3 elements");
112		return NULL;
113	}
114
115	for (i = 0; i < len; i++) {
116		int err = PyObjC_PythonToObjC(@encode(NSPoint),
117			PySequence_Fast_GET_ITEM(seq, i), points + i);
118		if (err == -1) {
119			return NULL;
120		}
121	}
122
123	PyObjC_DURING
124		if (PyObjCIMP_Check(method)) {
125			((void(*)(id,SEL,NSPoint*,NSInteger))
126			   PyObjCIMP_GetIMP(method))(
127			   	PyObjCObject_GetObject(self),
128				PyObjCIMP_GetSelector(method),
129				points,
130				idx);
131		} else {
132			PyObjC_InitSuper(&super,
133				PyObjCSelector_GetClass(method),
134				PyObjCObject_GetObject(self));
135
136
137			((void(*)(struct objc_super*, SEL, NSPoint*, NSInteger))objc_msgSendSuper)(&super,
138				PyObjCSelector_GetSelector(method),
139				points,
140				idx);
141		}
142	PyObjC_HANDLER
143		PyObjCErr_FromObjC(localException);
144		result = NULL;
145	PyObjC_ENDHANDLER
146
147	if (PyErr_Occurred()) return NULL;
148
149	result = Py_None;
150	Py_INCREF(result);
151
152	return result;
153}
154
155static void
156imp_NSBezierPath_elementAtIndex_associatedPoints_(
157	void* cif __attribute__((__unused__)),
158	void* resp,
159	void** args,
160	void* callable)
161{
162	id self = *(id*)args[0];
163	//SEL _meth = *(SEL*)args[1];
164	NSInteger idx = *(NSInteger*)args[2];
165	NSPoint* points = *(NSPoint**)args[3];
166
167	PyObject* result;
168	PyObject* seq = NULL;
169	PyObject* arglist = NULL;
170	PyObject* v;
171	int err;
172	int pointCount;
173	int i;
174	PyObject* pyself = NULL;
175	int cookie = 0;
176
177	PyGILState_STATE state = PyGILState_Ensure();
178
179	arglist = PyTuple_New(2);
180	if (arglist == NULL) goto error;
181
182	pyself = PyObjCObject_NewTransient(self, &cookie);
183	if (pyself == NULL) goto error;
184	PyTuple_SetItem(arglist, 0, pyself);
185	Py_INCREF(pyself);
186
187	v = PyInt_FromLong(idx);
188	if (v == NULL) goto error;
189	PyTuple_SET_ITEM(arglist, 1, v);
190
191	result = PyObject_Call((PyObject*)callable, arglist, NULL);
192	Py_DECREF(arglist); arglist = NULL;
193	PyObjCObject_ReleaseTransient(pyself, cookie); pyself = NULL;
194	if (result == NULL) goto error;
195
196	seq = PySequence_Fast(result, "should return tuple of lenght 2");
197	Py_DECREF(result);
198	if (seq == NULL) goto error;
199
200	if (PySequence_Fast_GET_SIZE(seq) != 2) {
201		PyErr_SetString(PyExc_ValueError,
202			"should return tuple of lenght 2");
203		goto error;
204	}
205
206	v = PySequence_Fast_GET_ITEM(seq, 0);
207
208	err = PyObjC_PythonToObjC(@encode(NSBezierPathElement), v, resp);
209	if (err == -1) goto error;
210
211	v = PySequence_Fast(PySequence_Fast_GET_ITEM(seq, 1),
212		"result[1] should be a sequence");
213	if (v == NULL) goto error;
214
215	switch (*(NSBezierPathElement*)resp) {
216	case NSMoveToBezierPathElement: pointCount = 1; break;
217	case NSLineToBezierPathElement: pointCount = 1; break;
218	case NSCurveToBezierPathElement: pointCount = 3; break;
219	case NSClosePathBezierPathElement: pointCount = 0; break;
220	default:
221		PyErr_SetString(PyExc_ValueError,
222			"Return[0] should be NS{*}PathElement");
223		Py_DECREF(v);
224		goto error;
225	}
226
227	if (PySequence_Fast_GET_SIZE(v) != pointCount) {
228		PyErr_SetString(PyExc_ValueError,
229			"wrong number of points");
230		Py_DECREF(v);
231		goto error;
232	}
233
234	for (i = 0; i < pointCount; i++) {
235		err = PyObjC_PythonToObjC(@encode(NSPoint),
236			PySequence_Fast_GET_ITEM(v, i),
237			points + i);
238		if (err == -1) {
239			Py_DECREF(v);
240			goto error;
241		}
242	}
243
244	Py_DECREF(v);
245	Py_DECREF(seq);
246	PyGILState_Release(state);
247	return;
248
249error:
250	*(NSBezierPathElement*)resp = 0;
251	Py_XDECREF(arglist);
252	if (pyself) {
253		PyObjCObject_ReleaseTransient(pyself, cookie);
254	}
255	Py_XDECREF(seq);
256	PyObjCErr_ToObjCWithGILState(&state);
257}
258
259
260static int setup_nsbezierpath(PyObject* m __attribute__((__unused__)))
261{
262	Class cls = objc_lookUpClass("NSBezierPath");
263	if (!cls) {
264		return 0;
265	}
266
267	if (PyObjC_RegisterMethodMapping(cls,
268		@selector(elementAtIndex:associatedPoints:),
269		call_NSBezierPath_elementAtIndex_associatedPoints_,
270		imp_NSBezierPath_elementAtIndex_associatedPoints_) < 0 ) {
271
272		return -1;
273	}
274
275	if (PyObjC_RegisterMethodMapping(cls,
276		@selector(setAssociatedPoints:atIndex:),
277		call_NSBezierPath_setAssociatedPoints_atIndex_,
278		PyObjCUnsupportedMethod_IMP) < 0 ) {
279
280		return -1;
281	}
282	return 0;
283}
284