xref: /haiku/src/kits/tracker/PoseViewScripting.cpp (revision 5e96d7d537fbec23bad4ae9b4c8e7b02e769f0c6)
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
67 // only untill a next change to the PoseView (a change may be adding,
68 // removing a pose, changing an attribute or stat resulting in a sort ordering
69 // change, changing the sort ordering rule. When getting a selected item,
70 // there is no guarantee that the item will still be selected after the
71 // operation. The client must be able to deal with these 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,
132 			kNextSpecifier },
133 		"get Entry [next|previous|index] # returns specified entries",
134 		0,
135 		{ B_REF_TYPE },
136 		{},
137 		{}
138 	},
139 	{	kPropertyEntry,
140 		{ B_EXECUTE_PROPERTY },
141 		{ B_ENTRY_SPECIFIER, B_INDEX_SPECIFIER },
142 		"execute Entry {path|index}	# opens specified entries",
143 		0,
144 		{ B_REF_TYPE },
145 		{},
146 		{}
147 	},
148 	{	kPropertySelection,
149 		{ B_GET_PROPERTY },
150 		{ B_DIRECT_SPECIFIER, kPreviousSpecifier, kNextSpecifier },
151 		"get Selection [next|previous] # returns the selected entries",
152 		0,
153 		{ B_REF_TYPE },
154 		{},
155 		{}
156 	},
157 	{	kPropertySelection,
158 		{ B_SET_PROPERTY },
159 		{ B_DIRECT_SPECIFIER, kPreviousSpecifier, kNextSpecifier },
160 		"set Selection of ... to {next|previous|entry} # selects specified "
161 		"entries",
162 		0,
163 		{},
164 		{},
165 		{}
166 	},
167 	{	kPropertySelection,
168 		{ B_COUNT_PROPERTIES },
169 		{ B_DIRECT_SPECIFIER },
170 		"count Selection of ... # counts selected items",
171 		0,
172 		{ B_INT32_TYPE },
173 		{},
174 		{}
175 	},
176 	{	kPropertySelection,
177 		{ B_CREATE_PROPERTY },
178 		{ B_DIRECT_SPECIFIER },
179 		"create selection of ... to {entry|index} "
180 		"# adds specified items to a selection in a PoseView",
181 		0,
182 		{},
183 		{},
184 		{}
185 	},
186 	{	kPropertySelection,
187 		{ B_DELETE_PROPERTY },
188 		{ B_ENTRY_SPECIFIER, B_INDEX_SPECIFIER },
189 		"delete selection {path|index} of ... "
190 		"# removes specified items from a selection in a PoseView",
191 		0,
192 		{},
193 		{},
194 		{}
195 	},
196 	{	NULL,
197 		{},
198 		{},
199 		NULL, 0,
200 		{},
201 		{},
202 		{}
203 	}
204 };
205 
206 #endif
207 
208 
209 status_t
210 BPoseView::GetSupportedSuites(BMessage* _SCRIPTING_ONLY(data))
211 {
212 #if _SUPPORTS_FEATURE_SCRIPTING
213 	data->AddString("suites", kPosesSuites);
214 	BPropertyInfo propertyInfo(
215 		const_cast<property_info*>(kPosesPropertyList));
216 	data->AddFlat("messages", &propertyInfo);
217 
218 	return _inherited::GetSupportedSuites(data);
219 #else
220 	return B_UNSUPPORTED;
221 #endif
222 }
223 
224 
225 bool
226 BPoseView::HandleScriptingMessage(BMessage* _SCRIPTING_ONLY(message))
227 {
228 #if _SUPPORTS_FEATURE_SCRIPTING
229 	if (message->what != B_GET_PROPERTY
230 		&& message->what != B_SET_PROPERTY
231 		&& message->what != B_CREATE_PROPERTY
232 		&& message->what != B_COUNT_PROPERTIES
233 		&& message->what != B_DELETE_PROPERTY
234 		&& message->what != B_EXECUTE_PROPERTY)
235 		return false;
236 
237 	// dispatch scripting messages
238 	BMessage reply(B_REPLY);
239 	const char* property = 0;
240 	bool handled = false;
241 
242 	int32 index = 0;
243 	int32 form = 0;
244 	BMessage specifier;
245 	status_t result = message->GetCurrentSpecifier(&index, &specifier,
246 		&form, &property);
247 
248 	if (result != B_OK || index == -1)
249 		return false;
250 
251 	ASSERT(property);
252 
253 	switch (message->what) {
254 		case B_CREATE_PROPERTY:
255 			handled = CreateProperty(message, &specifier, form, property,
256 				&reply);
257 			break;
258 
259 		case B_GET_PROPERTY:
260 			handled = GetProperty(&specifier, form, property, &reply);
261 			break;
262 
263 		case B_SET_PROPERTY:
264 			handled = SetProperty(message, &specifier, form, property,
265 				&reply);
266 			break;
267 
268 		case B_COUNT_PROPERTIES:
269 			handled = CountProperty(&specifier, form, property, &reply);
270 			break;
271 
272 		case B_DELETE_PROPERTY:
273 			handled = DeleteProperty(&specifier, form, property, &reply);
274 			break;
275 
276 		case B_EXECUTE_PROPERTY:
277 			handled = ExecuteProperty(&specifier, form, property, &reply);
278 			break;
279 	}
280 
281 	if (handled) {
282 		// done handling message, send a reply
283 		message->SendReply(&reply);
284 	}
285 
286 	return handled;
287 #else
288 	return false;
289 #endif
290 }
291 
292 
293 bool
294 BPoseView::ExecuteProperty(BMessage* _SCRIPTING_ONLY(specifier),
295 	int32 _SCRIPTING_ONLY(form), const char* _SCRIPTING_ONLY(property),
296 	BMessage* _SCRIPTING_ONLY(reply))
297 {
298 #if _SUPPORTS_FEATURE_SCRIPTING
299 	status_t error = B_OK;
300 	bool handled = false;
301 	if (strcmp(property, kPropertyEntry) == 0) {
302 		BMessage launchMessage(B_REFS_RECEIVED);
303 
304 		if (form == (int32)B_ENTRY_SPECIFIER) {
305 			// move all poses specified by entry_ref to Trash
306 			entry_ref ref;
307 			for (int32 index = 0; specifier->FindRef("refs", index, &ref)
308 				== B_OK; index++)
309 				launchMessage.AddRef("refs", &ref);
310 		} else if (form == (int32)B_INDEX_SPECIFIER) {
311 			// move all poses specified by index to Trash
312 			int32 specifyingIndex;
313 			for (int32 index = 0; specifier->FindInt32("index", index,
314 				&specifyingIndex) == B_OK; index++) {
315 				BPose* pose = PoseAtIndex(specifyingIndex);
316 
317 				if (!pose) {
318 					error = B_ENTRY_NOT_FOUND;
319 					break;
320 				}
321 
322 				launchMessage.AddRef("refs", pose->TargetModel()->EntryRef());
323 			}
324 		} else
325 			return false;
326 
327 		if (error == B_OK) {
328 			// add a messenger to the launch message that will be used to
329 			// dispatch scripting calls from apps to the PoseView
330 			launchMessage.AddMessenger("TrackerViewToken",
331 				BMessenger(this, 0, 0));
332 			if (fSelectionHandler)
333 				fSelectionHandler->PostMessage(&launchMessage);
334 		}
335 		handled = true;
336 	}
337 
338 	if (error != B_OK)
339 		reply->AddInt32("error", error);
340 
341 	return handled;
342 #else
343 	return false;
344 #endif
345 }
346 
347 
348 bool
349 BPoseView::CreateProperty(BMessage* _SCRIPTING_ONLY(specifier), BMessage*,
350 	int32 _SCRIPTING_ONLY(form), const char* _SCRIPTING_ONLY(property),
351 	BMessage* _SCRIPTING_ONLY(reply))
352 {
353 #if _SUPPORTS_FEATURE_SCRIPTING
354 	status_t error = B_OK;
355 	bool handled = false;
356 	if (strcmp(property, kPropertySelection) == 0) {
357 		// creating on a selection expands the current selection
358 
359 		if (form != B_DIRECT_SPECIFIER)
360 			// only support direct specifier
361 			return false;
362 
363 		// items to add to a selection may be passed as refs or as indices
364 		if (specifier->HasRef("data")) {
365 			entry_ref ref;
366 			// select poses specified by entries
367 			for (int32 index = 0; specifier->FindRef("data", index, &ref)
368 				== B_OK; index++) {
369 
370 				int32 poseIndex;
371 				BPose* pose = FindPose(&ref, form, &poseIndex);
372 
373 				if (!pose) {
374 					error = B_ENTRY_NOT_FOUND;
375 					handled = true;
376 					break;
377 				}
378 
379 				AddPoseToSelection(pose, poseIndex);
380 			}
381 			handled = true;
382 		} else {
383 			// select poses specified by indices
384 			int32 specifyingIndex;
385 			for (int32 index = 0; specifier->FindInt32("data", index,
386 				&specifyingIndex) == B_OK; index++) {
387 
388 				BPose* pose = PoseAtIndex(specifyingIndex);
389 				if (!pose) {
390 					error = B_BAD_INDEX;
391 					handled = true;
392 					break;
393 				}
394 
395 				AddPoseToSelection(pose, specifyingIndex);
396 			}
397 			handled = true;
398 		}
399 	}
400 
401 	if (error != B_OK)
402 		reply->AddInt32("error", error);
403 
404 	return handled;
405 #else
406 	return false;
407 #endif
408 }
409 
410 
411 bool
412 BPoseView::DeleteProperty(BMessage* _SCRIPTING_ONLY(specifier),
413 	int32 _SCRIPTING_ONLY(form), const char* _SCRIPTING_ONLY(property),
414 	BMessage* _SCRIPTING_ONLY(reply))
415 {
416 #if _SUPPORTS_FEATURE_SCRIPTING
417 	status_t error = B_OK;
418 	bool handled = false;
419 
420 	if (strcmp(property, kPropertySelection) == 0) {
421 		// deleting on a selection is handled as removing a part of the
422 		// selection not to be confused with deleting a selected item
423 
424 		if (form == (int32)B_ENTRY_SPECIFIER) {
425 			entry_ref ref;
426 			// select poses specified by entries
427 			for (int32 index = 0; specifier->FindRef("refs", index, &ref)
428 				== B_OK; index++) {
429 
430 				int32 poseIndex;
431 				BPose* pose = FindPose(&ref, form, &poseIndex);
432 
433 				if (!pose) {
434 					error = B_ENTRY_NOT_FOUND;
435 					break;
436 				}
437 
438 				RemovePoseFromSelection(pose);
439 			}
440 			handled = true;
441 
442 		} else if (form == B_INDEX_SPECIFIER) {
443 			// move all poses specified by index to Trash
444 			int32 specifyingIndex;
445 			for (int32 index = 0; specifier->FindInt32("index", index,
446 				&specifyingIndex) == B_OK; index++) {
447 				BPose* pose = PoseAtIndex(specifyingIndex);
448 
449 				if (!pose) {
450 					error = B_BAD_INDEX;
451 					break;
452 				}
453 
454 				RemovePoseFromSelection(pose);
455 			}
456 			handled = true;
457 		} else
458 			return false;
459 
460 	} else if (strcmp(property, kPropertyEntry) == 0) {
461 		// deleting entries is handled by moving entries to trash
462 
463 		// build a list of entries, specified by the specifier
464 		BObjectList<entry_ref>* entryList = new BObjectList<entry_ref>();
465 			// list will be deleted for us by the trashing thread
466 
467 		if (form == (int32)B_ENTRY_SPECIFIER) {
468 			// move all poses specified by entry_ref to Trash
469 			entry_ref ref;
470 			for (int32 index = 0; specifier->FindRef("refs", index, &ref)
471 				== B_OK; index++)
472 				entryList->AddItem(new entry_ref(ref));
473 
474 		} else if (form == (int32)B_INDEX_SPECIFIER) {
475 			// move all poses specified by index to Trash
476 			int32 specifyingIndex;
477 			for (int32 index = 0; specifier->FindInt32("index", index,
478 					&specifyingIndex) == B_OK; index++) {
479 				BPose* pose = PoseAtIndex(specifyingIndex);
480 
481 				if (!pose) {
482 					error = B_BAD_INDEX;
483 					break;
484 				}
485 
486 				entryList->AddItem(
487 					new entry_ref(*pose->TargetModel()->EntryRef()));
488 			}
489 		} else
490 			return false;
491 
492 		if (error == B_OK) {
493 			TrackerSettings settings;
494 			if (!settings.DontMoveFilesToTrash()) {
495 				// move the list we build into trash, don't make the
496 				// trashing task select the next item
497 				MoveListToTrash(entryList, false, false);
498 			} else
499 				Delete(entryList, false, settings.AskBeforeDeleteFile());
500 		}
501 
502 		handled = true;
503 	}
504 
505 	if (error != B_OK)
506 		reply->AddInt32("error", error);
507 
508 	return handled;
509 #else
510 	return false;
511 #endif
512 }
513 
514 
515 bool
516 BPoseView::CountProperty(BMessage*, int32,
517 	const char* _SCRIPTING_ONLY(property),
518 	BMessage* _SCRIPTING_ONLY(reply))
519 {
520 #if _SUPPORTS_FEATURE_SCRIPTING
521 	bool handled = false;
522 	//PRINT(("BPoseView::CountProperty, %s\n", property));
523 
524 	// just return the respecitve counts
525 	if (strcmp(property, kPropertySelection) == 0) {
526 		reply->AddInt32("result", fSelectionList->CountItems());
527 		handled = true;
528 	} else if (strcmp(property, kPropertyEntry) == 0) {
529 		reply->AddInt32("result", fPoseList->CountItems());
530 		handled = true;
531 	}
532 	return handled;
533 #else
534 	return false;
535 #endif
536 }
537 
538 
539 bool
540 BPoseView::GetProperty(BMessage* _SCRIPTING_ONLY(specifier),
541 	int32 _SCRIPTING_ONLY(form), const char* _SCRIPTING_ONLY(property),
542 	BMessage* _SCRIPTING_ONLY(reply))
543 {
544 #if _SUPPORTS_FEATURE_SCRIPTING
545 //	PRINT(("GetProperty %s\n", property));
546 	bool handled = false;
547 	status_t error = B_OK;
548 
549 	if (strcmp(property, kPropertyPath) == 0) {
550 		if (form == B_DIRECT_SPECIFIER) {
551 			handled = true;
552 			if (!TargetModel())
553 				error = B_NOT_A_DIRECTORY;
554 			else
555 				reply->AddRef("result", TargetModel()->EntryRef());
556 		}
557 	} else if (strcmp(property, kPropertySelection) == 0) {
558 		int32 count = fSelectionList->CountItems();
559 		switch (form) {
560 			case B_DIRECT_SPECIFIER:
561 				// return entries of all poses in selection
562 				for (int32 index = 0; index < count; index++)
563 					reply->AddRef("result", fSelectionList->ItemAt(index)->
564 						TargetModel()->EntryRef());
565 
566 				handled = true;
567 				break;
568 
569 			case kPreviousSpecifier:
570 			case kNextSpecifier:
571 				{
572 					// return entry and index of selected pose before or after
573 					// specified pose
574 					entry_ref ref;
575 					if (specifier->FindRef("data", &ref) != B_OK)
576 						break;
577 
578 					int32 poseIndex;
579 					BPose* pose = FindPose(&ref, &poseIndex);
580 
581 					for (;;) {
582 						if (form == (int32)kPreviousSpecifier)
583 							pose = PoseAtIndex(--poseIndex);
584 						else if (form == (int32)kNextSpecifier)
585 							pose = PoseAtIndex(++poseIndex);
586 
587 						if (!pose) {
588 							error = B_ENTRY_NOT_FOUND;
589 							break;
590 						}
591 
592 						if (pose->IsSelected()) {
593 							reply->AddRef("result",
594 								pose->TargetModel()->EntryRef());
595 							reply->AddInt32("index", IndexOfPose(pose));
596 							break;
597 						}
598 					}
599 
600 					handled = true;
601 					break;
602 				}
603 		}
604 	} else if (strcmp(property, kPropertyEntry) == 0) {
605 		int32 count = fPoseList->CountItems();
606 		switch (form) {
607 			case B_DIRECT_SPECIFIER:
608 			{
609 				// return all entries of all poses in PoseView
610 				for (int32 index = 0; index < count; index++) {
611 					reply->AddRef("result",
612 						PoseAtIndex(index)->TargetModel()->EntryRef());
613 				}
614 
615 				handled = true;
616 				break;
617 			}
618 
619 			case B_INDEX_SPECIFIER:
620 			{
621 				// return entry at index
622 				int32 index;
623 				if (specifier->FindInt32("index", &index) != B_OK)
624 					break;
625 
626 				if (!PoseAtIndex(index)) {
627 					error = B_BAD_INDEX;
628 					handled = true;
629 					break;
630 				}
631 				reply->AddRef("result",
632 					PoseAtIndex(index)->TargetModel()->EntryRef());
633 
634 				handled = true;
635 				break;
636 			}
637 
638 			case kPreviousSpecifier:
639 			case kNextSpecifier:
640 			{
641 				// return entry and index of pose before or after
642 				// specified pose
643 				entry_ref ref;
644 				if (specifier->FindRef("data", &ref) != B_OK)
645 					break;
646 
647 				int32 tmp;
648 				BPose* pose = FindPose(&ref, form, &tmp);
649 
650 				if (!pose) {
651 					error = B_ENTRY_NOT_FOUND;
652 					handled = true;
653 					break;
654 				}
655 
656 				reply->AddRef("result", pose->TargetModel()->EntryRef());
657 				reply->AddInt32("index", IndexOfPose(pose));
658 
659 				handled = true;
660 				break;
661 			}
662 		}
663 	}
664 
665 	if (error != B_OK)
666 		reply->AddInt32("error", error);
667 
668 	return handled;
669 #else
670 	return false;
671 #endif
672 }
673 
674 
675 bool
676 BPoseView::SetProperty(BMessage* _SCRIPTING_ONLY(message), BMessage*,
677 	int32 _SCRIPTING_ONLY(form), const char* _SCRIPTING_ONLY(property),
678 	BMessage* _SCRIPTING_ONLY(reply))
679 {
680 #if _SUPPORTS_FEATURE_SCRIPTING
681 	status_t error = B_OK;
682 	bool handled = false;
683 
684 	if (strcmp(property, kPropertySelection) == 0) {
685 		entry_ref ref;
686 
687 		switch (form) {
688 			case B_DIRECT_SPECIFIER:
689 			{
690 				int32 selStart;
691 				int32 selEnd;
692 				if (message->FindInt32("data", 0, &selStart) == B_OK
693 					&& message->FindInt32("data", 1, &selEnd) == B_OK) {
694 
695 					if (selStart < 0 || selStart >= fPoseList->CountItems()
696 						|| selEnd < 0 || selEnd >= fPoseList->CountItems()) {
697 						error = B_BAD_INDEX;
698 						handled = true;
699 						break;
700 					}
701 
702 					SelectPoses(selStart, selEnd);
703 					handled = true;
704 					break;
705 				}
706 			} // fall thru
707 			case kPreviousSpecifier:
708 			case kNextSpecifier:
709 			{
710 				// PRINT(("SetProperty direct/previous/next %s\n", property));
711 				// select/unselect poses specified by entries
712 				bool clearSelection = true;
713 				for (int32 index = 0; message->FindRef("data", index, &ref)
714 					== B_OK; index++) {
715 
716 					int32 poseIndex;
717 					BPose* pose = FindPose(&ref, form, &poseIndex);
718 
719 					if (!pose) {
720 						error = B_ENTRY_NOT_FOUND;
721 						handled = true;
722 						break;
723 					}
724 
725 					if (clearSelection) {
726 						// first selected item must call SelectPose so the
727 						// selection gets cleared first
728 						SelectPose(pose, poseIndex);
729 						clearSelection = false;
730 					} else
731 						AddPoseToSelection(pose, poseIndex);
732 
733 					handled = true;
734 				}
735 				break;
736 			}
737 		}
738 	}
739 
740 	if (error != B_OK)
741 		reply->AddInt32("error", error);
742 
743 	return handled;
744 #else
745 	return false;
746 #endif
747 }
748 
749 
750 BHandler*
751 BPoseView::ResolveSpecifier(BMessage* _SCRIPTING_ONLY(message),
752 	int32 _SCRIPTING_ONLY(index), BMessage* _SCRIPTING_ONLY(specifier),
753 	int32 _SCRIPTING_ONLY(form), const char* _SCRIPTING_ONLY(property))
754 {
755 #if _SUPPORTS_FEATURE_SCRIPTING
756 	BPropertyInfo propertyInfo(
757 		const_cast<property_info*>(kPosesPropertyList));
758 
759 	int32 result = propertyInfo.FindMatch(message, index, specifier, form,
760 		property);
761 	if (result < 0) {
762 		//PRINT(("FindMatch result %d \n"));
763 		return _inherited::ResolveSpecifier(message, index, specifier,
764 			form, property);
765 	}
766 
767 	return this;
768 #else
769 	return NULL;
770 #endif
771 }
772 
773 
774 BPose*
775 BPoseView::FindPose(const entry_ref* _SCRIPTING_ONLY(ref),
776 	int32 _SCRIPTING_ONLY(specifierForm), int32* _SCRIPTING_ONLY(index)) const
777 {
778 #if _SUPPORTS_FEATURE_SCRIPTING
779 	// flavor of FindPose, used by previous/next specifiers
780 
781 	BPose* pose = FindPose(ref, index);
782 
783 	if (specifierForm == (int32)kPreviousSpecifier)
784 		return PoseAtIndex(--*index);
785 	else if (specifierForm == (int32)kNextSpecifier)
786 		return PoseAtIndex(++*index);
787 	else
788 		return pose;
789 #else
790 	return NULL;
791 #endif
792 }
793