xref: /haiku/src/kits/tracker/PoseViewScripting.cpp (revision 3cb015b1ee509d69c643506e8ff573808c86dcfc)
1 /*
2 Open Tracker License
3 
4 Terms and Conditions
5 
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7 
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
14 
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
17 
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
28 
29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30 of Be Incorporated in the United States and other countries. Other brand product
31 names are registered trademarks or trademarks of their respective holders.
32 All rights reserved.
33 */
34 
35 //	PoseView scripting interface
36 
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <string.h>
40 
41 #include <ByteOrder.h>
42 #include <Debug.h>
43 #include <Message.h>
44 #include <PropertyInfo.h>
45 
46 #include "Tracker.h"
47 #include "PoseView.h"
48 
49 #define kPosesSuites "suite/vnd.Be-TrackerPoses"
50 
51 #define kPropertyPath "Path"
52 
53 #ifndef _SCRIPTING_ONLY
54 	#if _SUPPORTS_FEATURE_SCRIPTING
55 		#define _SCRIPTING_ONLY(x) x
56 	#else
57 		#define _SCRIPTING_ONLY(x)
58 	#endif
59 #endif
60 
61 // notes on PoseView scripting interface:
62 // Indices and entry_refs are used to specify poses; In the case of indices
63 // and previous/next specifiers the current PoseView sort order is used.
64 // If PoseView is not in list view mode, the order in which poses are indexed
65 // is arbitrary.
66 // Both of these specifiers, but indices more so, are likely to be accurate only
67 // till a next change to the PoseView (a change may be adding, removing a pose, changing
68 // an attribute or stat resulting in a sort ordering change, changing the sort ordering
69 // rule. When getting a selected item, there is no guarantee that the item will still
70 // be selected after the operation. The client must be able to deal with these
71 // inaccuracies.
72 // Specifying an index/entry_ref that no longer exists will be handled well.
73 
74 #if 0
75 doo Tracker get Suites of Poses of Window test
76 doo Tracker get Path of Poses of Window test
77 doo Tracker count Entry of Poses of Window test
78 doo Tracker get Entry of Poses of Window test
79 doo Tracker get Entry 2 of Poses of Window test
80 doo Tracker count Selection of Poses of Window test
81 doo Tracker get Selection of Poses of Window test
82 doo Tracker delete Entry 'test/6L6' of Poses of Window test
83 doo Tracker execute Entry 'test/6L6' of Poses of Window test
84 doo Tracker execute Entry 2 of Poses of Window test
85 doo Tracker set Selection of Poses of Window test to [0,2]
86 doo Tracker set Selection of Poses of Window test to 'test/KT55'
87 doo Tracker create Selection of Poses of Window test to 'test/EL34'
88 doo Tracker delete Selection 'test/EL34' of Poses of Window test
89 #endif
90 
91 // ToDo:
92 //	access list view column state
93 //	access poses
94 //				- pose location
95 //				- pose text widgets
96 
97 
98 #if _SUPPORTS_FEATURE_SCRIPTING
99 
100 const property_info kPosesPropertyList[] = {
101 	{	kPropertyPath,
102 		{ B_GET_PROPERTY },
103 		{ B_DIRECT_SPECIFIER },
104 		"get Path of ... # returns the path of a Tracker window, "
105 			"error if no path associated",
106 		0,
107 		{ B_REF_TYPE },
108 		{},
109 		{}
110 	},
111 	{	kPropertyEntry,
112 		{ B_COUNT_PROPERTIES },
113 		{ B_DIRECT_SPECIFIER },
114 		"count Entry of ... # count entries in a PoseView",
115 		0,
116 		{ B_INT32_TYPE },
117 		{},
118 		{}
119 	},
120 	{	kPropertyEntry,
121 		{ B_DELETE_PROPERTY },
122 		{ B_ENTRY_SPECIFIER, B_INDEX_SPECIFIER },
123 		"delete Entry {path|index} # deletes specified entries in a PoseView",
124 		0,
125 		{},
126 		{},
127 		{}
128 	},
129 	{	kPropertyEntry,
130 		{ B_GET_PROPERTY },
131 		{ B_DIRECT_SPECIFIER, B_INDEX_SPECIFIER, kPreviousSpecifier, kNextSpecifier },
132 		"get Entry [next|previous|index] # returns specified entries",
133 		0,
134 		{ B_REF_TYPE },
135 		{},
136 		{}
137 	},
138 	{	kPropertyEntry,
139 		{ B_EXECUTE_PROPERTY },
140 		{ B_ENTRY_SPECIFIER, B_INDEX_SPECIFIER },
141 		"execute Entry {path|index}	# opens specified entries",
142 		0,
143 		{ B_REF_TYPE },
144 		{},
145 		{}
146 	},
147 	{	kPropertySelection,
148 		{ B_GET_PROPERTY },
149 		{ B_DIRECT_SPECIFIER, kPreviousSpecifier, kNextSpecifier },
150 		"get Selection [next|previous] # returns the selected entries",
151 		0,
152 		{ B_REF_TYPE },
153 		{},
154 		{}
155 	},
156 	{	kPropertySelection,
157 		{ B_SET_PROPERTY },
158 		{ B_DIRECT_SPECIFIER, kPreviousSpecifier, kNextSpecifier },
159 		"set Selection of ... to {next|previous|entry} # selects specified entries",
160 		0,
161 		{},
162 		{},
163 		{}
164 	},
165 	{	kPropertySelection,
166 		{ B_COUNT_PROPERTIES },
167 		{ B_DIRECT_SPECIFIER },
168 		"count Selection of ... # counts selected items",
169 		0,
170 		{ B_INT32_TYPE },
171 		{},
172 		{}
173 	},
174 	{	kPropertySelection,
175 		{ B_CREATE_PROPERTY },
176 		{ B_DIRECT_SPECIFIER },
177 		"create selection of ... to {entry|index} "
178 		"# adds specified items to a selection in a PoseView",
179 		0,
180 		{},
181 		{},
182 		{}
183 	},
184 	{	kPropertySelection,
185 		{ B_DELETE_PROPERTY },
186 		{ B_ENTRY_SPECIFIER, B_INDEX_SPECIFIER },
187 		"delete selection {path|index} of ... "
188 		"# removes specified items from a selection in a PoseView",
189 		0,
190 		{},
191 		{},
192 		{}
193 	},
194 	{NULL,
195 		{},
196 		{},
197 		NULL, 0,
198 		{},
199 		{},
200 		{}
201 	}
202 };
203 
204 #endif
205 
206 status_t
207 BPoseView::GetSupportedSuites(BMessage *_SCRIPTING_ONLY(data))
208 {
209 #if _SUPPORTS_FEATURE_SCRIPTING
210 	data->AddString("suites", kPosesSuites);
211 	BPropertyInfo propertyInfo(const_cast<property_info *>(kPosesPropertyList));
212 	data->AddFlat("messages", &propertyInfo);
213 
214 	return _inherited::GetSupportedSuites(data);
215 #else
216 	return B_UNSUPPORTED;
217 #endif
218 }
219 
220 bool
221 BPoseView::HandleScriptingMessage(BMessage *_SCRIPTING_ONLY(message))
222 {
223 #if _SUPPORTS_FEATURE_SCRIPTING
224 	if (message->what != B_GET_PROPERTY
225 		&& message->what != B_SET_PROPERTY
226 		&& message->what != B_CREATE_PROPERTY
227 		&& message->what != B_COUNT_PROPERTIES
228 		&& message->what != B_DELETE_PROPERTY
229 		&& message->what != B_EXECUTE_PROPERTY)
230 		return false;
231 
232 	// dispatch scripting messages
233 	BMessage reply(B_REPLY);
234 	const char *property = 0;
235 	bool handled = false;
236 
237 	int32 index = 0;
238 	int32 form = 0;
239 	BMessage specifier;
240 	status_t result = message->GetCurrentSpecifier(&index, &specifier,
241 		&form, &property);
242 
243 	if (result != B_OK || index == -1)
244 		return false;
245 
246 	ASSERT(property);
247 
248 	switch (message->what) {
249 		case B_CREATE_PROPERTY:
250 			handled = CreateProperty(message, &specifier, form, property, &reply);
251 			break;
252 
253 		case B_GET_PROPERTY:
254 			handled = GetProperty(&specifier, form, property, &reply);
255 			break;
256 
257 		case B_SET_PROPERTY:
258 			handled = SetProperty(message, &specifier, form, property, &reply);
259 			break;
260 
261 		case B_COUNT_PROPERTIES:
262 			handled = CountProperty(&specifier, form, property, &reply);
263 			break;
264 
265 		case B_DELETE_PROPERTY:
266 			handled = DeleteProperty(&specifier, form, property, &reply);
267 			break;
268 
269 		case B_EXECUTE_PROPERTY:
270 			handled = ExecuteProperty(&specifier, form, property, &reply);
271 			break;
272 	}
273 
274 	if (handled)
275 		// done handling message, send a reply
276 		message->SendReply(&reply);
277 	return handled;
278 #else
279 	return false;
280 #endif
281 }
282 
283 bool
284 BPoseView::ExecuteProperty(BMessage *_SCRIPTING_ONLY(specifier),
285 	int32 _SCRIPTING_ONLY(form), const char *_SCRIPTING_ONLY(property),
286 	BMessage *_SCRIPTING_ONLY(reply))
287 {
288 #if _SUPPORTS_FEATURE_SCRIPTING
289 	status_t error = B_OK;
290 	bool handled = false;
291 	if (strcmp(property, kPropertyEntry) == 0) {
292 		BMessage launchMessage(B_REFS_RECEIVED);
293 
294 		if (form == (int32)B_ENTRY_SPECIFIER) {
295 			// move all poses specified by entry_ref to Trash
296 			entry_ref ref;
297 			for (int32 index = 0; specifier->FindRef("refs", index, &ref)
298 				== B_OK; index++)
299 				launchMessage.AddRef("refs", &ref);
300 
301 		} else if (form == (int32)B_INDEX_SPECIFIER) {
302 			// move all poses specified by index to Trash
303 			int32 specifyingIndex;
304 			for (int32 index = 0; specifier->FindInt32("index", index,
305 				&specifyingIndex) == B_OK; index++) {
306 				BPose *pose = PoseAtIndex(specifyingIndex);
307 
308 				if (!pose) {
309 					error = B_ENTRY_NOT_FOUND;
310 					break;
311 				}
312 
313 				launchMessage.AddRef("refs", pose->TargetModel()->EntryRef());
314 			}
315 		} else
316 			return false;
317 
318 		if (error == B_OK) {
319 			// add a messenger to the launch message that will be used to
320 			// dispatch scripting calls from apps to the PoseView
321 			launchMessage.AddMessenger("TrackerViewToken", BMessenger(this, 0, 0));
322 			if (fSelectionHandler)
323 				fSelectionHandler->PostMessage(&launchMessage);
324 		}
325 		handled = true;
326 	}
327 
328 	if (error != B_OK)
329 		reply->AddInt32("error", error);
330 
331 	return handled;
332 #else
333 	return false;
334 #endif
335 }
336 
337 bool
338 BPoseView::CreateProperty(BMessage *_SCRIPTING_ONLY(specifier), BMessage *,
339 	int32 _SCRIPTING_ONLY(form), const char *_SCRIPTING_ONLY(property),
340 	BMessage *_SCRIPTING_ONLY(reply))
341 {
342 #if _SUPPORTS_FEATURE_SCRIPTING
343 	status_t error = B_OK;
344 	bool handled = false;
345 	if (strcmp(property, kPropertySelection) == 0) {
346 		// creating on a selection expands the current selection
347 
348 		if (form != B_DIRECT_SPECIFIER)
349 			// only support direct specifier
350 			return false;
351 
352 		// items to add to a selection may be passed as refs or as indices
353 		if (specifier->HasRef("data")) {
354 			entry_ref ref;
355 			// select poses specified by entries
356 			for (int32 index = 0; specifier->FindRef("data", index, &ref)
357 				== B_OK; index++) {
358 
359 				int32 poseIndex;
360 				BPose *pose = FindPose(&ref, form, &poseIndex);
361 
362 				if (!pose) {
363 					error = B_ENTRY_NOT_FOUND;
364 					handled = true;
365 					break;
366 				}
367 
368 				AddPoseToSelection(pose, poseIndex);
369 			}
370 			handled = true;
371 		} else {
372 			// select poses specified by indices
373 			int32 specifyingIndex;
374 			for (int32 index = 0; specifier->FindInt32("data", index,
375 				&specifyingIndex) == B_OK; index++) {
376 
377 				BPose *pose = PoseAtIndex(specifyingIndex);
378 				if (!pose) {
379 					error = B_BAD_INDEX;
380 					handled = true;
381 					break;
382 				}
383 
384 				AddPoseToSelection(pose, specifyingIndex);
385 			}
386 			handled = true;
387 		}
388 	}
389 
390 	if (error != B_OK)
391 		reply->AddInt32("error", error);
392 
393 	return handled;
394 #else
395 	return false;
396 #endif
397 }
398 
399 bool
400 BPoseView::DeleteProperty(BMessage *_SCRIPTING_ONLY(specifier),
401 	int32 _SCRIPTING_ONLY(form), const char *_SCRIPTING_ONLY(property),
402 	BMessage *_SCRIPTING_ONLY(reply))
403 {
404 #if _SUPPORTS_FEATURE_SCRIPTING
405 	status_t error = B_OK;
406 	bool handled = false;
407 
408 	if (strcmp(property, kPropertySelection) == 0) {
409 		// deleting on a selection is handled as removing a part of the selection
410 		// not to be confused with deleting a selected item
411 
412 		if (form == (int32)B_ENTRY_SPECIFIER) {
413 			entry_ref ref;
414 			// select poses specified by entries
415 			for (int32 index = 0; specifier->FindRef("refs", index, &ref)
416 				== B_OK; index++) {
417 
418 				int32 poseIndex;
419 				BPose *pose = FindPose(&ref, form, &poseIndex);
420 
421 				if (!pose) {
422 					error = B_ENTRY_NOT_FOUND;
423 					break;
424 				}
425 
426 				RemovePoseFromSelection(pose);
427 			}
428 			handled = true;
429 
430 		} else if (form == B_INDEX_SPECIFIER) {
431 			// move all poses specified by index to Trash
432 			int32 specifyingIndex;
433 			for (int32 index = 0; specifier->FindInt32("index", index,
434 				&specifyingIndex) == B_OK; index++) {
435 				BPose *pose = PoseAtIndex(specifyingIndex);
436 
437 				if (!pose) {
438 					error = B_BAD_INDEX;
439 					break;
440 				}
441 
442 				RemovePoseFromSelection(pose);
443 			}
444 			handled = true;
445 		} else
446 			return false;
447 
448 	} else if (strcmp(property, kPropertyEntry) == 0) {
449 		// deleting entries is handled by moving entries to trash
450 
451 		// build a list of entries, specified by the specifier
452 		BObjectList<entry_ref> *entryList = new BObjectList<entry_ref>();
453 			// list will be deleted for us by the trashing thread
454 
455 		if (form == (int32)B_ENTRY_SPECIFIER) {
456 			// move all poses specified by entry_ref to Trash
457 			entry_ref ref;
458 			for (int32 index = 0; specifier->FindRef("refs", index, &ref)
459 				== B_OK; index++)
460 				entryList->AddItem(new entry_ref(ref));
461 
462 		} else if (form == (int32)B_INDEX_SPECIFIER) {
463 			// move all poses specified by index to Trash
464 			int32 specifyingIndex;
465 			for (int32 index = 0; specifier->FindInt32("index", index, &specifyingIndex)
466 				== B_OK; index++) {
467 				BPose *pose = PoseAtIndex(specifyingIndex);
468 
469 				if (!pose) {
470 					error = B_BAD_INDEX;
471 					break;
472 				}
473 
474 				entryList->AddItem(new entry_ref(*pose->TargetModel()->EntryRef()));
475 			}
476 		} else
477 			return false;
478 
479 		if (error == B_OK) {
480 			TrackerSettings settings;
481 			if (!settings.DontMoveFilesToTrash()) {
482 				// move the list we build into trash, don't make the trashing task
483 				// select the next item
484 				MoveListToTrash(entryList, false, false);
485 			} else
486 				Delete(entryList, false, settings.AskBeforeDeleteFile());
487 		}
488 
489 		handled = true;
490 	}
491 
492 	if (error != B_OK)
493 		reply->AddInt32("error", error);
494 
495 	return handled;
496 #else
497 	return false;
498 #endif
499 }
500 
501 bool
502 BPoseView::CountProperty(BMessage *, int32, const char *_SCRIPTING_ONLY(property),
503 	BMessage *_SCRIPTING_ONLY(reply))
504 {
505 #if _SUPPORTS_FEATURE_SCRIPTING
506 	bool handled = false;
507 //	PRINT(("BPoseView::CountProperty, %s\n", property));
508 
509 	// just return the respecitve counts
510 	if (strcmp(property, kPropertySelection) == 0) {
511 		reply->AddInt32("result", fSelectionList->CountItems());
512 		handled = true;
513 	} else if (strcmp(property, kPropertyEntry) == 0) {
514 		reply->AddInt32("result", fPoseList->CountItems());
515 		handled = true;
516 	}
517 	return handled;
518 #else
519 	return false;
520 #endif
521 }
522 
523 bool
524 BPoseView::GetProperty(BMessage *_SCRIPTING_ONLY(specifier),
525 	int32 _SCRIPTING_ONLY(form), const char *_SCRIPTING_ONLY(property),
526 	BMessage *_SCRIPTING_ONLY(reply))
527 {
528 #if _SUPPORTS_FEATURE_SCRIPTING
529 //	PRINT(("GetProperty %s\n", property));
530 	bool handled = false;
531 	status_t error = B_OK;
532 
533 	if (strcmp(property, kPropertyPath) == 0) {
534 		if (form == B_DIRECT_SPECIFIER) {
535 			handled = true;
536 			if (!TargetModel())
537 				error = B_NOT_A_DIRECTORY;
538 			else
539 				reply->AddRef("result", TargetModel()->EntryRef());
540 		}
541 	} else if (strcmp(property, kPropertySelection) == 0) {
542 		int32 count = fSelectionList->CountItems();
543 		switch (form) {
544 			case B_DIRECT_SPECIFIER:
545 				// return entries of all poses in selection
546 				for (int32 index = 0; index < count; index++)
547 					reply->AddRef("result", fSelectionList->ItemAt(index)->
548 						TargetModel()->EntryRef());
549 
550 				handled = true;
551 				break;
552 
553 			case kPreviousSpecifier:
554 			case kNextSpecifier:
555 				{
556 					// return entry and index of selected pose before or after
557 					// specified pose
558 					entry_ref ref;
559 					if (specifier->FindRef("data", &ref) != B_OK)
560 						break;
561 
562 					int32 poseIndex;
563 					BPose *pose = FindPose(&ref, &poseIndex);
564 
565 					for (;;) {
566 						if (form == (int32)kPreviousSpecifier)
567 							pose = PoseAtIndex(--poseIndex);
568 						else if (form == (int32)kNextSpecifier)
569 							pose = PoseAtIndex(++poseIndex);
570 
571 						if (!pose) {
572 							error = B_ENTRY_NOT_FOUND;
573 							break;
574 						}
575 
576 						if (pose->IsSelected()) {
577 							reply->AddRef("result", pose->TargetModel()->EntryRef());
578 							reply->AddInt32("index", IndexOfPose(pose));
579 							break;
580 						}
581 					}
582 
583 					handled = true;
584 					break;
585 				}
586 		}
587 	} else if (strcmp(property, kPropertyEntry) == 0) {
588 		int32 count = fPoseList->CountItems();
589 		switch (form) {
590 			case B_DIRECT_SPECIFIER:
591 				// return all entries of all poses in PoseView
592 				for (int32 index = 0; index < count; index++)
593 					reply->AddRef("result", PoseAtIndex(index)->TargetModel()->EntryRef());
594 
595 				handled = true;
596 				break;
597 			case B_INDEX_SPECIFIER:
598 				{
599 					// return entry at index
600 					int32 index;
601 					if (specifier->FindInt32("index", &index) != B_OK)
602 						break;
603 
604 					if (!PoseAtIndex(index)) {
605 						error = B_BAD_INDEX;
606 						handled = true;
607 						break;
608 					}
609 					reply->AddRef("result", PoseAtIndex(index)->TargetModel()->EntryRef());
610 
611 					handled = true;
612 					break;
613 				}
614 			case kPreviousSpecifier:
615 			case kNextSpecifier:
616 				{
617 					// return entry and index of pose before or after specified pose
618 					entry_ref ref;
619 					if (specifier->FindRef("data", &ref) != B_OK)
620 						break;
621 
622 					int32 tmp;
623 					BPose *pose = FindPose(&ref, form, &tmp);
624 
625 					if (!pose) {
626 						error = B_ENTRY_NOT_FOUND;
627 						handled = true;
628 						break;
629 					}
630 
631 					reply->AddRef("result", pose->TargetModel()->EntryRef());
632 					reply->AddInt32("index", IndexOfPose(pose));
633 
634 					handled = true;
635 					break;
636 				}
637 		}
638 	}
639 
640 	if (error != B_OK)
641 		reply->AddInt32("error", error);
642 
643 	return handled;
644 #else
645 	return false;
646 #endif
647 }
648 
649 bool
650 BPoseView::SetProperty(BMessage *_SCRIPTING_ONLY(message), BMessage *,
651 	int32 _SCRIPTING_ONLY(form), const char *_SCRIPTING_ONLY(property),
652 	BMessage *_SCRIPTING_ONLY(reply))
653 {
654 #if _SUPPORTS_FEATURE_SCRIPTING
655 	status_t error = B_OK;
656 	bool handled = false;
657 
658 	if (strcmp(property, kPropertySelection) == 0) {
659 		entry_ref ref;
660 
661 		switch (form) {
662 			case B_DIRECT_SPECIFIER:
663 				{
664 					int32 selStart;
665 					int32 selEnd;
666 					if (message->FindInt32("data", 0, &selStart) == B_OK
667 						&& message->FindInt32("data", 1, &selEnd) == B_OK) {
668 
669 						if (selStart < 0 || selStart >= fPoseList->CountItems()
670 							|| selEnd < 0 || selEnd >= fPoseList->CountItems()) {
671 							error = B_BAD_INDEX;
672 							handled = true;
673 							break;
674 						}
675 
676 						SelectPoses(selStart, selEnd);
677 						handled = true;
678 						break;
679 					}
680 				}
681 				// fall thru
682 			case kPreviousSpecifier:
683 			case kNextSpecifier:
684 				{
685 					// PRINT(("SetProperty direct/previous/next %s\n", property));
686 					// select/unselect poses specified by entries
687 					bool clearSelection = true;
688 					for (int32 index = 0; message->FindRef("data", index, &ref)
689 						== B_OK; index++) {
690 
691 						int32 poseIndex;
692 						BPose *pose = FindPose(&ref, form, &poseIndex);
693 
694 						if (!pose) {
695 							error = B_ENTRY_NOT_FOUND;
696 							handled = true;
697 							break;
698 						}
699 
700 						if (clearSelection) {
701 							// first selected item must call SelectPose so the selection
702 							// gets cleared first
703 							SelectPose(pose, poseIndex);
704 							clearSelection = false;
705 						} else
706 							AddPoseToSelection(pose, poseIndex);
707 
708 						handled = true;
709 					}
710 					break;
711 				}
712 		}
713 	}
714 
715 	if (error != B_OK)
716 		reply->AddInt32("error", error);
717 
718 	return handled;
719 #else
720 	return false;
721 #endif
722 }
723 
724 BHandler *
725 BPoseView::ResolveSpecifier(BMessage *_SCRIPTING_ONLY(message),
726 	int32 _SCRIPTING_ONLY(index), BMessage *_SCRIPTING_ONLY(specifier),
727 	int32 _SCRIPTING_ONLY(form), const char	*_SCRIPTING_ONLY(property))
728 {
729 #if _SUPPORTS_FEATURE_SCRIPTING
730 	BPropertyInfo propertyInfo(const_cast<property_info *>(kPosesPropertyList));
731 
732 	int32 result = propertyInfo.FindMatch(message, index, specifier, form, property);
733 	if (result < 0) {
734 // 		PRINT(("FindMatch result %d \n"));
735 		return _inherited::ResolveSpecifier(message, index, specifier,
736 			form, property);
737 	}
738 
739 	return this;
740 #else
741 	return NULL;
742 #endif
743 }
744 
745 BPose *
746 BPoseView::FindPose(const entry_ref *_SCRIPTING_ONLY(ref),
747 	int32 _SCRIPTING_ONLY(specifierForm), int32 *_SCRIPTING_ONLY(index)) const
748 {
749 #if _SUPPORTS_FEATURE_SCRIPTING
750 	// flavor of FindPose, used by previous/next specifiers
751 
752 	BPose *pose = FindPose(ref, index);
753 
754 	if (specifierForm == (int32)kPreviousSpecifier)
755 		return PoseAtIndex(--*index);
756 	else if (specifierForm == (int32)kNextSpecifier)
757 		return PoseAtIndex(++*index);
758 	else
759 		return pose;
760 #else
761 	return NULL;
762 #endif
763 }
764 
765