/*
** The workhorse sprintf code.
*/
static int dosprintf(SprintfState *ss, const char *fmt, va_list ap)
{
    char c;
    int flags, width, prec, radix, type;
    union {
	char ch;
	int i;
	long l;
	PRInt64 ll;
	double d;
	const char *s;
	int *ip;
#ifdef WIN32
	const WCHAR *ws;
#endif
    } u;
    const char *fmt0;
    static char *hex = "0123456789abcdef";
    static char *HEX = "0123456789ABCDEF";
    char *hexp;
    int rv, i;
    struct NumArg* nas = NULL;
    struct NumArg* nap;
    struct NumArg  nasArray[ NAS_DEFAULT_NUM ];
    char  pattern[20];
    const char* dolPt = NULL;  /* in "%4$.2f", dolPt will point to . */
#ifdef WIN32
    char *pBuf = NULL;
#endif

    /*
    ** build an argument array, IF the fmt is numbered argument
    ** list style, to contain the Numbered Argument list pointers
    */

    nas = BuildArgArray( fmt, ap, &rv, nasArray );
    if( rv < 0 ){
	/* the fmt contains error Numbered Argument format, [email protected] */
	PR_ASSERT(0);
	return rv;
    }

    while ((c = *fmt++) != 0) {
	if (c != '%') {
	    rv = (*ss->stuff)(ss, fmt - 1, 1);
	    if (rv < 0) {
		return rv;
	    }
	    continue;
	}
	fmt0 = fmt - 1;

	/*
	** Gobble up the % format string. Hopefully we have handled all
	** of the strange cases!
	*/
	flags = 0;
	c = *fmt++;
	if (c == '%') {
	    /* quoting a % with %% */
	    rv = (*ss->stuff)(ss, fmt - 1, 1);
	    if (rv < 0) {
		return rv;
	    }
	    continue;
	}

	if( nas != NULL ){
	    /* the fmt contains the Numbered Arguments feature */
	    i = 0;
	    while( c && c != '$' ){	    /* should imporve error check later */
		i = ( i * 10 ) + ( c - '0' );
		c = *fmt++;
	    }

	    if( nas[i-1].type == TYPE_UNKNOWN ){
		if( nas && ( nas != nasArray ) )
		    PR_DELETE( nas );
		return -1;
	    }

	    nap = &nas[i-1];
	    dolPt = fmt;
	    c = *fmt++;
	}

	/*
	 * Examine optional flags.  Note that we do not implement the
	 * '#' flag of sprintf().  The ANSI C spec. of the '#' flag is
	 * somewhat ambiguous and not ideal, which is perhaps why
	 * the various sprintf() implementations are inconsistent
	 * on this feature.
	 */
	while ((c == '-') || (c == '+') || (c == ' ') || (c == '0')) {
	    if (c == '-') flags |= FLAG_LEFT;
	    if (c == '+') flags |= FLAG_SIGNED;
	    if (c == ' ') flags |= FLAG_SPACED;
	    if (c == '0') flags |= FLAG_ZEROS;
	    c = *fmt++;
	}
	if (flags & FLAG_SIGNED) flags &= ~FLAG_SPACED;
	if (flags & FLAG_LEFT) flags &= ~FLAG_ZEROS;

	/* width */
	if (c == '*') {
	    c = *fmt++;
	    width = va_arg(ap, int);
	} else {
// Drop some objects on another one
void backdrop_drop_object(BackdropInfo *info,BackdropObject *on_object)
{
	BackdropObject *object;
	char *buf,*dbuf;
	struct InfoData __aligned data;
	BPTR lock;

	if (!(buf=AllocVec(512,0)))
		return;
	dbuf=buf+256;

	// Drop on an AppIcon
	if (on_object->type==BDO_APP_ICON)
	{
		DOpusAppMessage *msg;
		struct MsgPort *port;

		// Is the icon busy?
		if (on_object->flags&BDOF_BUSY)
		{
			DisplayBeep(info->window->WScreen);
			FreeVec(buf);
			return;
		}

		// Build AppMessage
		if (!(msg=backdrop_appmessage(info,1)))
		{
			FreeVec(buf);
			return;
		}

		// Set message type
		msg->da_Msg.am_Type=MTYPE_APPICON;

		// Get AppInfo
		port=WB_AppWindowData(
			(struct AppWindow *)on_object->misc_data,
			&msg->da_Msg.am_ID,
			&msg->da_Msg.am_UserData);

		// Send the message
		PutMsg(port,(struct Message *)msg);
		FreeVec(buf);
		return;
	}

	// Only support dropping on disks at the moment
	if ((on_object->type!=BDO_DISK && on_object->type!=BDO_BAD_DISK) ||
		on_object->flags&(BDOF_ASSIGN|BDOF_CACHE))
	{
		DisplayBeep(info->window->WScreen);
		FreeVec(buf);
		return;
	}

	// Go through backdrop list
	for (object=(BackdropObject *)info->objects.list.lh_Head;
		object->node.ln_Succ;
		object=(BackdropObject *)object->node.ln_Succ)
	{
		// Selected disk?
		if (object->type==BDO_DISK && !(object->flags&(BDOF_ASSIGN|BDOF_CACHE)) && object->state)
		{
			BPTR lock;

			// Get disk lock
			if (lock=backdrop_icon_lock(object))
			{
				// This is the source
				Info(lock,&data);

				// Get device name
				DeviceFromLock(lock,buf);

				// Unlock lock
				UnLock(lock);
			}
			break;
		}
	}

	// Didn't get anything?
	if (!object->node.ln_Succ)
	{
		DisplayBeep(info->window->WScreen);
		FreeVec(buf);
		return;
	}

	// Drop on a bad disk?
	if (on_object->type==BDO_BAD_DISK)
	{
		// Get device name
		strcpy(dbuf,on_object->name);
	}

	// Real disk
	else
	{
		// Get destination disk lock
		if (!(lock=backdrop_icon_lock(on_object)))
		{
			FreeVec(buf);
			return;
		}

		// Destination is the one we dropped it on
		Info(lock,&data);

		// Get device name
		DeviceFromLock(lock,dbuf);
		UnLock(lock);
	}

	// Launch diskcopy
	function_launch(
		FUNCTION_RUN_FUNCTION,
		def_function_diskcopy,
		0,
		0,
		0,0,
		0,0,
		BuildArgArray(buf,dbuf,0),
		0,0);

	FreeVec(buf);
}