Beispiel #1
0
void DisplayMenuToClient (edict_t *ent, MenuText *menu)
{
   if (!IsValidPlayer (ent))
      return;

   int clientIndex = ENTINDEX (ent) - 1;

   if (menu != null)
   {
      String tempText = String (menu->menuText);
      tempText.Replace ("\v", "\n");

      char *text = g_localizer->TranslateInput (tempText);
      tempText = String (text);

      // make menu looks best
      for (int i = 0; i <= 9; i++)
         tempText.Replace (FormatBuffer ("%d.", i), FormatBuffer ("\\r%d.\\w", i));

      text = tempText;

      while (strlen (text) >= 64)
      {
         MESSAGE_BEGIN (MSG_ONE_UNRELIABLE, g_netMsg->GetId (NETMSG_SHOWMENU), null, ent);
            WRITE_SHORT (menu->validSlots);
            WRITE_CHAR (-1);
            WRITE_BYTE (1);

         for (int i = 0; i <= 63; i++)
            WRITE_CHAR (text[i]);

         MESSAGE_END ();

         text += 64;
      }

      MESSAGE_BEGIN (MSG_ONE_UNRELIABLE, g_netMsg->GetId (NETMSG_SHOWMENU), null, ent);
         WRITE_SHORT (menu->validSlots);
         WRITE_CHAR (-1);
         WRITE_BYTE (0);
         WRITE_STRING (text);
      MESSAGE_END();

      g_clients[clientIndex].menu = menu;
   }
   else
   {
      MESSAGE_BEGIN (MSG_ONE_UNRELIABLE, g_netMsg->GetId (NETMSG_SHOWMENU), null, ent);
         WRITE_SHORT (0);
         WRITE_CHAR (0);
         WRITE_BYTE (0);
         WRITE_STRING ("");
      MESSAGE_END();

     g_clients[clientIndex].menu = null;
   }
   CLIENT_COMMAND (ent, "speak \"player/geiger1\"\n"); // Stops others from hearing menu sounds..
}
Beispiel #2
0
static void bar_pane_exif_entry_write_config(GtkWidget *entry, GString *outstr, gint indent)
{
	ExifEntry *ee = g_object_get_data(G_OBJECT(entry), "entry_data");
	if (!ee) return;

	WRITE_NL(); WRITE_STRING("<entry ");
	WRITE_CHAR(*ee, key);
	if (!ee->auto_title) WRITE_CHAR(*ee, title);
	WRITE_BOOL(*ee, if_set);
	WRITE_BOOL(*ee, editable);
	WRITE_STRING("/>");
}
Beispiel #3
0
/* warning - don't pass here const string */
void UTIL_ShowMenu(edict_t* pEdict, int slots, int time, char *menu, int mlen)
{
	char *n = menu;
	char c = 0;
	int a;

	if (!gmsgShowMenu)
		return;			// some games don't support ShowMenu (Firearms)

	do
	{
		a = mlen;
		if (a > 175) a = 175;
		mlen -= a;
		c = *(n+=a);
		*n = 0;
		
		MESSAGE_BEGIN(MSG_ONE, gmsgShowMenu, NULL, pEdict);
		WRITE_SHORT(slots);
		WRITE_CHAR(time);
		WRITE_BYTE(c ? TRUE : FALSE);
		WRITE_STRING(menu);
		MESSAGE_END();
		*n = c;
		menu = n;
	}
	while (*n);
}
Beispiel #4
0
static void write_color_profile(GString *outstr, gint indent)
{
	gint i;
#ifndef HAVE_LCMS
	g_string_append_printf(outstr, "<!-- NOTICE: %s was not built with support for color profiles,\n"
			    "         color profile options will have no effect.\n-->\n", GQ_APPNAME);
#endif

	WRITE_NL(); WRITE_STRING("<color_profiles ");
	WRITE_CHAR(options->color_profile, screen_file);
	WRITE_BOOL(options->color_profile, enabled);
	WRITE_BOOL(options->color_profile, use_image);
	WRITE_INT(options->color_profile, input_type);
	WRITE_BOOL(options->color_profile, use_x11_screen_profile);
	WRITE_INT(options->color_profile, render_intent);
	WRITE_STRING(">");

	indent++;
	for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
		{
		WRITE_NL(); WRITE_STRING("<profile ");
		write_char_option(outstr, indent, "input_file", options->color_profile.input_file[i]);
		write_char_option(outstr, indent, "input_name", options->color_profile.input_name[i]);
		WRITE_STRING("/>");
		}
	indent--;
	WRITE_NL(); WRITE_STRING("</color_profiles>");
}
*/	static void Write_Char(char c, int n)
/*
**		Write out repeated number of chars.
**		Unicode: not used
**
***********************************************************************/
{
	char buf[4];

	buf[0] = c;
	for (; n > 0; n--) WRITE_CHAR(buf);
}
Beispiel #6
0
static void bar_pane_keywords_write_config(GtkWidget *pane, GString *outstr, gint indent)
{
	PaneKeywordsData *pkd;

	pkd = g_object_get_data(G_OBJECT(pane), "pane_data");
	if (!pkd) return;

	WRITE_NL(); WRITE_STRING("<pane_keywords ");
	write_char_option(outstr, indent, "id", pkd->pane.id);
	write_char_option(outstr, indent, "title", gtk_label_get_text(GTK_LABEL(pkd->pane.title)));
	WRITE_BOOL(pkd->pane, expanded);
	WRITE_CHAR(*pkd, key);
	WRITE_STRING("/>");
}
Beispiel #7
0
static void bar_pane_comment_write_config(GtkWidget *pane, GString *outstr, gint indent)
{
	PaneCommentData *pcd;

	pcd = g_object_get_data(G_OBJECT(pane), "pane_data");
	if (!pcd) return;

	WRITE_NL(); WRITE_STRING("<pane_comment ");
	write_char_option(outstr, indent, "id", pcd->pane.id);
	write_char_option(outstr, indent, "title", gtk_label_get_text(GTK_LABEL(pcd->pane.title)));
	WRITE_BOOL(pcd->pane, expanded);
	WRITE_CHAR(*pcd, key);
	WRITE_INT(*pcd, height);
	WRITE_STRING("/>");
}
*/	static void Move_Cursor(STD_TERM *term, int count)
/*
**		Move cursor right or left by one char.
**		Unicode: not yet supported!
**
***********************************************************************/
{
	if (count < 0) {
		if (term->pos > 0) {
			term->pos--;
			Write_Char(BS, 1);
		}
	}
	else {
		if (term->pos < term->end) {
			WRITE_CHAR(term->buffer + term->pos);
			term->pos++;
		}
	}
}
*/	static char *Insert_Char(STD_TERM *term, char *cp)
/*
**		Insert a char at the current position. Adjust end position.
**		Redisplay the line.
**		Unicode: not yet supported!
**
***********************************************************************/
{
	//printf("\r\nins pos: %d end: %d ==", term->pos, term->end);
	if (term->end < TERM_BUF_LEN-1) { // avoid buffer overrun

		if (term->pos < term->end) { // open space for it:
			memmove(term->buffer + term->pos + 1, term->buffer + term->pos, 1 + term->end - term->pos);
		}
		WRITE_CHAR(cp);
		term->buffer[term->pos] = *cp;
		term->end++;
		term->pos++;
		Show_Line(term, 0);
	}

	return ++cp;
}
Beispiel #10
0
void Message::Send()
{
	msgparam *pParam = NULL;

	for (size_t i=1; i<=m_CurParam; i++)
	{
		pParam = m_Params[i];
		switch (pParam->type)
		{
		case arg_byte:
			WRITE_BYTE(pParam->v.iData);
			break;
		case arg_char:
			WRITE_CHAR(pParam->v.iData);
			break;
		case arg_short:
			WRITE_SHORT(pParam->v.iData);
			break;
		case arg_long:
			WRITE_LONG(pParam->v.iData);
			break;
		case arg_angle:
			WRITE_ANGLE(pParam->v.fData);
			break;
		case arg_coord:
			WRITE_COORD(pParam->v.fData);
			break;
		case arg_string:
			WRITE_STRING(pParam->szData.chars());
			break;
		case arg_entity:
			WRITE_ENTITY(pParam->v.iData);
			break;
		}
	}
}
Beispiel #11
0
void UTIL_ShowMenu(edict_t* pEdict, int keybits, int time, char *menu, int mlen)
{
	char *n = menu;
	char c = 0;
	int a;

	do {
		a = mlen;
		if (a > 175) a = 175;
		mlen -= a;
		c = *(n+=a);
		*n = 0;

		MESSAGE_BEGIN(MSG_ONE, gmsgShowMenu, NULL, pEdict);
			WRITE_SHORT(keybits);
			WRITE_CHAR(time);
			WRITE_BYTE(c ? TRUE : FALSE);
			WRITE_STRING(menu);
		MESSAGE_END();
		*n = c;
		menu = n;
	}
	while (*n);
}
Beispiel #12
0
static void write_global_attributes(GString *outstr, gint indent)
{
	/* General Options */
	WRITE_NL(); WRITE_BOOL(*options, show_icon_names);
	WRITE_SEPARATOR();

	WRITE_NL(); WRITE_BOOL(*options, tree_descend_subdirs);
	WRITE_NL(); WRITE_BOOL(*options, view_dir_list_single_click_enter);
	WRITE_NL(); WRITE_BOOL(*options, lazy_image_sync);
	WRITE_NL(); WRITE_BOOL(*options, update_on_time_change);
	WRITE_SEPARATOR();

	WRITE_NL(); WRITE_BOOL(*options, progressive_key_scrolling);
	WRITE_NL(); WRITE_UINT(*options, keyboard_scroll_step);

	WRITE_NL(); WRITE_UINT(*options, duplicates_similarity_threshold);
	WRITE_NL(); WRITE_UINT(*options, duplicates_match);
	WRITE_NL(); WRITE_UINT(*options, duplicates_select_type);
	WRITE_NL(); WRITE_BOOL(*options, duplicates_thumbnails);
	WRITE_NL(); WRITE_BOOL(*options, rot_invariant_sim);
	WRITE_SEPARATOR();

	WRITE_NL(); WRITE_BOOL(*options, mousewheel_scrolls);
	WRITE_NL(); WRITE_BOOL(*options, image_lm_click_nav);
	WRITE_NL(); WRITE_INT(*options, open_recent_list_maxsize);
	WRITE_NL(); WRITE_INT(*options, dnd_icon_size);
	WRITE_NL(); WRITE_BOOL(*options, place_dialogs_under_mouse);

	WRITE_NL(); WRITE_BOOL(*options, save_window_positions);
	WRITE_NL(); WRITE_BOOL(*options, use_saved_window_positions_for_new_windows);
	WRITE_NL(); WRITE_BOOL(*options, tools_restore_state);

	/* File operations Options */
	WRITE_NL(); WRITE_BOOL(*options, file_ops.enable_in_place_rename);
	WRITE_NL(); WRITE_BOOL(*options, file_ops.confirm_delete);
	WRITE_NL(); WRITE_BOOL(*options, file_ops.enable_delete_key);
	WRITE_NL(); WRITE_BOOL(*options, file_ops.safe_delete_enable);
	WRITE_NL(); WRITE_CHAR(*options, file_ops.safe_delete_path);
	WRITE_NL(); WRITE_INT(*options, file_ops.safe_delete_folder_maxsize);

	/* Properties dialog Options */
	WRITE_NL(); WRITE_CHAR(*options, properties.tabs_order);

	/* Image Options */
	WRITE_NL(); WRITE_UINT(*options, image.zoom_mode);

	WRITE_SEPARATOR();
	WRITE_NL(); WRITE_BOOL(*options, image.zoom_2pass);
	WRITE_NL(); WRITE_BOOL(*options, image.zoom_to_fit_allow_expand);
	WRITE_NL(); WRITE_UINT(*options, image.zoom_quality);
	WRITE_NL(); WRITE_INT(*options, image.zoom_increment);
	WRITE_NL(); WRITE_BOOL(*options, image.fit_window_to_image);
	WRITE_NL(); WRITE_BOOL(*options, image.limit_window_size);
	WRITE_NL(); WRITE_INT(*options, image.max_window_size);
	WRITE_NL(); WRITE_BOOL(*options, image.limit_autofit_size);
	WRITE_NL(); WRITE_INT(*options, image.max_autofit_size);
	WRITE_NL(); WRITE_UINT(*options, image.scroll_reset_method);
	WRITE_NL(); WRITE_INT(*options, image.tile_cache_max);
	WRITE_NL(); WRITE_INT(*options, image.image_cache_max);
	WRITE_NL(); WRITE_BOOL(*options, image.enable_read_ahead);
	WRITE_NL(); WRITE_BOOL(*options, image.exif_rotate_enable);
	WRITE_NL(); WRITE_BOOL(*options, image.use_custom_border_color);
	WRITE_NL(); WRITE_BOOL(*options, image.use_custom_border_color_in_fullscreen);
	WRITE_NL(); WRITE_COLOR(*options, image.border_color);
	WRITE_NL(); WRITE_BOOL(*options, image.use_clutter_renderer);

	/* Thumbnails Options */
	WRITE_NL(); WRITE_INT(*options, thumbnails.max_width);
	WRITE_NL(); WRITE_INT(*options, thumbnails.max_height);
	WRITE_NL(); WRITE_BOOL(*options, thumbnails.enable_caching);
	WRITE_NL(); WRITE_BOOL(*options, thumbnails.cache_into_dirs);
	WRITE_NL(); WRITE_BOOL(*options, thumbnails.use_xvpics);
	WRITE_NL(); WRITE_BOOL(*options, thumbnails.spec_standard);
	WRITE_NL(); WRITE_UINT(*options, thumbnails.quality);
	WRITE_NL(); WRITE_BOOL(*options, thumbnails.use_exif);

	/* File sorting Options */
	WRITE_NL(); WRITE_INT(*options, file_sort.method);
	WRITE_NL(); WRITE_BOOL(*options, file_sort.ascending);
	WRITE_NL(); WRITE_BOOL(*options, file_sort.case_sensitive);
	WRITE_NL(); WRITE_BOOL(*options, file_sort.natural);

	/* Fullscreen Options */
	WRITE_NL(); WRITE_INT(*options, fullscreen.screen);
	WRITE_NL(); WRITE_BOOL(*options, fullscreen.clean_flip);
	WRITE_NL(); WRITE_BOOL(*options, fullscreen.disable_saver);
	WRITE_NL(); WRITE_BOOL(*options, fullscreen.above);

	WRITE_SEPARATOR();

	/* Image Overlay Options */
	WRITE_NL(); WRITE_CHAR(*options, image_overlay.template_string);

	WRITE_NL(); WRITE_INT(*options, image_overlay.x);
	WRITE_NL(); WRITE_INT(*options, image_overlay.y);
	WRITE_NL(); WRITE_INT(*options, image_overlay.text_red);
	WRITE_NL(); WRITE_INT(*options, image_overlay.text_green);
	WRITE_NL(); WRITE_INT(*options, image_overlay.text_blue);
	WRITE_NL(); WRITE_INT(*options, image_overlay.text_alpha);
	WRITE_NL(); WRITE_INT(*options, image_overlay.background_red);
	WRITE_NL(); WRITE_INT(*options, image_overlay.background_green);
	WRITE_NL(); WRITE_INT(*options, image_overlay.background_blue);
	WRITE_NL(); WRITE_INT(*options, image_overlay.background_alpha);
	WRITE_NL(); WRITE_CHAR(*options, image_overlay.font);

	/* Slideshow Options */
	WRITE_NL(); WRITE_INT_UNIT(*options, slideshow.delay, SLIDESHOW_SUBSECOND_PRECISION);
	WRITE_NL(); WRITE_BOOL(*options, slideshow.random);
	WRITE_NL(); WRITE_BOOL(*options, slideshow.repeat);

	/* Collection Options */
	WRITE_NL(); WRITE_BOOL(*options, collections.rectangular_selection);

	/* Filtering Options */
	WRITE_NL(); WRITE_BOOL(*options, file_filter.show_hidden_files);
	WRITE_NL(); WRITE_BOOL(*options, file_filter.show_parent_directory);
	WRITE_NL(); WRITE_BOOL(*options, file_filter.show_dot_directory);
	WRITE_NL(); WRITE_BOOL(*options, file_filter.disable_file_extension_checks);
	WRITE_NL(); WRITE_BOOL(*options, file_filter.disable);
	WRITE_SEPARATOR();

	/* Sidecars Options */
	WRITE_NL(); WRITE_CHAR(*options, sidecar.ext);

	/* Shell command */
	WRITE_NL(); WRITE_CHAR(*options, shell.path);
	WRITE_NL(); WRITE_CHAR(*options, shell.options);

	/* Helpers */
	WRITE_NL(); WRITE_CHAR(*options, helpers.html_browser.command_name);
	WRITE_NL(); WRITE_CHAR(*options, helpers.html_browser.command_line);

	/* Metadata Options */
	WRITE_NL(); WRITE_BOOL(*options, metadata.enable_metadata_dirs);
	WRITE_NL(); WRITE_BOOL(*options, metadata.save_in_image_file);
	WRITE_NL(); WRITE_BOOL(*options, metadata.save_legacy_IPTC);
	WRITE_NL(); WRITE_BOOL(*options, metadata.warn_on_write_problems);
	WRITE_NL(); WRITE_BOOL(*options, metadata.save_legacy_format);
	WRITE_NL(); WRITE_BOOL(*options, metadata.sync_grouped_files);
	WRITE_NL(); WRITE_BOOL(*options, metadata.confirm_write);
	WRITE_NL(); WRITE_INT(*options, metadata.confirm_timeout);
	WRITE_NL(); WRITE_BOOL(*options, metadata.confirm_after_timeout);
	WRITE_NL(); WRITE_BOOL(*options, metadata.confirm_on_image_change);
	WRITE_NL(); WRITE_BOOL(*options, metadata.confirm_on_dir_change);
	WRITE_NL(); WRITE_BOOL(*options, metadata.keywords_case_sensitive);
	WRITE_NL(); WRITE_BOOL(*options, metadata.write_orientation);

	WRITE_NL(); WRITE_INT(*options, stereo.mode);
	WRITE_NL(); WRITE_INT(*options, stereo.fsmode);
	WRITE_NL(); WRITE_BOOL(*options, stereo.enable_fsmode);
	WRITE_NL(); WRITE_INT(*options, stereo.fixed_w);
	WRITE_NL(); WRITE_INT(*options, stereo.fixed_h);
	WRITE_NL(); WRITE_INT(*options, stereo.fixed_x1);
	WRITE_NL(); WRITE_INT(*options, stereo.fixed_y1);
	WRITE_NL(); WRITE_INT(*options, stereo.fixed_x2);
	WRITE_NL(); WRITE_INT(*options, stereo.fixed_y2);
}
Beispiel #13
0
void RadioShowMenu( edict_t *pEntity, edict_t *pRadio, int n )
{
	// Cant use radio in spec mode
	if (pEntity->v.iuser1 > 0) return;
	// dont use if radio is tuning
	if (pRadio->v.iuser1 == 1) return;

	char menutext[1024];
	int bitsel = 0;

	if (n < 3)
	{

		sprintf(menutext, "Switch to song:\n\n");

		if (n == 1)
		{

			strcat(menutext, "1. Take my Breath Away\n");
			strcat(menutext, "2. Dreamgate - Now we are free\n");
			strcat(menutext, "3. Hamsterdance\n");
			strcat(menutext, "4. Muse - Plug In Baby\n");
			strcat(menutext, "5. Scooter - Ramp [Supertramp - Logical Song]\n\n");
			
			strcat(menutext, "6. Show Page 2\n\n");
			
		}
		else
		{

			strcat(menutext, "1. Boomtang Boys - Popcorn [Micro Mix]\n");
			strcat(menutext, "2. Mr. Roboto\n");
			strcat(menutext, "3. Chicane - Salt Water\n");
			strcat(menutext, "4. John Jeski - Sailing Accordion Polka\n");
			strcat(menutext, "5. Warrior - Voodoo\n\n");
			
			strcat(menutext, "6. Show Page 1\n\n");
		}
	
		strcat(menutext, "7. Switch to next song\n");
		strcat(menutext, "8. Switch to previous song\n\n");
		strcat(menutext, "9. Show pitch menu\n");
	
	}
	else
	{

		sprintf(menutext, "Change the pitch and speed:\n\n");

		strcat(menutext, "1. Change to normal pitch\n\n");
		
		strcat(menutext, "2. 0.5x speed/pitch\n");
		strcat(menutext, "3. 0.8x speed/pitch\n");
		strcat(menutext, "4. 1.2x speed/pitch\n");
		strcat(menutext, "5. 1.4x speed/pitch\n");
		strcat(menutext, "6. 1.5x speed/pitch\n");
		strcat(menutext, "7. 1.8x speed/pitch\n");
		strcat(menutext, "8. 2.0x speed/pitch\n\n");
		
		strcat(menutext, "9. Back to song menu\n");


	}


	strcat(menutext, "\n\n0. Cancel\n");
	
	bitsel |= 1<<0; // activate this choice in the menu 1
	bitsel |= 1<<1; // activate this choice in the menu 2
	bitsel |= 1<<2; // activate this choice in the menu 3
	bitsel |= 1<<3; // activate this choice in the menu 4
	bitsel |= 1<<4; // activate this choice in the menu 5
	bitsel |= 1<<5; // activate this choice in the menu 6
	bitsel |= 1<<6; // activate this choice in the menu 7
	bitsel |= 1<<7; // activate this choice in the menu 8
	bitsel |= 1<<8; // activate this choice in the menu 9
	bitsel |= 1<<9; // activate this choice in the menu 9

	// Now, show the menu to everyone!


	int gmsgShowMenu = 0;
	gmsgShowMenu = REG_USER_MSG( "ShowMenu", -1 ); 
	
	int char_count = 0;
	char *pFileList = menutext;
	char *aFileList = menutext;

	while ( pFileList && *pFileList && char_count < 1024 )
	{
		char chunk[MAX_MENU_CHUNK+1];
		
		if ( strlen( pFileList ) < MAX_MENU_CHUNK )
		{
			strcpy( chunk, pFileList );
		}
		else
		{
			strncpy( chunk, pFileList, MAX_MENU_CHUNK );
			chunk[MAX_MENU_CHUNK] = 0;		// strncpy doesn't always append the null terminator
		}

		char_count += strlen( chunk );
		
		if ( char_count < 1024 )
			pFileList = aFileList + char_count; 
		else
			*pFileList = 0;

		ALERT(at_console, "SENDING %i!!!\n", char_count);

		MESSAGE_BEGIN( MSG_ONE, gmsgShowMenu, NULL, pEntity );
			WRITE_SHORT( bitsel );
			WRITE_CHAR( 60 );
			WRITE_BYTE( *pFileList ? TRUE : FALSE );	// TRUE means there is still more message to come
			WRITE_STRING( chunk );
		MESSAGE_END();
	}


	lastMenuPage[ENTINDEX(pEntity)] = n;
	lastMenuEnt[ENTINDEX(pEntity)] = ENTINDEX(pRadio);

	

	// Set the values that determine how long we accept input...
	menushow2[ENTINDEX(pEntity)] = gpGlobals->time + 60;
}
Beispiel #14
0
static cell AMX_NATIVE_CALL write_char(AMX *amx, cell *params) /* 1 param */
{
	WRITE_CHAR(params[1]);
	return 1;
}
Beispiel #15
0
/***
*int _output(stream, format, argptr), static int output(format, argptr)
*
*Purpose:
*   Output performs printf style output onto a stream.  It is called by
*   printf/fprintf/sprintf/vprintf/vfprintf/vsprintf to so the dirty
*   work.  In multi-thread situations, _output assumes that the given
*   stream is already locked.
*
*   Algorithm:
*       The format string is parsed by using a finite state automaton
*       based on the current state and the current character read from
*       the format string.  Thus, looping is on a per-character basis,
*       not a per conversion specifier basis.  Once the format specififying
*       character is read, output is performed.
*
*Entry:
*   FILE *stream   - stream for output
*   char *format   - printf style format string
*   va_list argptr - pointer to list of subsidiary arguments
*
*Exit:
*   Returns the number of characters written, or -1 if an output error
*   occurs.
*ifdef _UNICODE
*   The wide-character flavour returns the number of wide-characters written.
*endif
*
*Exceptions:
*
*******************************************************************************/
#ifdef CPRFLAG
#ifndef FORMAT_VALIDATIONS
_CRTIMP int __cdecl _vtcprintf (
    const _TCHAR *format,
    va_list argptr
)
{
    return _vtcprintf_l(format, NULL, argptr);
}

#else  /* FORMAT_VALIDATIONS */
_CRTIMP int __cdecl _vtcprintf_s (
    const _TCHAR *format,
    va_list argptr
)
{
    return _vtcprintf_s_l(format, NULL, argptr);
}

#endif  /* FORMAT_VALIDATIONS */
#endif  /* CPRFLAG */

#ifdef CPRFLAG
#ifndef FORMAT_VALIDATIONS
_CRTIMP int __cdecl _vtcprintf_l (
#else  /* FORMAT_VALIDATIONS */
_CRTIMP int __cdecl _vtcprintf_s_l (
#endif  /* FORMAT_VALIDATIONS */
#else  /* CPRFLAG */

#ifdef _UNICODE
#ifndef FORMAT_VALIDATIONS
int __cdecl _woutput (
    miniFILE *stream,
#else  /* FORMAT_VALIDATIONS */
int __cdecl _woutput_s (
    miniFILE *stream,
#endif  /* FORMAT_VALIDATIONS */
#else  /* _UNICODE */
#ifndef FORMAT_VALIDATIONS
int __cdecl _output (
    miniFILE *stream,
#else  /* FORMAT_VALIDATIONS */
int __cdecl _output_s (
    miniFILE *stream,

#endif  /* FORMAT_VALIDATIONS */
#endif  /* _UNICODE */

#endif  /* CPRFLAG */
    const _TCHAR *format,
    va_list argptr
)
{
    int hexadd=0;     /* offset to add to number to get 'a'..'f' */
    TCHAR ch;       /* character just read */
    int flags=0;      /* flag word -- see #defines above for flag values */
    enum STATE state;   /* current state */
    enum CHARTYPE chclass; /* class of current character */
    int radix;      /* current conversion radix */
    int charsout;   /* characters currently written so far, -1 = IO error */
    int fldwidth = 0;   /* selected field width -- 0 means default */
    int precision = 0;  /* selected precision  -- -1 means default */
    TCHAR prefix[2];    /* numeric prefix -- up to two characters */
    int prefixlen=0;  /* length of prefix -- 0 means no prefix */
    int capexp = 0;     /* non-zero = 'E' exponent signifient, zero = 'e' */
    int no_output=0;  /* non-zero = prodcue no output for this specifier */
    union {
        const char *sz;   /* pointer text to be printed, not zero terminated */
        const wchar_t *wz;
    } text;

    int textlen;    /* length of the text in bytes/wchars to be printed.
                       textlen is in multibyte or wide chars if _UNICODE */
    union {
        char sz[BUFFERSIZE];
#ifdef _UNICODE
        wchar_t wz[BUFFERSIZE];
#endif  /* _UNICODE */
    } buffer;
    wchar_t wchar;                      /* temp wchar_t */
    int buffersize;                     /* size of text.sz (used only for the call to _cfltcvt) */
    int bufferiswide=0;         /* non-zero = buffer contains wide chars already */

#ifndef CPRFLAG
    _VALIDATE_RETURN( (stream != NULL), EINVAL, -1);
#endif  /* CPRFLAG */
    _VALIDATE_RETURN( (format != NULL), EINVAL, -1);

    charsout = 0;       /* no characters written yet */
    textlen = 0;        /* no text yet */
    state = ST_NORMAL;  /* starting state */
    buffersize = 0;

    /* main loop -- loop while format character exist and no I/O errors */
    while ((ch = *format++) != _T('\0') && charsout >= 0) {
#ifndef FORMAT_VALIDATIONS
        chclass = FIND_CHAR_CLASS(__lookuptable, ch);  /* find character class */
        state = FIND_NEXT_STATE(__lookuptable, chclass, state); /* find next state */
#else  /* FORMAT_VALIDATIONS */
        chclass = FIND_CHAR_CLASS(__lookuptable_s, ch);  /* find character class */
        state = FIND_NEXT_STATE(__lookuptable_s, chclass, state); /* find next state */

        _VALIDATE_RETURN((state != ST_INVALID), EINVAL, -1);

#endif  /* FORMAT_VALIDATIONS */

        /* execute code for each state */
        switch (state) {

        case ST_NORMAL:

NORMAL_STATE:

            /* normal state -- just write character */
#ifdef _UNICODE
            bufferiswide = 1;
#else  /* _UNICODE */
            bufferiswide = 0;
#endif  /* _UNICODE */
            WRITE_CHAR(ch, &charsout);
            break;

        case ST_PERCENT:
            /* set default value of conversion parameters */
            prefixlen = fldwidth = no_output = capexp = 0;
            flags = 0;
            precision = -1;
            bufferiswide = 0;   /* default */
            break;

        case ST_FLAG:
            /* set flag based on which flag character */
            switch (ch) {
            case _T('-'):
                flags |= FL_LEFT;   /* '-' => left justify */
                break;
            case _T('+'):
                flags |= FL_SIGN;   /* '+' => force sign indicator */
                break;
            case _T(' '):
                flags |= FL_SIGNSP; /* ' ' => force sign or space */
                break;
            case _T('#'):
                flags |= FL_ALTERNATE;  /* '#' => alternate form */
                break;
            case _T('0'):
                flags |= FL_LEADZERO;   /* '0' => pad with leading zeros */
                break;
            }
            break;

        case ST_WIDTH:
            /* update width value */
            if (ch == _T('*')) {
                /* get width from arg list */
                fldwidth = get_int_arg(&argptr);
                if (fldwidth < 0) {
                    /* ANSI says neg fld width means '-' flag and pos width */
                    flags |= FL_LEFT;
                    fldwidth = -fldwidth;
                }
            }
            else {
                /* add digit to current field width */
                fldwidth = fldwidth * 10 + (ch - _T('0'));
            }
            break;

        case ST_DOT:
            /* zero the precision, since dot with no number means 0
               not default, according to ANSI */
            precision = 0;
            break;

        case ST_PRECIS:
            /* update precison value */
            if (ch == _T('*')) {
                /* get precision from arg list */
                precision = get_int_arg(&argptr);
                if (precision < 0)
                    precision = -1; /* neg precision means default */
            }
            else {
                /* add digit to current precision */
                precision = precision * 10 + (ch - _T('0'));
            }
            break;

        case ST_SIZE:
            /* just read a size specifier, set the flags based on it */
            switch (ch) {
            case _T('l'):
                /*
                 * In order to handle the ll case, we depart from the
                 * simple deterministic state machine.
                 */
                if (*format == _T('l'))
                {
                    ++format;
                    flags |= FL_LONGLONG;   /* 'll' => long long */
                }
                else
                {
                    flags |= FL_LONG;   /* 'l' => long int or wchar_t */
                }
                break;

            case _T('I'):
                /*
                 * In order to handle the I, I32, and I64 size modifiers, we
                 * depart from the simple deterministic state machine. The
                 * code below scans for characters following the 'I',
                 * and defaults to 64 bit on WIN64 and 32 bit on WIN32
                 */
#if PTR_IS_INT64
                flags |= FL_I64;    /* 'I' => __int64 on WIN64 systems */
#endif  /* PTR_IS_INT64 */
                if ( (*format == _T('6')) && (*(format + 1) == _T('4')) )
                {
                    format += 2;
                    flags |= FL_I64;    /* I64 => __int64 */
                }
                else if ( (*format == _T('3')) && (*(format + 1) == _T('2')) )
                {
                    format += 2;
                    flags &= ~FL_I64;   /* I32 => __int32 */
                }
                else if ( (*format == _T('d')) ||
                          (*format == _T('i')) ||
                          (*format == _T('o')) ||
                          (*format == _T('u')) ||
                          (*format == _T('x')) ||
                          (*format == _T('X')) )
                {
                    /*
                     * Nothing further needed.  %Id (et al) is
                     * handled just like %d, except that it defaults to 64 bits
                     * on WIN64.  Fall through to the next iteration.
                     */
                }
                else {
                    state = ST_NORMAL;
                    goto NORMAL_STATE;
                }
                break;

            case _T('h'):
                flags |= FL_SHORT;  /* 'h' => short int or char */
                break;

            case _T('w'):
                flags |= FL_WIDECHAR;  /* 'w' => wide character */
                break;

            }
            break;

        case ST_TYPE:
            /* we have finally read the actual type character, so we       */
            /* now format and "print" the output.  We use a big switch     */
            /* statement that sets 'text' to point to the text that should */
            /* be printed, and 'textlen' to the length of this text.       */
            /* Common code later on takes care of justifying it and        */
            /* other miscellaneous chores.  Note that cases share code,    */
            /* in particular, all integer formatting is done in one place. */
            /* Look at those funky goto statements!                        */

            switch (ch) {

            case _T('C'):   /* ISO wide character */
                if (!(flags & (FL_SHORT|FL_LONG|FL_WIDECHAR)))
#ifdef _UNICODE
                    flags |= FL_SHORT;
#else  /* _UNICODE */
                    flags |= FL_WIDECHAR;   /* ISO std. */
#endif  /* _UNICODE */
            /* fall into 'c' case */

            case _T('c'): {
                /* print a single character specified by int argument */
#ifdef _UNICODE
                bufferiswide = 1;
                wchar = (wchar_t) get_int_arg(&argptr);
                if (flags & FL_SHORT) {
                    /* format multibyte character */
                    /* this is an extension of ANSI */
                    char tempchar[2];
                    {
                        tempchar[0] = (char)(wchar & 0x00ff);
                        tempchar[1] = '\0';
                    }

                    if (_MBTOWC(buffer.wz,tempchar, MB_CUR_MAX) < 0)
                    {
                        /* ignore if conversion was unsuccessful */
                        no_output = 1;
                    }
                } else {
                    buffer.wz[0] = wchar;
                }
                text.wz = buffer.wz;
                textlen = 1;    /* print just a single character */
#else  /* _UNICODE */
                if (flags & (FL_LONG|FL_WIDECHAR)) {
                    wchar = (wchar_t) get_short_arg(&argptr);
                    no_output = 1;
                } else {
                    /* format multibyte character */
                    /* this is an extension of ANSI */
                    unsigned short temp;
                    wchar = (wchar_t)get_int_arg(&argptr);
                    temp = (unsigned short)wchar;
                    {
                        buffer.sz[0] = (char) temp;
                        textlen = 1;
                    }
                }
                text.sz = buffer.sz;
#endif  /* _UNICODE */
            }
            break;

            case _T('Z'): {
                /* print a Counted String */
                struct _count_string {
                    short Length;
                    short MaximumLength;
                    char *Buffer;
                } *pstr;

                pstr = (struct _count_string *)get_ptr_arg(&argptr);
                if (pstr == NULL || pstr->Buffer == NULL) {
                    /* null ptr passed, use special string */
                    text.sz = __nullstring;
                    textlen = (int)strlen(text.sz);
                } else {
                    if (flags & FL_WIDECHAR) {
                        text.wz = (wchar_t *)pstr->Buffer;
                        textlen = pstr->Length / (int)sizeof(wchar_t);
                        bufferiswide = 1;
                    } else {
                        bufferiswide = 0;
                        text.sz = pstr->Buffer;
                        textlen = pstr->Length;
                    }
                }
            }
            break;

            case _T('S'):   /* ISO wide character string */
#ifndef _UNICODE
                if (!(flags & (FL_SHORT|FL_LONG|FL_WIDECHAR)))
                    flags |= FL_WIDECHAR;
#else  /* _UNICODE */
                if (!(flags & (FL_SHORT|FL_LONG|FL_WIDECHAR)))
                    flags |= FL_SHORT;
#endif  /* _UNICODE */

            case _T('s'): {
                /* print a string --                            */
                /* ANSI rules on how much of string to print:   */
                /*   all if precision is default,               */
                /*   min(precision, length) if precision given. */
                /* prints '(null)' if a null string is passed   */

                int i;
                const char *p;       /* temps */
                const wchar_t *pwch;

                /* At this point it is tempting to use strlen(), but */
                /* if a precision is specified, we're not allowed to */
                /* scan past there, because there might be no null   */
                /* at all.  Thus, we must do our own scan.           */

                i = (precision == -1) ? INT_MAX : precision;
                text.sz = (char *)get_ptr_arg(&argptr);

                /* scan for null upto i characters */
#ifdef _UNICODE
                if (flags & FL_SHORT) {
                    if (text.sz == NULL) /* NULL passed, use special string */
                        text.sz = __nullstring;
                    p = text.sz;
                    for (textlen=0; textlen<i && *p; textlen++) {
                        ++p;
                    }
                    /* textlen now contains length in multibyte chars */
                } else {
                    if (text.wz == NULL) /* NULL passed, use special string */
                        text.wz = __wnullstring;
                    bufferiswide = 1;
                    pwch = text.wz;
                    while (i-- && *pwch)
                        ++pwch;
                    textlen = (int)(pwch - text.wz);       /* in wchar_ts */
                    /* textlen now contains length in wide chars */
                }
#else  /* _UNICODE */
                if (flags & (FL_LONG|FL_WIDECHAR)) {
                    if (text.wz == NULL) /* NULL passed, use special string */
                        text.wz = __wnullstring;
                    bufferiswide = 1;
                    pwch = text.wz;
                    while ( i-- && *pwch )
                        ++pwch;
                    textlen = (int)(pwch - text.wz);
                    /* textlen now contains length in wide chars */
                } else {
                    if (text.sz == NULL) /* NULL passed, use special string */
                        text.sz = __nullstring;
                    p = text.sz;
                    while (i-- && *p)
                        ++p;
                    textlen = (int)(p - text.sz);    /* length of the string */
                }

#endif  /* _UNICODE */
            }
            break;


            case _T('n'): {
                /* write count of characters seen so far into */
                /* short/int/long thru ptr read from args */

                void *p;        /* temp */

                p = get_ptr_arg(&argptr);

                /* %n is disabled */
                _VALIDATE_RETURN(("'n' format specifier disabled" && 0), EINVAL, -1);
                break;

                /* store chars out into short/long/int depending on flags */
#if !LONG_IS_INT
                if (flags & FL_LONG)
                    *(long *)p = charsout;
                else
#endif  /* !LONG_IS_INT */

#if !SHORT_IS_INT
                    if (flags & FL_SHORT)
                        *(short *)p = (short) charsout;
                    else
#endif  /* !SHORT_IS_INT */
                        *(int *)p = charsout;

                no_output = 1;              /* force no output */
            }
            break;

            case _T('E'):
            case _T('G'):
            case _T('A'):
                capexp = 1;                 /* capitalize exponent */
                ch += _T('a') - _T('A');    /* convert format char to lower */
            /* DROP THROUGH */
            case _T('e'):
            case _T('f'):
            case _T('g'):
            case _T('a'): {
                /* floating point conversion -- we call cfltcvt routines */
                /* to do the work for us.                                */
                flags |= FL_SIGNED;         /* floating point is signed conversion */
                text.sz = buffer.sz;        /* put result in buffer */
                buffersize = BUFFERSIZE;

                /* compute the precision value */
                if (precision < 0)
                    precision = 6;          /* default precision: 6 */
                else if (precision == 0 && ch == _T('g'))
                    precision = 1;          /* ANSI specified */
                else if (precision > MAXPRECISION)
                    precision = MAXPRECISION;

                if (precision > BUFFERSIZE - _CVTBUFSIZE) {
                    precision = BUFFERSIZE - _CVTBUFSIZE;
                }

                /* for safecrt, we pass along the FL_ALTERNATE flag to _safecrt_cfltcvt */
                if (flags & FL_ALTERNATE)
                {
                    capexp |= FL_ALTERNATE;
                }

                _CRT_DOUBLE tmp;
                tmp=va_arg(argptr, _CRT_DOUBLE);
                /* Note: assumes ch is in ASCII range */
                /* In safecrt, we provide a special version of _cfltcvt which internally calls printf (see safecrt_output_s.c) */
                _CFLTCVT(&tmp, buffer.sz, buffersize, (char)ch, precision, capexp);

                /* check if result was negative, save '-' for later */
                /* and point to positive part (this is for '0' padding) */
                if (*text.sz == '-') {
                    flags |= FL_NEGATIVE;
                    ++text.sz;
                }

                textlen = (int)strlen(text.sz);     /* compute length of text */
            }
            break;

            case _T('d'):
            case _T('i'):
                /* signed decimal output */
                flags |= FL_SIGNED;
                radix = 10;
                goto COMMON_INT;

            case _T('u'):
                radix = 10;
                goto COMMON_INT;

            case _T('p'):
                /* write a pointer -- this is like an integer or long */
                /* except we force precision to pad with zeros and */
                /* output in big hex. */

                precision = 2 * sizeof(void *);     /* number of hex digits needed */
#if PTR_IS_INT64
                flags |= FL_I64;                    /* assume we're converting an int64 */
#elif !PTR_IS_INT
                flags |= FL_LONG;                   /* assume we're converting a long */
#endif  /* !PTR_IS_INT */
            /* DROP THROUGH to hex formatting */

            case _T('X'):
                /* unsigned upper hex output */
                hexadd = _T('A') - _T('9') - 1;     /* set hexadd for uppercase hex */
                goto COMMON_HEX;

            case _T('x'):
                /* unsigned lower hex output */
                hexadd = _T('a') - _T('9') - 1;     /* set hexadd for lowercase hex */
                /* DROP THROUGH TO COMMON_HEX */

COMMON_HEX:
                radix = 16;
                if (flags & FL_ALTERNATE) {
                    /* alternate form means '0x' prefix */
                    prefix[0] = _T('0');
                    prefix[1] = (TCHAR)(_T('x') - _T('a') + _T('9') + 1 + hexadd);  /* 'x' or 'X' */
                    prefixlen = 2;
                }
                goto COMMON_INT;

            case _T('o'):
                /* unsigned octal output */
                radix = 8;
                if (flags & FL_ALTERNATE) {
                    /* alternate form means force a leading 0 */
                    flags |= FL_FORCEOCTAL;
                }
                /* DROP THROUGH to COMMON_INT */

COMMON_INT: {
                    /* This is the general integer formatting routine. */
                    /* Basically, we get an argument, make it positive */
                    /* if necessary, and convert it according to the */
                    /* correct radix, setting text and textlen */
                    /* appropriately. */

#if _INTEGRAL_MAX_BITS >= 64
//                unsigned __int64 number;    /* number to convert */
                    __uint64_t number;      /* number to convert */
                    int digit;              /* ascii value of digit */
                    __int64 l;              /* temp long value */
#else  /* _INTEGRAL_MAX_BITS >= 64        */
                    unsigned long number;   /* number to convert */
                    int digit;              /* ascii value of digit */
                    long l;                 /* temp long value */
#endif  /* _INTEGRAL_MAX_BITS >= 64        */

                    /* 1. read argument into l, sign extend as needed */
#if _INTEGRAL_MAX_BITS >= 64
                    if (flags & FL_I64)
                        l = get_int64_arg(&argptr);
                    else
#endif  /* _INTEGRAL_MAX_BITS >= 64        */

                        if (flags & FL_LONGLONG)
                            l = get_long_long_arg(&argptr);
                        else

#if !LONG_IS_INT
                            if (flags & FL_LONG)
                                l = get_long_arg(&argptr);
                            else
#endif  /* !LONG_IS_INT */

#if !SHORT_IS_INT
                                if (flags & FL_SHORT) {
                                    if (flags & FL_SIGNED)
                                        l = (short) get_int_arg(&argptr); /* sign extend */
                                    else
                                        l = (unsigned short) get_int_arg(&argptr);    /* zero-extend*/

                                } else
#endif  /* !SHORT_IS_INT */
                                {
                                    if (flags & FL_SIGNED)
                                        l = get_int_arg(&argptr); /* sign extend */
                                    else
                                        l = (unsigned int) get_int_arg(&argptr);    /* zero-extend*/

                                }

                    /* 2. check for negative; copy into number */
                    if ( (flags & FL_SIGNED) && l < 0) {
                        number = -l;
                        flags |= FL_NEGATIVE;   /* remember negative sign */
                    } else {
                        number = l;
                    }

#if _INTEGRAL_MAX_BITS >= 64
                    if ( (flags & FL_I64) == 0 && (flags & FL_LONGLONG) == 0 ) {
                        /*
                         * Unless printing a full 64-bit value, insure values
                         * here are not in cananical longword format to prevent
                         * the sign extended upper 32-bits from being printed.
                         */
                        number &= 0xffffffff;
                    }
#endif  /* _INTEGRAL_MAX_BITS >= 64        */

                    /* 3. check precision value for default; non-default */
                    /*    turns off 0 flag, according to ANSI. */
                    if (precision < 0)
                        precision = 1;  /* default precision */
                    else {
                        flags &= ~FL_LEADZERO;
                        if (precision > MAXPRECISION)
                            precision = MAXPRECISION;
                    }

                    /* 4. Check if data is 0; if so, turn off hex prefix */
                    if (number == 0)
                        prefixlen = 0;

                    /* 5. Convert data to ASCII -- note if precision is zero */
                    /*    and number is zero, we get no digits at all.       */

                    char *sz;
                    sz = &buffer.sz[BUFFERSIZE-1];    /* last digit at end of buffer */

                    while (precision-- > 0 || number != 0) {
                        digit = (int)(number % radix) + '0';
                        number /= radix;                /* reduce number */
                        if (digit > '9') {
                            /* a hex digit, make it a letter */
                            digit += hexadd;
                        }
                        *sz-- = (char)digit;       /* store the digit */
                    }

                    textlen = (int)((char *)&buffer.sz[BUFFERSIZE-1] - sz); /* compute length of number */
                    ++sz;          /* text points to first digit now */


                    /* 6. Force a leading zero if FORCEOCTAL flag set */
                    if ((flags & FL_FORCEOCTAL) && (textlen == 0 || sz[0] != '0')) {
                        *--sz = '0';
                        ++textlen;      /* add a zero */
                    }

                    text.sz = sz;
                }
                break;
            }


            /* At this point, we have done the specific conversion, and */
            /* 'text' points to text to print; 'textlen' is length.  Now we */
            /* justify it, put on prefixes, leading zeros, and then */
            /* print it. */

            if (!no_output) {
                int padding;    /* amount of padding, negative means zero */

                if (flags & FL_SIGNED) {
                    if (flags & FL_NEGATIVE) {
                        /* prefix is a '-' */
                        prefix[0] = _T('-');
                        prefixlen = 1;
                    }
                    else if (flags & FL_SIGN) {
                        /* prefix is '+' */
                        prefix[0] = _T('+');
                        prefixlen = 1;
                    }
                    else if (flags & FL_SIGNSP) {
                        /* prefix is ' ' */
                        prefix[0] = _T(' ');
                        prefixlen = 1;
                    }
                }

                /* calculate amount of padding -- might be negative, */
                /* but this will just mean zero */
                padding = fldwidth - textlen - prefixlen;

                /* put out the padding, prefix, and text, in the correct order */

                if (!(flags & (FL_LEFT | FL_LEADZERO))) {
                    /* pad on left with blanks */
                    WRITE_MULTI_CHAR(_T(' '), padding, &charsout);
                }

                /* write prefix */
                WRITE_STRING(prefix, prefixlen, &charsout);

                if ((flags & FL_LEADZERO) && !(flags & FL_LEFT)) {
                    /* write leading zeros */
                    WRITE_MULTI_CHAR(_T('0'), padding, &charsout);
                }

                /* write text */
#ifndef _UNICODE
                if (bufferiswide && (textlen > 0)) {
                    charsout = -1;
                } else {
                    WRITE_STRING(text.sz, textlen, &charsout);
                }
#else  /* _UNICODE */
                if (!bufferiswide && textlen > 0) {
                    char *p;
                    int retval = 0
                                 int count;

                    p = text.sz;
                    count = textlen;
                    while (count-- > 0) {
                        retval = _MBTOWC(&wchar, p, MB_CUR_MAX);
                        if (retval <= 0) {
                            charsout = -1;
                            break;
                        }
                        WRITE_CHAR(wchar, &charsout);
                        p += retval;
                    }
                } else {
                    WRITE_STRING(text.wz, textlen, &charsout);
                }
#endif  /* _UNICODE */

                if (charsout >= 0 && (flags & FL_LEFT)) {
                    /* pad on right with blanks */
                    WRITE_MULTI_CHAR(_T(' '), padding, &charsout);
                }

                /* we're done! */
            }
Beispiel #16
0
static hb_buffer_t *tx3g_decode_to_utf8( hb_buffer_t *in )
{
    uint8_t *pos = in->data;
    uint8_t *end = in->data + in->size;
    
    uint16_t numStyleRecords = 0;
    
    uint8_t *startStyle;
    uint8_t *endStyle;
    
    /*
     * Parse the packet as a TX3G TextSample.
     * 
     * Look for a single StyleBox ('styl') and read all contained StyleRecords.
     * Ignore all other box types.
     * 
     * NOTE: Buffer overflows on read are not checked.
     */
    uint16_t textLength = READ_U16();
    uint8_t *text = READ_ARRAY(textLength);
    startStyle = calloc( textLength, 1 );
    endStyle = calloc( textLength, 1 );
    while ( pos < end ) {
        /*
         * Read TextSampleModifierBox
         */
        uint32_t size = READ_U32();
        if ( size == 0 ) {
            size = pos - end;   // extends to end of packet
        }
        if ( size == 1 ) {
            hb_log( "dectx3gsub: TextSampleModifierBox has unsupported large size" );
            break;
        }
        uint32_t type = READ_U32();
        if ( type == FOURCC("uuid") ) {
            hb_log( "dectx3gsub: TextSampleModifierBox has unsupported extended type" );
            break;
        }
        
        if ( type == FOURCC("styl") ) {
            // Found a StyleBox. Parse the contained StyleRecords
            
            if ( numStyleRecords != 0 ) {
                hb_log( "dectx3gsub: found additional StyleBoxes on subtitle; skipping" );
                SKIP_ARRAY(size);
                continue;
            }
            
            numStyleRecords = READ_U16();
            
            int i;
            for (i=0; i<numStyleRecords; i++) {
                StyleRecord curRecord;
                curRecord.startChar         = READ_U16();
                curRecord.endChar           = READ_U16();
                curRecord.fontID            = READ_U16();
                curRecord.faceStyleFlags    = READ_U8();
                curRecord.fontSize          = READ_U8();
                curRecord.textColorRGBA     = READ_U32();
                
                startStyle[curRecord.startChar] |= curRecord.faceStyleFlags;
                endStyle[curRecord.endChar]     |= curRecord.faceStyleFlags;
            }
        } else {
            // Found some other kind of TextSampleModifierBox. Skip it.
            SKIP_ARRAY(size);
        }
    }
    
    /*
     * Copy text to output buffer, and add HTML markup for the style records
     */
    int maxOutputSize = textLength + (numStyleRecords * NUM_FACE_STYLE_FLAGS * (MAX_OPEN_TAG_SIZE + MAX_CLOSE_TAG_SIZE));
    hb_buffer_t *out = hb_buffer_init( maxOutputSize );
    if ( out == NULL )
        goto fail;
    uint8_t *dst = out->data;
    int charIndex = 0;
    for ( pos = text, end = text + textLength; pos < end; pos++ ) {
        if (IS_10xxxxxx(*pos)) {
            // Is a non-first byte of a multi-byte UTF-8 character
            WRITE_CHAR(*pos);
            continue;   // ...without incrementing 'charIndex'
        }
        
        uint8_t plusStyles = startStyle[charIndex];
        uint8_t minusStyles = endStyle[charIndex];
        
        if (minusStyles & UNDERLINE)
            WRITE_END_TAG('u');
        if (minusStyles & ITALIC)
            WRITE_END_TAG('i');
        if (minusStyles & BOLD)
            WRITE_END_TAG('b');
        
        if (plusStyles & BOLD)
            WRITE_START_TAG('b');
        if (plusStyles & ITALIC)
            WRITE_START_TAG('i');
        if (plusStyles & UNDERLINE)
            WRITE_START_TAG('u');
        
        WRITE_CHAR(*pos);
        charIndex++;
    }
    
    // Trim output buffer to the actual amount of data written
    out->size = dst - out->data;
    
    // Copy metadata from the input packet to the output packet
    out->s.start = in->s.start;
    out->s.stop = in->s.stop;
    
fail:
    free( startStyle );
    free( endStyle );
    
    return out;
}
/**
 * Format a string representation of the elements of @p value using @p fmt,
 * writing the result to @p outp.
 *
 * @param		value	The value to be formatted.
 * @param		fmt	The format string.
 * @param[out]		outp	On success, the string will be written to this 
 *				buffer. This argment may be NULL if the value is
 *				not desired.
 * @param[in,out]	olen	The capacity of @p outp. On success, will be set
 *				to the actual number of bytes required for the
 *				requested string encoding (including a trailing
 *				NUL).
 * @param		ap	Argument list.
 *
 * @par Format Strings
 * 
 * Value format strings are similar, but not identical to, those used
 * by printf(3).
 * 
 * Format specifier format:
 *     %[repeat][flags][width][.precision][length modifier][specifier]
 *
 * The format specifier is interpreted as an encoding directive for an
 * individual value element; each format specifier will fetch the next element
 * from the value, encode the element as the appropriate type based on the
 * length modifiers and specifier, and then format the result as a string.
 * 
 * For example, given a string value of '0x000F', and a format specifier of
 * '%#hhx', the value will be asked to encode its first element as
 * BHND_NVRAM_TYPE_UINT8. String formatting will then be applied to the 8-bit
 * unsigned integer representation, producing a string value of "0xF".
 * 
 * Repeat:
 * - [digits]		Repeatedly apply the format specifier to the input
 *			value's elements up to `digits` times. The delimiter
 *			must be passed as a string in the next variadic
 *			argument.
 * - []			Repeatedly apply the format specifier to the input
 *			value's elements until all elements have been. The
 *			processed. The delimiter must be passed as a string in
 *			the next variadic argument.
 * - [*]		Repeatedly apply the format specifier to the input
 *			value's elements. The repeat count is read from the
 *			next variadic argument as a size_t value
 * 
 * Flags:
 * - '#'		use alternative form (e.g. 0x/0X prefixing of hex
 *			strings).
 * - '0'		zero padding
 * - '-'		left adjust padding
 * - '+'		include a sign character
 * - ' '		include a space in place of a sign character for
 *			positive numbers.
 * 
 * Width/Precision:
 * - digits		minimum field width.
 * - *			read the minimum field width from the next variadic
 *			argument as a ssize_t value. A negative value enables
 *			left adjustment.
 * - .digits		field precision.
 * - .*			read the field precision from the next variadic argument
 *			as a ssize_t value. A negative value enables left
 *			adjustment.
 *
 * Length Modifiers:
 * - 'hh', 'I8'		Convert the value to an 8-bit signed or unsigned
 *			integer.
 * - 'h', 'I16'		Convert the value to an 16-bit signed or unsigned
 *			integer.
 * - 'l', 'I32'		Convert the value to an 32-bit signed or unsigned
 *			integer.
 * - 'll', 'j', 'I64'	Convert the value to an 64-bit signed or unsigned
 *			integer.
 * 
 * Data Specifiers:
 * - 'd', 'i'		Convert and format as a signed decimal integer.
 * - 'u'		Convert and format as an unsigned decimal integer.
 * - 'o'		Convert and format as an unsigned octal integer.
 * - 'x'		Convert and format as an unsigned hexadecimal integer,
 *			using lowercase hex digits.
 * - 'X'		Convert and format as an unsigned hexadecimal integer,
 *			using uppercase hex digits.
 * - 's'		Convert and format as a string.
 * - '%'		Print a literal '%' character.
 *
 * @retval 0		success
 * @retval EINVAL	If @p fmt contains unrecognized format string
 *			specifiers.
 * @retval ENOMEM	If the @p outp is non-NULL, and the provided @p olen
 *			is too small to hold the encoded value.
 * @retval EFTYPE	If value coercion from @p value to a single string
 *			value via @p fmt is unsupported.
 * @retval ERANGE	If value coercion of @p value would overflow (or
 *			underflow) the representation defined by @p fmt.
 */
int
bhnd_nvram_val_vprintf(bhnd_nvram_val *value, const char *fmt, char *outp,
    size_t *olen, va_list ap)
{
	const void	*elem;
	size_t		 elen;
	size_t		 limit, nbytes;
	int		 error;

	elem = NULL;

	/* Determine output byte limit */
	nbytes = 0;
	if (outp != NULL)
		limit = *olen;
	else
		limit = 0;

#define	WRITE_CHAR(_c)	do {			\
	if (limit > nbytes)			\
		*(outp + nbytes) = _c;		\
						\
	if (nbytes == SIZE_MAX)			\
		return (EFTYPE);		\
	nbytes++;				\
} while (0)

	/* Encode string value as per the format string */
	for (const char *p = fmt; *p != '\0'; p++) {
		const char	*delim;
		size_t		 precision, width, delim_len;
		u_long		 repeat, bits;
		bool		 alt_form, ladjust, have_precision;
		char		 padc, signc, lenc;

		padc = ' ';
		signc = '\0';
		lenc = '\0';
		delim = "";
		delim_len = 0;

		ladjust = false;
		alt_form = false;

		have_precision = false;
		precision = 1;
		bits = 32;
		width = 0;
		repeat = 1;

		/* Copy all input to output until we hit a format specifier */
		if (*p != '%') {
			WRITE_CHAR(*p);
			continue;
		}

		/* Hit '%' -- is this followed by an escaped '%' literal? */
		p++;
		if (*p == '%') {
			WRITE_CHAR('%');
			p++;
			continue;
		}

		/* Parse repeat specifier */
		if (*p == '[') {
			p++;
			
			/* Determine repeat count */
			if (*p == ']') {
				/* Repeat consumes all input */
				repeat = bhnd_nvram_val_nelem(value);
			} else if (*p == '*') {
				/* Repeat is supplied as an argument */
				repeat = va_arg(ap, size_t);
				p++;
			} else {
				char *endp;

				/* Repeat specified as argument */
				repeat = strtoul(p, &endp, 10);
				if (p == endp) {
					BHND_NV_LOG("error parsing repeat "
						    "count at '%s'", p);
					return (EINVAL);
				}
				
				/* Advance past repeat count */
				p = endp;
			}

			/* Advance past terminating ']' */
			if (*p != ']') {
				BHND_NV_LOG("error parsing repeat count at "
				    "'%s'", p);
				return (EINVAL);
			}
			p++;

			delim = va_arg(ap, const char *);
			delim_len = strlen(delim);
		}

		/* Parse flags */
		while (*p != '\0') {
			const char	*np;
			bool		 stop;

			stop = false;
			np = p+1;
	
			switch (*p) {
			case '#':
				alt_form = true;
				break;
			case '0':
				padc = '0';
				break;
			case '-':
				ladjust = true;
				break;
			case ' ':
				/* Must not override '+' */
				if (signc != '+')
					signc = ' ';
				break;
			case '+':
				signc = '+';
				break;
			default:
				/* Non-flag character */
				stop = true;
				break;
			}

			if (stop)
				break;
			else
				p = np;
		}

		/* Parse minimum width */
		if (*p == '*') {
			ssize_t arg;

			/* Width is supplied as an argument */
			arg = va_arg(ap, int);

			/* Negative width argument is interpreted as
			 * '-' flag followed by positive width */
			if (arg < 0) {
				ladjust = true;
				arg = -arg;
			}

			width = arg;
			p++;
		} else if (bhnd_nv_isdigit(*p)) {