2 // a small scripting utility
3 // written by Attila Mezei (attila.mezei@mail.datanet.hu)
4 // contributions by Sander Stoks, Peter Folk, Chris Herborth, Marco Nelissen, Scott Lindsey and others
6 // public domain, use it at your own risk
8 // 1.2.8: (Sander Stoks): Added command-line option -o which will output the "result" value
9 // in the reply message to stdout, so you can use it in shell scripting more easily:
10 // "hey Becasso get AspectRatio of Canvas 0"
12 // Reply BMessage(B_REPLY):
13 // "result" (B_DOUBLE_TYPE) : 0.600
14 // but "hey -o Becasso get AspectRatio of Canvas 0"
15 // outputs 0.600000 directly.
17 // 1.2.7: by Sander Stoks: Made a fork since I don't think Attila still supports "hey", and
18 // because the latest version on BeBits seems to be 1.2.4.
19 // Changes w.r.t. 1.2.6: When an application returns an error on a message, hey now
20 // keeps iterating over applications with the same signature. This is useful because,
21 // for instance, Terminal starts as a new process for each instance, so it previously
22 // wouldn't work to move a specific Terminal window using hey. You can now say
23 // "hey Terminal set Frame of Window foo to BRect[...]".
25 // 1.2.6: syntax extended by Sander Stoks <sander@stoks.nl to allow:
26 // "hey Application let Specifier do ..."
27 // allowing you to send messages directly to other handlers than the app itself.
28 // In cooperation with the new Application defined commands (note that some
29 // Be classes, e.g. BWindow, publish commands as well) this allows, for example:
30 // "hey NetPositive let Window 0 do MoveBy BPoint[10,10]"
31 // Note that this is partly redundant, since
32 // "hey NetPositive let Window 0 do get Title"
33 // duplicates "hey NetPositive get Title of Window 0"
34 // But with the old system,
35 // "hey NetPositive MoveBy of Window 0 with data=BPoint[10,10]"
36 // couldn't work ("MoveBy" is not defined by the Application itself).
38 // 1.2.5: value_info is supported in BPropertyInfo. This means when you send GETSUITES (B_GET_SUPPORTED_SUITES)
39 // the value info is printed after the property infos, like this:
40 // "messages" (B_PROPERTY_INFO_TYPE) :
41 // property commands specifiers
42 // --------------------------------------------------------------------------------
43 // Suites B_GET_PROPERTY DIRECT
44 // Messenger B_GET_PROPERTY DIRECT
45 // InternalName B_GET_PROPERTY DIRECT
48 // --------------------------------------------------------------------------------
49 // Backup 0x6261636B ('back') COMMAND
50 // Usage: This command backs up your hard drive.
51 // Abort 0x61626F72 ('abor') COMMAND
52 // Usage: Stops the current operation...
53 // Type Code 0x74797065 ('type') TYPE CODE
54 // Usage: Type code info...
56 // You can also use the application defined commands (as the verb) with hey:
57 // hey MyBackupApp Backup "Maui"
59 // 1.2.4: the syntax is extended by Peter Folk <pfolk@uni.uiuc.edu> to contain:
60 // do the x of y -3 of z '"1"'
61 // I.e. "do" => B_EXECUTE_PROPERTY, optional "the" makes direct specifiers
62 // more like english, bare reverse-index-specifiers are now handled, and
63 // named specifiers can contain only digits by quoting it (but make sure the
64 // shell passed the quotes through).
66 // Hey(target,const char*,reply) was previously limited to 100 tokens. It
67 // now uses a vector<> so it's only limited by available memory.
69 // Also, the archive name is now Y2K compliant =)
71 // 1.2.3: new option: -s for silent processing (no reply or errors printed) AM
73 // 1.2.2: Fixes by Marco Nelissen (marcone@xs4all.nl)
74 // - fixed parsing of negative numbers
75 // - fixed "with" syntax, which was broken (after a create, "with" would be taken as a specifier)
77 // 1.2.1: compiled for x86, R4 with minor modifications at BPropertyInfo
79 // 1.2.0: the syntax is extended by Sander Stoks (sander@adamation.com) to contain
80 // with name=<value> [and name=<value> [...]]
81 // at the end of the command which will add additional data to the scripting message. E.g:
82 // hey Becasso create Canvas with name=MyCanvas and size=BRect(100,100,300,300)
83 // Also a small interpreter is included.
85 // Detailed printout of B_PROPERTY_INFO in BMessages. Better than BPropertyInfo::PrintToStream().
86 // Also prints usage info for a property if defined.
88 // 1.1.1: minor change from chrish@qnx.com to return -1 if an error is
89 // sent back in the reply message; also added B_COUNT_PROPERTIES support
91 // The range specifier sent to the target was 1 greater than it should've been. Fixed.
93 // 'hey' made the assumption that the first thread in a team will be the
94 // application thread (and therefore have the application's name).
95 // This was not always the case. Fix from Scott Lindsey <wombat@gobe.com>.
97 //v1.1.0: Flattened BPropertyInfo is printed if found in the reply of B_GET_SUPPORTED_SUITES
98 // 1,2,3 and 4 character message constant is supported (e.g. '1', '12', '123', '1234')
99 // Alpha is sent with rgb_color
101 //v1.0.0 First public release
110 #include <SupportDefs.h>
112 int32
HeyInterpreterThreadHook(void* arg
);
114 status_t
Hey(BMessenger
* target
, const char* arg
, BMessage
* reply
);
115 bool isSpace(char c
);
116 status_t
Hey(BMessenger
* target
, char* argv
[], int32
* argx
, int32 argc
, BMessage
* reply
);
117 status_t
add_specifier(BMessage
*to_message
, char *argv
[], int32
*argx
, int32 argc
);
118 status_t
add_data(BMessage
*to_message
, char *argv
[], int32
*argx
);
119 status_t
add_with(BMessage
*to_message
, char *argv
[], int32
*argx
, int32 argc
);
120 void add_message_contents(BList
*textlist
, BMessage
*msg
, int32 level
);
121 char *get_datatype_string(int32 type
);
122 char *format_data(int32 type
, char *ptr
, long size
);
123 void print_message(BMessage
*message
);
124 char *id_to_string(long ID
, char *here
);
125 bool is_valid_char(uint8 c
);
127 const char VERSION
[] = "v1.2.8";
129 #define DEBUG_HEY 0 // 1: prints the script message to be sent to the target application, 0: prints only the reply
132 // test, these should be zero for normal operation
133 #define TEST_VALUEINFO 0
136 // flag for silent mode
138 // flag for stdout mode
142 parse(BMessenger
& the_application
, int argc
, char *argv
[], int32 argapp
)
144 if (!the_application
.IsValid()) {
146 fprintf(stderr
, "Cannot find the application (%s)\n", argv
[argapp
]);
152 fprintf(stderr
, "Cannot find the verb!\n");
158 int32 argx
= argapp
+1;
159 status_t err
= Hey(&the_application
, argv
, &argx
, argc
, &the_reply
);
163 fprintf(stderr
, "Error when sending message to %s!\n",
168 if (the_reply
.what
== (uint32
)B_MESSAGE_NOT_UNDERSTOOD
169 || the_reply
.what
== (uint32
)B_ERROR
) { // I do it myself
170 if (the_reply
.HasString("message")) {
172 printf("%s (error 0x%8" B_PRIx32
")\n",
173 the_reply
.FindString("message"),
174 the_reply
.FindInt32("error"));
178 printf("error 0x%8" B_PRIx32
"\n",
179 the_reply
.FindInt32("error"));
187 if (the_reply
.GetInfo("result", &tc
) == B_OK
) {
188 if (tc
== B_INT8_TYPE
) {
190 the_reply
.FindInt8("result", &v
);
192 } else if (tc
== B_INT16_TYPE
) {
194 the_reply
.FindInt16("result", &v
);
196 } else if (tc
== B_INT32_TYPE
) {
198 the_reply
.FindInt32("result", &v
);
199 printf("%" B_PRId32
"\n", v
);
200 } else if (tc
== B_UINT8_TYPE
) {
202 the_reply
.FindInt8("result", (int8
*)&v
);
204 } else if (tc
== B_UINT16_TYPE
) {
206 the_reply
.FindInt16("result", (int16
*)&v
);
208 } else if (tc
== B_UINT32_TYPE
) {
210 the_reply
.FindInt32("result", (int32
*)&v
);
211 printf("%" B_PRIu32
"\n", v
);
212 } else if (tc
== B_STRING_TYPE
) {
214 the_reply
.FindString("result", &v
);
216 } else if (tc
== B_FLOAT_TYPE
) {
218 the_reply
.FindFloat("result", &v
);
220 } else if (tc
== B_DOUBLE_TYPE
) {
222 the_reply
.FindDouble("result", &v
);
224 } else if (tc
== B_BOOL_TYPE
) {
226 the_reply
.FindBool("result", &v
);
227 printf("%s\n", v
? "true" : "false");
229 printf("Unsupported type\n");
233 print_message(&the_reply
);
246 fprintf(exitCode
== EXIT_SUCCESS
? stdout
: stderr
,
247 "hey %s, written by Attila Mezei (attila.mezei@mail.datanet.hu)\n"
248 "usage: hey [-s][-o] <app|signature|teamid> [let <specifier> do] <verb> <specifier_1> <of\n"
249 " <specifier_n>>* [to <value>] [with name=<value> [and name=<value>]*]\n"
250 "where <verb> : DO|GET|SET|COUNT|CREATE|DELETE|GETSUITES|QUIT|SAVE|LOAD|'what'\n"
251 " <specifier> : [the] <property_name> [ <index> | name | \"name\" | '\"name\"' ]\n"
252 " <index> : int | -int | '['int']' | '['-int']' | '['startint to end']'\n"
253 " <value> : \"string\" | <integer> | <float> | bool(value) | int8(value)\n"
254 " | int16(value) | int32(value) | float(value) | double(value)\n"
255 " | BPoint(x,y) | BRect(l,t,r,b) | rgb_color(r,g,b,a) | file(path)\n"
256 "options: -s: silent\n"
257 " -o: output result to stdout for easy parsing\n\n", VERSION
);
263 main(int argc
, char *argv
[])
265 BApplication
app("application/x-amezei-hey");
274 // Updated option mechanism
275 for (int i
= 0; i
< argc
; i
++) {
276 if (strcmp(argv
[i
], "-s") == 0 || strcmp(argv
[i
], "-S") == 0) {
279 } else if (strcmp(argv
[i
], "-o") == 0 || strcmp(argv
[i
], "-O") == 0) {
282 } else if (strcmp(argv
[1], "-h") == 0
283 || strcmp(argv
[1], "--help") == 0)
287 // find the application
288 BMessenger the_application
;
293 teamid
= atoi(argv
[argapp
]);
295 if (be_roster
->GetRunningAppInfo(teamid
, &appinfo
) != B_OK
)
297 the_application
=BMessenger(NULL
, teamid
);
298 if (!parse(the_application
, argc
, argv
, argapp
))
303 be_roster
->GetAppList(&team_list
);
305 for (int32 i
= 0; i
< team_list
.CountItems(); i
++) {
306 teamid
= (team_id
)(addr_t
)team_list
.ItemAt(i
);
307 be_roster
->GetRunningAppInfo(teamid
, &appinfo
);
308 if (strcmp(appinfo
.signature
, argv
[argapp
]) == 0) {
309 the_application
=BMessenger(appinfo
.signature
);
310 if (!parse(the_application
, argc
, argv
, argapp
))
313 if (strcmp(appinfo
.ref
.name
, argv
[argapp
]) == 0) {
314 the_application
= BMessenger(0, teamid
);
315 if (!parse(the_application
, argc
, argv
, argapp
))
326 HeyInterpreterThreadHook(void* arg
)
331 BMessage
environment(*(BMessage
*) arg
);
332 const char* prompt
= "Hey";
333 if (environment
.HasString("prompt"))
334 environment
.FindString("prompt", &prompt
);
335 printf("%s> ", prompt
);
338 if (environment
.HasMessenger("Target"))
339 environment
.FindMessenger("Target", &target
);
344 while (gets(command
)) {
346 err
= Hey(&target
, command
, &reply
);
348 print_message(&reply
);
352 printf("%s> ", prompt
);
359 Hey(BMessenger
* target
, const char* arg
, BMessage
* reply
)
362 char* tokens
= new char[strlen(arg
) * 2];
363 // number of tokens is limited only by memory
364 char* currentToken
= tokens
;
367 bool inquotes
= false;
369 while (arg
[argNdex
] != 0) { // for each character in arg
370 if (arg
[argNdex
] == '\"')
371 inquotes
= !inquotes
;
372 if (!inquotes
&& isSpace(arg
[argNdex
])) { // if the character is white space
373 if (tokenNdex
!= 0) { // close off currentToken token
374 currentToken
[tokenNdex
] = 0;
375 argv
.AddItem(currentToken
);
376 currentToken
+= tokenNdex
+ 1;
379 } else { // just skip the whitespace
382 } else { // copy char into current token
383 currentToken
[tokenNdex
] = arg
[argNdex
];
389 if (tokenNdex
!=0) { // close off currentToken token
390 currentToken
[tokenNdex
] = 0;
391 argv
.AddItem(currentToken
);
396 status_t ret
= Hey(target
, (char **)argv
.Items(), &argx
, argv
.CountItems() - 1, reply
);
397 // This used to be "return Hey(...);"---so tokens wasn't delete'd.
418 Hey(BMessenger
* target
, char* argv
[], int32
* argx
, int32 argc
, BMessage
* reply
)
420 bool direct_what
= false;
421 BMessage the_message
;
422 if (strcasecmp(argv
[*argx
], "let") == 0) {
423 BMessage
get_target (B_GET_PROPERTY
);
424 get_target
.AddSpecifier ("Messenger");
425 // parse the specifiers
427 status_t result
= B_OK
;
428 while ((result
= add_specifier(&get_target
, argv
, argx
, argc
)) == B_OK
)
431 if (result
!= B_ERROR
) {
433 fprintf(stderr
, "Bad specifier syntax!\n");
437 if (target
&& target
->IsValid()) {
438 result
= target
->SendMessage(&get_target
, &msgr
);
441 result
= msgr
.FindMessenger ("result", target
);
442 if (result
!= B_OK
) {
444 fprintf(stderr
, "Couldn't retrieve the BMessenger!\n");
450 fprintf(stderr
, "Syntax error - forgot \"do\"?\n");
454 if (strcasecmp(argv
[*argx
], "do") == 0)
455 the_message
.what
= B_EXECUTE_PROPERTY
;
456 else if (strcasecmp(argv
[*argx
], "get") == 0)
457 the_message
.what
= B_GET_PROPERTY
;
458 else if (strcasecmp(argv
[*argx
], "set") == 0)
459 the_message
.what
= B_SET_PROPERTY
;
460 else if (strcasecmp(argv
[*argx
], "create") == 0)
461 the_message
.what
= B_CREATE_PROPERTY
;
462 else if (strcasecmp(argv
[*argx
], "delete") == 0)
463 the_message
.what
= B_DELETE_PROPERTY
;
464 else if (strcasecmp(argv
[*argx
], "quit") == 0)
465 the_message
.what
= B_QUIT_REQUESTED
;
466 else if (strcasecmp(argv
[*argx
], "save") == 0)
467 the_message
.what
= B_SAVE_REQUESTED
;
468 else if (strcasecmp(argv
[*argx
], "load") == 0)
469 the_message
.what
= B_REFS_RECEIVED
;
470 else if (strcasecmp(argv
[*argx
], "count") == 0)
471 the_message
.what
= B_COUNT_PROPERTIES
;
472 else if (strcasecmp(argv
[*argx
], "getsuites") == 0)
473 the_message
.what
= B_GET_SUPPORTED_SUITES
;
475 switch(strlen(argv
[*argx
])) {
476 // can be a message constant if 1,2,3 or 4 chars
478 the_message
.what
= (int32
)argv
[*argx
][0];
481 the_message
.what
= (((int32
)argv
[*argx
][0]) << 8)
482 | (((int32
)argv
[*argx
][1]));
485 the_message
.what
= (((int32
)argv
[*argx
][0]) << 16)
486 | (((int32
)argv
[*argx
][1]) << 8)
487 | (((int32
)argv
[*argx
][2]));
490 the_message
.what
= (((int32
)argv
[*argx
][0]) << 24)
491 | (((int32
)argv
[*argx
][1]) << 16)
492 | (((int32
)argv
[*argx
][2]) << 8)
493 | (((int32
)argv
[*argx
][3]));
496 // maybe this is a user defined command, ask for the supported suites
498 if (target
&& target
->IsValid()) {
500 if (target
->SendMessage(B_GET_SUPPORTED_SUITES
, &reply
)
502 // if all goes well, reply contains all kinds of
507 BPropertyInfo propinfo
;
508 const value_info
*vinfo
;
509 int32 vinfo_index
, vinfo_count
;
512 // while (rply.FindString("suites", j++, &str) == B_OK)
513 // printf ("Suite %ld: %s\n", j, str);
516 while (reply
.FindData("messages", B_PROPERTY_INFO_TYPE
,
517 j
++, (const void **)&voidptr
, &sizefound
)
519 if (propinfo
.Unflatten(B_PROPERTY_INFO_TYPE
,
520 (const void *)voidptr
, sizefound
) == B_OK
) {
521 vinfo
= propinfo
.Values();
523 vinfo_count
= propinfo
.CountValues();
525 value_info vinfo
[10] = {
526 {"Backup", 'back', B_COMMAND_KIND
,
527 "This command backs up your hard"
529 {"Abort", 'abor', B_COMMAND_KIND
,
530 "Stops the current operation..."},
531 {"Type Code", 'type', B_TYPE_CODE_KIND
,
537 while (vinfo_index
< vinfo_count
) {
538 if (strcmp(vinfo
[vinfo_index
].name
,
542 vinfo
[vinfo_index
].value
;
544 printf("FOUND COMMAND \"%s\" = %lX\n",
545 vinfo
[vinfo_index
].name
,
559 fprintf(stderr
, "Bad verb (\"%s\")\n", argv
[*argx
]);
566 status_t result
= B_OK
;
569 // One exception: Single data item at end of line.
570 if (direct_what
&& *argx
== argc
- 1 && argv
[*argx
] != NULL
)
571 add_data(&the_message
, argv
, argx
);
573 // parse the specifiers
574 if (the_message
.what
!= B_REFS_RECEIVED
) {
575 // LOAD has no specifier
576 while ((result
= add_specifier(&the_message
, argv
, argx
, argc
))
580 if (result
!= B_ERROR
) {
582 fprintf(stderr
, "Bad specifier syntax!\n");
588 // if verb is SET or LOAD, there should be a to <value>
589 if ((the_message
.what
== B_SET_PROPERTY
|| the_message
.what
== B_REFS_RECEIVED
) && argv
[*argx
] != NULL
) {
590 if (strcasecmp(argv
[*argx
], "to") == 0)
592 result
= add_data(&the_message
, argv
, argx
);
593 if (result
!= B_OK
) {
594 if (result
== B_FILE_NOT_FOUND
) {
596 fprintf(stderr
, "File not found!\n");
598 fprintf(stderr
, "Invalid 'to...' value format!\n");
603 add_with(&the_message
, argv
, argx
, argc
);
606 fprintf(stderr
, "Send ");
607 print_message(&the_message
);
608 fprintf(stderr
, "\n");
611 if (target
&& target
->IsValid()) {
613 result
= target
->SendMessage(&the_message
, reply
);
615 result
= target
->SendMessage(&the_message
);
620 // There can be a with <name>=<type>() [and <name>=<type> ...]
621 // I treat "and" just the same as "with", it's just to make the script syntax more English-like.
623 add_with(BMessage
*to_message
, char *argv
[], int32
*argx
, int32 argc
)
625 status_t result
= B_OK
;
626 if (*argx
< argc
- 1 && argv
[++(*argx
)] != NULL
) {
627 // printf ("argv[%ld] = %s\n", *argx, argv[*argx]);
628 if (strcasecmp(argv
[*argx
], "with") == 0) {
629 // printf ("\"with\" detected!\n");
633 result
= add_data(to_message
, argv
, argx
);
634 if (result
!= B_OK
) {
635 if (result
== B_FILE_NOT_FOUND
) {
637 fprintf(stderr
, "File not found!\n");
640 fprintf(stderr
, "Invalid 'with...' value format!\n");
645 // printf ("argc = %d, argv[%d] = %s\n", argc, *argx, argv[*argx]);
646 if (*argx
< argc
- 1 && strcasecmp(argv
[*argx
], "and") == 0)
656 // returns B_OK if successful
657 // B_ERROR if no more specifiers
658 // B_BAD_SCRIPT_SYNTAX if syntax error
660 add_specifier(BMessage
*to_message
, char *argv
[], int32
*argx
, int32 argc
)
662 char *property
= argv
[*argx
];
664 if (property
== NULL
)
665 return B_ERROR
; // no more specifiers
669 if (strcasecmp(property
, "do") == 0) {
670 // Part of the "hey App let Specifier do Verb".
671 return B_ERROR
; // no more specifiers
674 if (strcasecmp(property
, "to") == 0) {
676 // no more specifiers
679 if (strcasecmp(property
, "with") == 0) {
681 add_with(to_message
, argv
, argx
, argc
);
683 // no more specifiers
686 if (strcasecmp(property
, "of") == 0) {
687 // skip "of", read real property
688 property
= argv
[*argx
];
689 if (property
== NULL
)
690 return B_BAD_SCRIPT_SYNTAX
;
694 if (strcasecmp(property
, "the") == 0) {
695 // skip "the", read real property
696 property
= argv
[*argx
];
697 if (property
== NULL
)
698 return B_BAD_SCRIPT_SYNTAX
;
702 // decide the specifier
704 char *specifier
= NULL
;
705 if (to_message
->what
== B_CREATE_PROPERTY
) {
706 // create is always direct. without this, a "with" would be
707 // taken as a specifier
710 specifier
= argv
[*argx
];
711 if (specifier
== NULL
) {
713 to_message
->AddSpecifier(property
);
715 // no more specifiers
720 if (strcasecmp(specifier
, "of") == 0) {
722 to_message
->AddSpecifier(property
);
726 if (strcasecmp(specifier
, "to") == 0) {
728 to_message
->AddSpecifier(property
);
730 // no more specifiers
734 if (specifier
[0] == '[') {
735 // index, reverse index or range
738 if (specifier
[1] == '-') {
740 ix1
= strtoul(specifier
+ 2, &end
, 10);
741 BMessage
revspec(B_REVERSE_INDEX_SPECIFIER
);
742 revspec
.AddString("property", property
);
743 revspec
.AddInt32("index", ix1
);
744 to_message
->AddSpecifier(&revspec
);
747 ix1
= strtoul(specifier
+ 1, &end
, 10);
750 to_message
->AddSpecifier(property
, ix1
);
753 specifier
= argv
[*argx
];
754 if (specifier
== NULL
) {
755 // I was wrong, it was just an index
756 to_message
->AddSpecifier(property
, ix1
);
760 if (strcasecmp(specifier
, "to") == 0) {
761 specifier
= argv
[*argx
];
762 if (specifier
== NULL
)
763 return B_BAD_SCRIPT_SYNTAX
;
765 ix2
= strtoul(specifier
, &end
, 10);
766 to_message
->AddSpecifier(property
, ix1
, ix2
- ix1
> 0
770 return B_BAD_SCRIPT_SYNTAX
;
775 // if it contains only digits, it will be an index...
776 bool index_spec
= true;
777 bool reverse
= specifier
[0] == '-';
778 // accept bare reverse-index-specs
779 size_t speclen
= strlen(specifier
);
780 for (int32 i
= (reverse
? 1 : 0); i
< (int32
)speclen
; ++i
) {
781 if (specifier
[i
] < '0' || specifier
[i
] > '9') {
790 BMessage
revspec(B_REVERSE_INDEX_SPECIFIER
);
791 revspec
.AddString("property", property
);
792 revspec
.AddInt32("index", atol(specifier
+ 1));
793 to_message
->AddSpecifier(&revspec
);
795 to_message
->AddSpecifier(property
, atol(specifier
));
797 // Allow any name by counting an initial " as a literal-string
799 if (specifier
[0] == '\"') {
800 if (specifier
[speclen
- 1] == '\"')
801 specifier
[speclen
- 1] = '\0';
805 to_message
->AddSpecifier(property
, specifier
);
814 add_data(BMessage
*to_message
, char *argv
[], int32
*argx
)
816 char *valuestring
= argv
[*argx
];
818 if (valuestring
== NULL
)
821 // try to interpret it as an integer or float
822 bool contains_only_digits
= true;
823 bool is_floating_point
= false;
824 for (int32 i
= 0; i
< (int32
)strlen(valuestring
); i
++) {
825 if (i
!= 0 || valuestring
[i
] != '-') {
826 if (valuestring
[i
] < '0' || valuestring
[i
] > '9') {
827 if (valuestring
[i
] == '.') {
828 is_floating_point
= true;
830 contains_only_digits
= false;
836 //printf("%d %d\n", contains_only_digits,is_floating_point);
837 if (contains_only_digits
) {
838 if (is_floating_point
) {
839 to_message
->AddFloat("data", atof(valuestring
));
842 to_message
->AddInt32("data", atol(valuestring
));
847 // if true or false, it is bool
848 if (strcasecmp(valuestring
, "true") == 0) {
849 to_message
->AddBool("data", true);
851 } else if (strcasecmp(valuestring
, "false") == 0) {
852 to_message
->AddBool("data", false);
856 // Add support for "<name>=<type>()" here:
857 // The type is then added under the name "name".
859 #define MAX_NAME_LENGTH 128
860 char curname
[MAX_NAME_LENGTH
];
861 strcpy (curname
, "data"); // This is the default.
863 char *s
= valuestring
;
864 while (*++s
&& *s
!= '=')
865 // Look for a '=' character...
867 if (*s
== '=') { // We found a <name>=
869 strcpy (curname
, valuestring
); // Use the new <name>
870 valuestring
= s
+ 1; // Reposition the valuestring ptr.
873 // must begin with a type( value )
874 if (strncasecmp(valuestring
, "int8", strlen("int8")) == 0)
875 to_message
->AddInt8(curname
, atol(valuestring
+ strlen("int8(")));
876 else if (strncasecmp(valuestring
, "int16", strlen("int16")) == 0)
877 to_message
->AddInt16(curname
, atol(valuestring
+ strlen("int16(")));
878 else if (strncasecmp(valuestring
, "int32", strlen("int32")) == 0)
879 to_message
->AddInt32(curname
, atol(valuestring
+ strlen("int32(")));
880 else if (strncasecmp(valuestring
, "int64", strlen("int64")) == 0)
881 to_message
->AddInt64(curname
, atol(valuestring
+ strlen("int64(")));
882 else if (strncasecmp(valuestring
, "bool", strlen("bool")) == 0) {
883 if (strncasecmp(valuestring
+ strlen("bool("), "true", 4) == 0)
884 to_message
->AddBool(curname
, true);
885 else if (strncasecmp(valuestring
+ strlen("bool("), "false", 5) == 0)
886 to_message
->AddBool(curname
, false);
888 to_message
->AddBool(curname
, atol(valuestring
+ strlen("bool(")) == 0 ? false : true);
889 } else if (strncasecmp(valuestring
, "float", strlen("float")) == 0)
890 to_message
->AddFloat(curname
, atof(valuestring
+ strlen("float(")));
891 else if (strncasecmp(valuestring
, "double", strlen("double")) == 0)
892 to_message
->AddDouble(curname
, atof(valuestring
+ strlen("double(")));
893 else if (strncasecmp(valuestring
, "BPoint", strlen("BPoint")) == 0) {
895 x
= atof(valuestring
+ strlen("BPoint("));
896 if (strchr(valuestring
, ','))
897 y
= atof(strchr(valuestring
, ',') + 1);
898 else if (strchr(valuestring
, ' '))
899 y
= atof(strchr(valuestring
, ' ') + 1);
902 to_message
->AddPoint(curname
, BPoint(x
,y
));
903 } else if (strncasecmp(valuestring
, "BRect", strlen("BRect")) == 0) {
904 float l
= 0.0f
, t
= 0.0f
, r
= 0.0f
, b
= 0.0f
;
906 l
= atof(valuestring
+ strlen("BRect("));
907 ptr
= strchr(valuestring
, ',');
910 ptr
= strchr(ptr
+ 1, ',');
913 ptr
= strchr(ptr
+ 1, ',');
919 to_message
->AddRect(curname
, BRect(l
,t
,r
,b
));
920 } else if (strncasecmp(valuestring
, "rgb_color", strlen("rgb_color")) == 0) {
923 clr
.red
= atol(valuestring
+ strlen("rgb_color("));
924 ptr
= strchr(valuestring
, ',');
926 clr
.green
= atol(ptr
+ 1);
927 ptr
= strchr(ptr
+ 1, ',');
929 clr
.blue
= atol(ptr
+ 1);
930 ptr
= strchr(ptr
+ 1, ',');
932 clr
.alpha
= atol(ptr
+ 1);
936 to_message
->AddData(curname
, B_RGB_COLOR_TYPE
, &clr
, sizeof(rgb_color
));
937 } else if (strncasecmp(valuestring
, "file", strlen("file")) == 0) {
940 // remove the last ] or )
941 if (valuestring
[strlen(valuestring
) - 1] == ')'
942 || valuestring
[strlen(valuestring
) - 1] == ']')
943 valuestring
[strlen(valuestring
) - 1] = 0;
945 if (get_ref_for_path(valuestring
+ 5, &file_ref
) != B_OK
)
946 return B_FILE_NOT_FOUND
;
948 // check if the ref is valid
950 if (entry
.SetTo(&file_ref
) != B_OK
)
951 return B_FILE_NOT_FOUND
;
952 //if(!entry.Exists()) return B_FILE_NOT_FOUND;
954 // add both ways, refsreceived needs it as "refs" while scripting needs "data"
955 to_message
->AddRef("refs", &file_ref
);
956 to_message
->AddRef(curname
, &file_ref
);
959 // does it begin with a quote?
960 if (valuestring
[0] == '\"') {
961 if (valuestring
[strlen(valuestring
) - 1] == '\"')
962 valuestring
[strlen(valuestring
) - 1] = 0;
963 to_message
->AddString(curname
, valuestring
+ 1);
965 to_message
->AddString(curname
, valuestring
);
973 print_message(BMessage
*message
)
976 add_message_contents(&textlist
, message
, 0);
978 char *whatString
= get_datatype_string(message
->what
);
979 printf("BMessage(%s):\n", whatString
);
981 for (int32 i
= 0; i
< textlist
.CountItems(); i
++) {
982 printf(" %s\n", (char*)textlist
.ItemAt(i
));
983 free(textlist
.ItemAt(i
));
989 add_message_contents(BList
*textlist
, BMessage
*msg
, int32 level
)
995 #ifdef HAIKU_TARGET_PLATFORM_DANO
996 const char *namefound
;
1002 char *textline
, *datatype
, *content
;
1004 // go though all message data
1005 count
= msg
->CountNames(B_ANY_TYPE
);
1006 for (i
=0; i
< count
; i
++) {
1007 msg
->GetInfo(B_ANY_TYPE
, i
, &namefound
, &typefound
);
1010 while (msg
->FindData(namefound
, typefound
, j
++, (const void **)&voidptr
,
1011 &sizefound
) == B_OK
) {
1012 datatype
= get_datatype_string(typefound
);
1013 content
= format_data(typefound
, (char*)voidptr
, sizefound
);
1014 textline
= (char*)malloc(20 + level
* 4 + strlen(namefound
)
1015 + strlen(datatype
) + strlen(content
));
1016 memset(textline
, 32, 20 + level
* 4);
1017 sprintf(textline
+ level
* 4, "\"%s\" (%s) : %s", namefound
,
1019 textlist
->AddItem(textline
);
1023 if (typefound
== B_MESSAGE_TYPE
) {
1024 msg
->FindMessage(namefound
, j
- 1, &a_message
);
1025 add_message_contents(textlist
, &a_message
, level
+ 1);
1026 } else if (typefound
== B_RAW_TYPE
&& strcmp(namefound
,
1027 "_previous_") == 0) {
1028 if (a_message
.Unflatten((const char *)voidptr
) == B_OK
)
1029 add_message_contents(textlist
, &a_message
, level
+ 1);
1037 get_datatype_string(int32 type
)
1039 char *str
= new char[128];
1042 case B_ANY_TYPE
: strcpy(str
, "B_ANY_TYPE"); break;
1043 case B_ASCII_TYPE
: strcpy(str
, "B_ASCII_TYPE"); break;
1044 case B_BOOL_TYPE
: strcpy(str
, "B_BOOL_TYPE"); break;
1045 case B_CHAR_TYPE
: strcpy(str
, "B_CHAR_TYPE"); break;
1046 case B_COLOR_8_BIT_TYPE
: strcpy(str
, "B_COLOR_8_BIT_TYPE"); break;
1047 case B_DOUBLE_TYPE
: strcpy(str
, "B_DOUBLE_TYPE"); break;
1048 case B_FLOAT_TYPE
: strcpy(str
, "B_FLOAT_TYPE"); break;
1049 case B_GRAYSCALE_8_BIT_TYPE
: strcpy(str
, "B_GRAYSCALE_8_BIT_TYPE"); break;
1050 case B_INT64_TYPE
: strcpy(str
, "B_INT64_TYPE"); break;
1051 case B_INT32_TYPE
: strcpy(str
, "B_INT32_TYPE"); break;
1052 case B_INT16_TYPE
: strcpy(str
, "B_INT16_TYPE"); break;
1053 case B_INT8_TYPE
: strcpy(str
, "B_INT8_TYPE"); break;
1054 case B_MESSAGE_TYPE
: strcpy(str
, "B_MESSAGE_TYPE"); break;
1055 case B_MESSENGER_TYPE
: strcpy(str
, "B_MESSENGER_TYPE"); break;
1056 case B_MIME_TYPE
: strcpy(str
, "B_MIME_TYPE"); break;
1057 case B_MONOCHROME_1_BIT_TYPE
: strcpy(str
, "B_MONOCHROME_1_BIT_TYPE"); break;
1058 case B_OBJECT_TYPE
: strcpy(str
, "B_OBJECT_TYPE"); break;
1059 case B_OFF_T_TYPE
: strcpy(str
, "B_OFF_T_TYPE"); break;
1060 case B_PATTERN_TYPE
: strcpy(str
, "B_PATTERN_TYPE"); break;
1061 case B_POINTER_TYPE
: strcpy(str
, "B_POINTER_TYPE"); break;
1062 case B_POINT_TYPE
: strcpy(str
, "B_POINT_TYPE"); break;
1063 case B_RAW_TYPE
: strcpy(str
, "B_RAW_TYPE"); break;
1064 case B_RECT_TYPE
: strcpy(str
, "B_RECT_TYPE"); break;
1065 case B_REF_TYPE
: strcpy(str
, "B_REF_TYPE"); break;
1066 case B_RGB_32_BIT_TYPE
: strcpy(str
, "B_RGB_32_BIT_TYPE"); break;
1067 case B_RGB_COLOR_TYPE
: strcpy(str
, "B_RGB_COLOR_TYPE"); break;
1068 case B_SIZE_T_TYPE
: strcpy(str
, "B_SIZE_T_TYPE"); break;
1069 case B_SSIZE_T_TYPE
: strcpy(str
, "B_SSIZE_T_TYPE"); break;
1070 case B_STRING_TYPE
: strcpy(str
, "B_STRING_TYPE"); break;
1071 case B_TIME_TYPE
: strcpy(str
, "B_TIME_TYPE"); break;
1072 case B_UINT64_TYPE
: strcpy(str
, "B_UINT64_TYPE"); break;
1073 case B_UINT32_TYPE
: strcpy(str
, "B_UINT32_TYPE"); break;
1074 case B_UINT16_TYPE
: strcpy(str
, "B_UINT16_TYPE"); break;
1075 case B_UINT8_TYPE
: strcpy(str
, "B_UINT8_TYPE"); break;
1076 case B_PROPERTY_INFO_TYPE
: strcpy(str
, "B_PROPERTY_INFO_TYPE"); break;
1077 // message constants:
1078 case B_ABOUT_REQUESTED
: strcpy(str
, "B_ABOUT_REQUESTED"); break;
1079 case B_WINDOW_ACTIVATED
: strcpy(str
, "B_WINDOW_ACTIVATED"); break;
1080 case B_ARGV_RECEIVED
: strcpy(str
, "B_ARGV_RECEIVED"); break;
1081 case B_QUIT_REQUESTED
: strcpy(str
, "B_QUIT_REQUESTED"); break;
1082 case B_CANCEL
: strcpy(str
, "B_CANCEL"); break;
1083 case B_KEY_DOWN
: strcpy(str
, "B_KEY_DOWN"); break;
1084 case B_KEY_UP
: strcpy(str
, "B_KEY_UP"); break;
1085 case B_MINIMIZE
: strcpy(str
, "B_MINIMIZE"); break;
1086 case B_MOUSE_DOWN
: strcpy(str
, "B_MOUSE_DOWN"); break;
1087 case B_MOUSE_MOVED
: strcpy(str
, "B_MOUSE_MOVED"); break;
1088 case B_MOUSE_ENTER_EXIT
: strcpy(str
, "B_MOUSE_ENTER_EXIT"); break;
1089 case B_MOUSE_UP
: strcpy(str
, "B_MOUSE_UP"); break;
1090 case B_PULSE
: strcpy(str
, "B_PULSE"); break;
1091 case B_READY_TO_RUN
: strcpy(str
, "B_READY_TO_RUN"); break;
1092 case B_REFS_RECEIVED
: strcpy(str
, "B_REFS_RECEIVED"); break;
1093 case B_SCREEN_CHANGED
: strcpy(str
, "B_SCREEN_CHANGED"); break;
1094 case B_VALUE_CHANGED
: strcpy(str
, "B_VALUE_CHANGED"); break;
1095 case B_VIEW_MOVED
: strcpy(str
, "B_VIEW_MOVED"); break;
1096 case B_VIEW_RESIZED
: strcpy(str
, "B_VIEW_RESIZED"); break;
1097 case B_WINDOW_MOVED
: strcpy(str
, "B_WINDOW_MOVED"); break;
1098 case B_WINDOW_RESIZED
: strcpy(str
, "B_WINDOW_RESIZED"); break;
1099 case B_WORKSPACES_CHANGED
: strcpy(str
, "B_WORKSPACES_CHANGED"); break;
1100 case B_WORKSPACE_ACTIVATED
: strcpy(str
, "B_WORKSPACE_ACTIVATED"); break;
1101 case B_ZOOM
: strcpy(str
, "B_ZOOM"); break;
1102 case _APP_MENU_
: strcpy(str
, "_APP_MENU_"); break;
1103 case _BROWSER_MENUS_
: strcpy(str
, "_BROWSER_MENUS_"); break;
1104 case _MENU_EVENT_
: strcpy(str
, "_MENU_EVENT_"); break;
1105 case _QUIT_
: strcpy(str
, "_QUIT_"); break;
1106 case _VOLUME_MOUNTED_
: strcpy(str
, "_VOLUME_MOUNTED_"); break;
1107 case _VOLUME_UNMOUNTED_
: strcpy(str
, "_VOLUME_UNMOUNTED_"); break;
1108 case _MESSAGE_DROPPED_
: strcpy(str
, "_MESSAGE_DROPPED_"); break;
1109 case _MENUS_DONE_
: strcpy(str
, "_MENUS_DONE_"); break;
1110 case _SHOW_DRAG_HANDLES_
: strcpy(str
, "_SHOW_DRAG_HANDLES_"); break;
1111 case B_SET_PROPERTY
: strcpy(str
, "B_SET_PROPERTY"); break;
1112 case B_GET_PROPERTY
: strcpy(str
, "B_GET_PROPERTY"); break;
1113 case B_CREATE_PROPERTY
: strcpy(str
, "B_CREATE_PROPERTY"); break;
1114 case B_DELETE_PROPERTY
: strcpy(str
, "B_DELETE_PROPERTY"); break;
1115 case B_COUNT_PROPERTIES
: strcpy(str
, "B_COUNT_PROPERTIES"); break;
1116 case B_EXECUTE_PROPERTY
: strcpy(str
, "B_EXECUTE_PROPERTY"); break;
1117 case B_GET_SUPPORTED_SUITES
: strcpy(str
, "B_GET_SUPPORTED_SUITES"); break;
1118 case B_CUT
: strcpy(str
, "B_CUT"); break;
1119 case B_COPY
: strcpy(str
, "B_COPY"); break;
1120 case B_PASTE
: strcpy(str
, "B_PASTE"); break;
1121 case B_SELECT_ALL
: strcpy(str
, "B_SELECT_ALL"); break;
1122 case B_SAVE_REQUESTED
: strcpy(str
, "B_SAVE_REQUESTED"); break;
1123 case B_MESSAGE_NOT_UNDERSTOOD
: strcpy(str
, "B_MESSAGE_NOT_UNDERSTOOD"); break;
1124 case B_NO_REPLY
: strcpy(str
, "B_NO_REPLY"); break;
1125 case B_REPLY
: strcpy(str
, "B_REPLY"); break;
1126 case B_SIMPLE_DATA
: strcpy(str
, "B_SIMPLE_DATA"); break;
1127 //case B_MIME_DATA : strcpy(str, "B_MIME_DATA"); break;
1128 case B_ARCHIVED_OBJECT
: strcpy(str
, "B_ARCHIVED_OBJECT"); break;
1129 case B_UPDATE_STATUS_BAR
: strcpy(str
, "B_UPDATE_STATUS_BAR"); break;
1130 case B_RESET_STATUS_BAR
: strcpy(str
, "B_RESET_STATUS_BAR"); break;
1131 case B_NODE_MONITOR
: strcpy(str
, "B_NODE_MONITOR"); break;
1132 case B_QUERY_UPDATE
: strcpy(str
, "B_QUERY_UPDATE"); break;
1133 case B_BAD_SCRIPT_SYNTAX
: strcpy(str
, "B_BAD_SCRIPT_SYNTAX"); break;
1136 case B_NO_SPECIFIER
: strcpy(str
, "B_NO_SPECIFIER"); break;
1137 case B_DIRECT_SPECIFIER
: strcpy(str
, "B_DIRECT_SPECIFIER"); break;
1138 case B_INDEX_SPECIFIER
: strcpy(str
, "B_INDEX_SPECIFIER"); break;
1139 case B_REVERSE_INDEX_SPECIFIER
: strcpy(str
, "B_REVERSE_INDEX_SPECIFIER"); break;
1140 case B_RANGE_SPECIFIER
: strcpy(str
, "B_RANGE_SPECIFIER"); break;
1141 case B_REVERSE_RANGE_SPECIFIER
: strcpy(str
, "B_REVERSE_RANGE_SPECIFIER"); break;
1142 case B_NAME_SPECIFIER
: strcpy(str
, "B_NAME_SPECIFIER"); break;
1144 case B_ERROR
: strcpy(str
, "B_ERROR"); break;
1147 id_to_string(type
, str
);
1155 format_data(int32 type
, char *ptr
, long size
)
1172 BMessage anothermsg
;
1187 str
= new char[size
+ 4];
1189 strncpy(str
+ 1, ptr
, size
);
1193 case B_POINTER_TYPE
:
1195 sprintf(str
, "%p", *(void**)ptr
);
1199 str
= new char[1024];
1200 anothermsg
.AddData("myref", B_REF_TYPE
, ptr
, size
);
1201 anothermsg
.FindRef("myref", &aref
);
1202 if (entry
.SetTo(&aref
)==B_OK
){
1203 entry
.GetPath(&path
);
1204 strcpy(str
, path
.Path());
1206 strcpy(str
, "invalid entry_ref");
1209 case B_SSIZE_T_TYPE
:
1213 sprintf(str
, "%" B_PRId64
" (0x%" B_PRIx64
")", i64
, i64
);
1220 sprintf(str
, "%" B_PRId32
" (0x%08" B_PRId32
")", i32
, i32
);
1226 sprintf(str
, "%d (0x%04X)", i16
, i16
);
1233 sprintf(str
, "%d (0x%02X)", i8
, i8
);
1238 ui64
= *(uint64
*)ptr
;
1239 sprintf(str
, "%" B_PRIu64
" (0x%" B_PRIx64
")", ui64
, ui64
);
1244 ui32
= *(uint32
*)ptr
;
1245 sprintf(str
, "%" B_PRIu32
" (0x%08" B_PRIx32
")", ui32
, ui32
);
1250 ui16
= *(uint16
*)ptr
;
1251 sprintf(str
, "%u (0x%04X)", ui16
, ui16
);
1257 sprintf(str
, "%u (0x%02X)", ui8
, ui8
);
1263 strcpy(str
, "TRUE");
1265 strcpy(str
, "FALSE");
1271 sprintf(str
, "%.3f", *fptr
);
1276 dptr
= (double*)ptr
;
1277 sprintf(str
, "%.3f", *dptr
);
1281 str
= new char[200];
1283 sprintf(str
, "BRect(%.1f, %.1f, %.1f, %.1f)", fptr
[0], fptr
[1],
1288 str
= new char[200];
1290 sprintf(str
, "BPoint(%.1f, %.1f)", fptr
[0], fptr
[1]);
1293 case B_RGB_COLOR_TYPE
:
1295 sprintf(str
, "Red=%u Green=%u Blue=%u Alpha=%u",
1296 ((uint8
*)ptr
)[0], ((uint8
*)ptr
)[1], ((uint8
*)ptr
)[2],
1300 case B_COLOR_8_BIT_TYPE
:
1301 str
= new char[size
* 6 + 4];
1303 for (int32 i
= 0; i
< min_c(256, size
); i
++) {
1304 sprintf(idtext
, "%u ", ((unsigned char*)ptr
)[i
]);
1307 *(str
+strlen(str
)-2) = 0;
1310 case B_MESSAGE_TYPE
:
1312 if (anothermsg
.Unflatten((const char *)ptr
) == B_OK
) {
1313 char *whatString
= get_datatype_string(anothermsg
.what
);
1314 sprintf(str
, "what=%s", whatString
);
1315 delete[] whatString
;
1317 strcpy(str
, "error when unflattening");
1320 case B_PROPERTY_INFO_TYPE
:
1322 BPropertyInfo propinfo
;
1323 if (propinfo
.Unflatten(B_PROPERTY_INFO_TYPE
, (const void *)ptr
,
1325 str
= new char[size
* 32]; // an approximation
1327 const property_info
*pinfo
= propinfo
.Properties();
1329 sprintf(str
, "\n property commands "
1330 "specifiers types\n-----------------------------------"
1331 "----------------------------------------------------------------\n");
1332 for (int32 pinfo_index
= 0; pinfo_index
< propinfo
.CountProperties(); pinfo_index
++) {
1334 + (strlen(pinfo
[pinfo_index
].name
) < 16 ?
1335 strlen(pinfo
[pinfo_index
].name
) : 16));
1336 strcat(str
, pinfo
[pinfo_index
].name
);
1338 char *start
= str
+ strlen(str
);
1340 for (int32 i
= 0; i
< 10 && pinfo
[pinfo_index
].commands
[i
];
1342 tempstr
= get_datatype_string(
1343 pinfo
[pinfo_index
].commands
[i
]);
1344 strcat(str
, tempstr
);
1349 // pad the rest with spaces
1350 if (strlen(start
) < 36) {
1356 for (int32 i
= 0; i
< 10 && pinfo
[pinfo_index
].specifiers
[i
]; i
++) {
1357 switch (pinfo
[pinfo_index
].specifiers
[i
]) {
1358 case B_NO_SPECIFIER
:
1359 strcat(str
, "NONE ");
1361 case B_DIRECT_SPECIFIER
:
1362 strcat(str
, "DIRECT ");
1364 case B_INDEX_SPECIFIER
:
1365 strcat(str
, "INDEX ");
1367 case B_REVERSE_INDEX_SPECIFIER
:
1368 strcat(str
, "REV.INDEX ");
1370 case B_RANGE_SPECIFIER
:
1371 strcat(str
, "RANGE ");
1373 case B_REVERSE_RANGE_SPECIFIER
:
1374 strcat(str
, "REV.RANGE ");
1376 case B_NAME_SPECIFIER
:
1377 strcat(str
, "NAME ");
1379 case B_ID_SPECIFIER
:
1383 strcat(str
, "<NONE> ");
1388 // pad the rest with spaces
1389 if (strlen(start
) < 60) {
1391 " " + strlen(start
));
1394 for (int32 i
= 0; i
< 10
1395 && pinfo
[pinfo_index
].types
[i
] != 0; i
++) {
1396 uint32 type
= pinfo
[pinfo_index
].types
[i
];
1398 snprintf(str2
, sizeof(str2
), "%c%c%c%c ",
1399 int(type
& 0xFF000000) >> 24,
1400 int(type
& 0xFF0000) >> 16,
1401 int(type
& 0xFF00) >> 8,
1406 for (int32 i
= 0; i
< 3; i
++) {
1407 for (int32 j
= 0; j
< 5
1408 && pinfo
[pinfo_index
].ctypes
[i
].pairs
[j
].type
1410 uint32 type
= pinfo
[pinfo_index
].ctypes
[i
].pairs
[j
].type
;
1411 char str2
[strlen(pinfo
[pinfo_index
].ctypes
[i
].pairs
[j
].name
) + 8];
1412 snprintf(str2
, sizeof(str2
),
1414 pinfo
[pinfo_index
].ctypes
[i
].pairs
[j
].name
,
1415 int(type
& 0xFF000000) >> 24,
1416 int(type
& 0xFF0000) >> 16,
1417 int(type
& 0xFF00) >> 8,
1424 // is there usage info?
1425 if (pinfo
[pinfo_index
].usage
) {
1426 strcat(str
, " Usage: ");
1427 strcat(str
, pinfo
[pinfo_index
].usage
);
1433 // handle value infos....
1434 const value_info
*vinfo
= propinfo
.Values();
1435 int32 vinfo_count
= propinfo
.CountValues();
1436 #if TEST_VALUEINFO>0
1437 value_info vinfo
[10] = {
1438 {"Backup", 'back', B_COMMAND_KIND
,
1439 "This command backs up your hard drive."},
1440 {"Abort", 'abor', B_COMMAND_KIND
,
1441 "Stops the current operation..."},
1442 {"Type Code", 'type', B_TYPE_CODE_KIND
,
1443 "Type code info..."}
1448 if (vinfo
&& vinfo_count
> 0) {
1449 sprintf(str
+ strlen(str
),
1451 " kind\n---------------------------------------------"
1452 "-----------------------------------\n");
1454 for (int32 vinfo_index
= 0; vinfo_index
< vinfo_count
;
1456 char *start
= str
+ strlen(str
);
1457 strcat(str
, " " + (strlen(vinfo
[vinfo_index
].name
) < 16 ? strlen(vinfo
[vinfo_index
].name
) : 16));
1458 strcat(str
, vinfo
[vinfo_index
].name
);
1461 sprintf(str
+ strlen(str
), "0x%8" B_PRIx32
" (",
1462 vinfo
[vinfo_index
].value
);
1463 id_to_string(vinfo
[vinfo_index
].value
, str
+ strlen(str
));
1466 // pad the rest with spaces
1467 if (strlen(start
) < 36 + 19) {
1469 " " + strlen(start
));
1473 switch (vinfo
[vinfo_index
].kind
) {
1474 case B_COMMAND_KIND
:
1475 strcat(str
, "COMMAND ");
1478 case B_TYPE_CODE_KIND
:
1479 strcat(str
, "TYPE CODE ");
1483 strcat(str
, "unknown ");
1489 // is there usage info?
1490 if (vinfo
[vinfo_index
].usage
) {
1491 strcat(str
, " Usage: ");
1492 strcat(str
, vinfo
[vinfo_index
].usage
);
1499 strcpy(str
, "error when unflattening");
1505 str
= new char[min_c(256, size
) * 20 + 4];
1507 for (int32 i
= 0; i
< min_c(256, size
); i
++) {
1508 sprintf(idtext
, "0x%02X, ", (uint16
)ptr
[i
]);
1509 strcat(str
, idtext
);
1511 *(str
+ strlen(str
) - 2) = 0;
1520 id_to_string(long ID
, char *here
)
1522 uint8 digit0
= (ID
>>24)& 255;
1523 uint8 digit1
= (ID
>>16)& 255;
1524 uint8 digit2
= (ID
>>8) & 255;
1525 uint8 digit3
= (ID
) & 255;
1526 bool itsvalid
= false;
1532 itsvalid
= is_valid_char(digit3
);
1533 sprintf(here
, "'%c'", digit3
);
1536 itsvalid
= is_valid_char(digit2
) && is_valid_char(digit3
);
1537 sprintf(here
, "'%c%c'", digit2
, digit3
);
1541 itsvalid
= is_valid_char(digit1
) && is_valid_char(digit2
)
1542 && is_valid_char(digit3
);
1543 sprintf(here
, "'%c%c%c'", digit1
, digit2
, digit3
);
1547 itsvalid
= is_valid_char(digit0
) && is_valid_char(digit1
)
1548 && is_valid_char(digit2
) && is_valid_char(digit3
);
1549 sprintf(here
, "'%c%c%c%c'", digit0
, digit1
, digit2
, digit3
);
1553 sprintf(here
, "%ldL", ID
);
1560 is_valid_char(uint8 c
)
1562 return c
>= 32 && c
< 128;