/* * Get the Unicode character code of the first character of a string */ void CVmBifT3Test::get_charcode(VMG_ uint argc) { const char *str; /* one argument required */ check_argc(vmg_ argc, 1); /* get the object ID as an integer */ str = pop_str_val(vmg0_); /* * if the string is empty, return nil; otherwise, return the Unicode * character code of the first character */ if (vmb_get_len(str) == 0) { /* empty string - return nil */ retval_nil(vmg0_); } else { /* * get the character code of the first character and return it * as an integer */ retval_int(vmg_ (int)utf8_ptr::s_getch(str + VMB_LEN)); } }
/* * displayText(str) - display a text string. */ void CVmBifSample::display_text(VMG_ uint argc) { const char *strp; size_t len; /* * Check to make sure we have the right number of arguments. 'argc' * tells us how many arguments we received from the T3 program. */ check_argc(vmg_ argc, 1); /* * Get the first argument, which is the string to display. * * This will give us a pointer to a string in internal format, which * has a two-byte length prefix. So, once we have the string, we must * get the length from the string pointer, and then skip the length * prefix to get to the real text of the string. * * Arguments from the T3 program to a native function always appear on * the VM stack, which we can access using the pop_xxx_val() functions. * The arguments appear on the stack in order such that the first * pop_xxx_val() gives us the first argument, the second pop_xxx_val() * gives us the second argument, and so on. The pop_xxx_val() * functions REMOVE an argument from the stack - once it's removed, we * can get to the next one. We MUST remove EXACTLY the number of * arguments that we receive before we return. */ strp = pop_str_val(vmg0_); len = vmb_get_len(strp); strp += VMB_LEN; /* * Okay, we have our string, but it's in UTF-8 format, which is an * encoding format for Unicode. We don't want to display Unicode; we * want to display the local character set. How do we do this? * Fortunately, T3 provides a handy character mapping subsystem that * will let us convert the string fairly automatically. The VM also * gives us a pre-loaded mapper for this specific kind of conversion, * in the object G_cmap_to_ui. G_cmap_to_ui will map characters from * UTF-8 to the local User Interface character set. * * To avoid the need to allocate a gigantic string buffer to convert * the characters, the mapper lets us map in chunks of any size. So, * we'll simply map and display chunks until we run out of string. */ while (len != 0) { char buf[128]; size_t cur_out; size_t cur_in; /* * Map as much as we can into our buffer. This will set cur_out to * the number of bytes in the local character set (the output of * the conversion), and will set cur_in to the number of bytes we * used from the Unicode string (the input). */ cur_out = G_cmap_to_ui->map_utf8(buf, sizeof(buf), strp, len, &cur_in); /* * Show the local characters. * * "%.*s" is just like "%s", but the ".*" tells printf to show * exactly the number of characters in the int argument before the * string, instead of showing everything until it finds a null byte * in the string. This is important because map_utf8 does NOT * null-terminate the result. */ printf("%.*s", (int)cur_out, buf); /* * skip the characters of input we just translated, so that on the * next iteration of this loop we'll translate the next bunch of * characters */ strp += cur_in; len -= cur_in; } }