<commit_before>#include "StdAfx.h"
#include "Inject.h"

#include "Util.h"

// Ripped from Oblivion Script Extender
// http://obse.silverlock.org/
// The sordid thread-suspending logic in DoInjectDLL is my own dismal contribution for ModelMod

extern BOOL SuspendProcessThreads(DWORD dwOwnerPID, bool suspend);

Inject::Inject(void)
{
}

Inject::~Inject(void)
{
}

bool Inject::InjectDLL(DWORD processId, const char * dllPath, bool processWasLaunched)
{
	bool	result = false;

	// wrap DLL injection in SEH, if it crashes print a message
	__try {
		result = DoInjectDLL(processId, dllPath, processWasLaunched);
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		_injectError = "DLL injection failed. In most cases, this is caused by an overly paranoid software firewall or antivirus package. Disabling either of these may solve the problem.";
		result = false;
	}

	return result;
}

/*** jmp hook layout
 *	E9 ## ## ## ##	jmp LoadLibraryA
 *						offset = LoadLibraryA - (base + 5)
 *	<string>		name of function
 ***/

typedef unsigned int UInt32;
typedef unsigned char UInt8;

bool Inject::DoInjectDLL(DWORD processId, const char * dllPath, bool processWasLaunched)
{
	bool result = false; // assume failure

	HANDLE process = OpenProcess(
		PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, processId);
	if(process)
	{
		UInt32	hookBase = (UInt32)VirtualAllocEx(process, NULL, 8192, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
		if(hookBase)
		{
			// safe because kernel32 is loaded at the same address in all processes
			// (can change across restarts)
			UInt32	loadLibraryAAddr = (UInt32)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");

			//_MESSAGE("hookBase = %08X", hookBase);
			//_MESSAGE("loadLibraryAAddr = %08X", loadLibraryAAddr);

			SIZE_T	bytesWritten;
			WriteProcessMemory(process, (LPVOID)(hookBase + 5), dllPath, strlen(dllPath) + 1, &bytesWritten);

			UInt8	hookCode[5];

			hookCode[0] = 0xE9;
			*((UInt32 *)&hookCode[1]) = loadLibraryAAddr - (hookBase + 5);

			WriteProcessMemory(process, (LPVOID)(hookBase), hookCode, sizeof(hookCode), &bytesWritten);

			// So, if we are attaching to an existing process, all of its threads should have already been suspended by the loader.
			// however, its quite possible that we suspended the threads inside a critical section, and we'll have problems either
			// creating the hook thread or waiting for it to exit.
			// So what we'll do is wait for a bit on the hook thread, and if we timeout, resume all threads in the target process for a brief period,
			// then resuspend them.  Then resume our hook thread and try again.  Do this some number of times and hopefully we'll be successful.
			// Its basically a jackhammer, and it can fail (especially if our hook thread does a bunch of slow initialization stuff), but it
			// usually succeeds.

			const int SuspendSleepTime = 1;

			int hook_thread_attempts = 3;
			HANDLE hookThread = NULL;
			bool hookThreadValid = false;
			while (!hookThreadValid && hook_thread_attempts > 0) {
				hook_thread_attempts--;
				hookThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)hookBase, (void *)(hookBase + 5), 0, NULL);
				hookThreadValid = hookThread && hookThread != INVALID_HANDLE_VALUE;
				if (!hookThreadValid) {
					Util::Log("Failed to create hook thread (%d more attempts)\n", hook_thread_attempts);
					SuspendProcessThreads(processId, false);
					Sleep(SuspendSleepTime);
					SuspendProcessThreads(processId, true);
				}
			}
			if (hookThreadValid)
			{
				ResumeThread(hookThread);

				DWORD waitTimeout;
				int MaxHookAttempts;
				if (processWasLaunched) {
					waitTimeout = INFINITE;
					MaxHookAttempts = 1;
				}
				else {
					waitTimeout = 500;
					// Note, if you need to debug injection (via attaching during SpinWhileFileExists),
					// set this to a large number
					// to prevent the loader from bailing and aborting
					// during the time it takes you to attach.
					// 100 attempts at 500 timeout = about 50 seconds of waiting.
					// Don't use waitTimeout INFINITE as above, it will deadlock.
					MaxHookAttempts = 25;
				}

				int attempt = 0;

				for (attempt = 0; !result && attempt < MaxHookAttempts; ++attempt) {
					Util::Log("Waiting for hook thread: attempt %d; timeout: %d\n", attempt, waitTimeout);

					switch(WaitForSingleObject(hookThread, waitTimeout))  // g_options.m_threadTimeout
					{
						case WAIT_OBJECT_0:
							Util::Log("Hook Thread complete\n");
							result = true;
							break;

						case WAIT_ABANDONED:
							_injectError = "Hook Thread WAIT_ABANDONED";
							break;

						case WAIT_TIMEOUT:
							// Possible lock contention.
							// Resume all threads, sleep for a bit then suspend them all again.  Then resume hook thread and retry.
							Util::Log("Timeout\n");
							SuspendProcessThreads(processId,false);
							Sleep(SuspendSleepTime);
							SuspendProcessThreads(processId,true);
							ResumeThread(hookThread);
							break;

						case WAIT_FAILED:
							_injectError = "Hook Thread WAIT_FAILED";
							break;
						default:
							_injectError = "Hook Thread Unknown wait state";

					}
				}

				if (!result) {
					_injectError = "Unable to complete hook thread after several attempts";
				}

				CloseHandle(hookThread);
			}
			else {
				//http://stackoverflow.com/questions/3006229/get-a-text-from-the-error-code-returns-from-the-getlasterror-function
				DWORD   dwLastError = ::GetLastError();
				const DWORD BufSize = 256;
				TCHAR   lpBuffer[BufSize] = _T("?");
				if(dwLastError != 0)    // Don't want to see a "operation done successfully" error ;-)
				::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,                 // Its a system error
                     NULL,                                      // No string to be formatted needed
                     dwLastError,                               // Hey Windows: Please explain this error!
                     MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),  // Do it in the standard language
                     lpBuffer,              // Put the message here
                     BufSize-1,                     // Number of bytes to store the message
                     NULL);

				_injectError = string("CreateRemoteThread failed: ") + string(lpBuffer);
			}

			// the size parameter must be 0 when using MEM_RELEASE (CodeAnalysis C6333)
			VirtualFreeEx(process, (LPVOID)hookBase, 0, MEM_RELEASE);
		}
		else
			_injectError = "Process::InstallHook: couldn't allocate memory in target process";

		CloseHandle(process);
	}
	else
		_injectError = "Process::InstallHook: couldn't get process handle.  You may need to run MMLoader as an adminstrator.";

	return result;
}
<commit_msg>MMLoader(CodeAnalysis): fix unlikely failure getting handle of kernel32.dll<commit_after>#include "StdAfx.h"
#include "Inject.h"

#include "Util.h"

// Ripped from Oblivion Script Extender
// http://obse.silverlock.org/
// The sordid thread-suspending logic in DoInjectDLL is my own dismal contribution for ModelMod

extern BOOL SuspendProcessThreads(DWORD dwOwnerPID, bool suspend);

Inject::Inject(void)
{
}

Inject::~Inject(void)
{
}

bool Inject::InjectDLL(DWORD processId, const char * dllPath, bool processWasLaunched)
{
	bool	result = false;

	// wrap DLL injection in SEH, if it crashes print a message
	__try {
		result = DoInjectDLL(processId, dllPath, processWasLaunched);
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		_injectError = "DLL injection failed. In most cases, this is caused by an overly paranoid software firewall or antivirus package. Disabling either of these may solve the problem.";
		result = false;
	}

	return result;
}

/*** jmp hook layout
 *	E9 ## ## ## ##	jmp LoadLibraryA
 *						offset = LoadLibraryA - (base + 5)
 *	<string>		name of function
 ***/

typedef unsigned int UInt32;
typedef unsigned char UInt8;

bool Inject::DoInjectDLL(DWORD processId, const char * dllPath, bool processWasLaunched)
{
	bool result = false; // assume failure

	HMODULE k32 = GetModuleHandle("kernel32.dll");
	if (k32 == 0) {
		_injectError = "Failed to obtain handle for kernel32.dll";
		return result;
	}

	HANDLE process = OpenProcess(
		PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, processId);
	if(process)
	{
		UInt32	hookBase = (UInt32)VirtualAllocEx(process, NULL, 8192, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
		if(hookBase)
		{
			// safe because kernel32 is loaded at the same address in all processes
			// (can change across restarts)
			UInt32	loadLibraryAAddr = (UInt32)GetProcAddress(k32, "LoadLibraryA");

			//_MESSAGE("hookBase = %08X", hookBase);
			//_MESSAGE("loadLibraryAAddr = %08X", loadLibraryAAddr);

			SIZE_T	bytesWritten;
			WriteProcessMemory(process, (LPVOID)(hookBase + 5), dllPath, strlen(dllPath) + 1, &bytesWritten);

			UInt8	hookCode[5];

			hookCode[0] = 0xE9;
			*((UInt32 *)&hookCode[1]) = loadLibraryAAddr - (hookBase + 5);

			WriteProcessMemory(process, (LPVOID)(hookBase), hookCode, sizeof(hookCode), &bytesWritten);

			// So, if we are attaching to an existing process, all of its threads should have already been suspended by the loader.
			// however, its quite possible that we suspended the threads inside a critical section, and we'll have problems either
			// creating the hook thread or waiting for it to exit.
			// So what we'll do is wait for a bit on the hook thread, and if we timeout, resume all threads in the target process for a brief period,
			// then resuspend them.  Then resume our hook thread and try again.  Do this some number of times and hopefully we'll be successful.
			// Its basically a jackhammer, and it can fail (especially if our hook thread does a bunch of slow initialization stuff), but it
			// usually succeeds.

			const int SuspendSleepTime = 1;

			int hook_thread_attempts = 3;
			HANDLE hookThread = NULL;
			bool hookThreadValid = false;
			while (!hookThreadValid && hook_thread_attempts > 0) {
				hook_thread_attempts--;
				hookThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)hookBase, (void *)(hookBase + 5), 0, NULL);
				hookThreadValid = hookThread && hookThread != INVALID_HANDLE_VALUE;
				if (!hookThreadValid) {
					Util::Log("Failed to create hook thread (%d more attempts)\n", hook_thread_attempts);
					SuspendProcessThreads(processId, false);
					Sleep(SuspendSleepTime);
					SuspendProcessThreads(processId, true);
				}
			}
			if (hookThreadValid)
			{
				ResumeThread(hookThread);

				DWORD waitTimeout;
				int MaxHookAttempts;
				if (processWasLaunched) {
					waitTimeout = INFINITE;
					MaxHookAttempts = 1;
				}
				else {
					waitTimeout = 500;
					// Note, if you need to debug injection (via attaching during SpinWhileFileExists),
					// set this to a large number
					// to prevent the loader from bailing and aborting
					// during the time it takes you to attach.
					// 100 attempts at 500 timeout = about 50 seconds of waiting.
					// Don't use waitTimeout INFINITE as above, it will deadlock.
					MaxHookAttempts = 25;
				}

				int attempt = 0;

				for (attempt = 0; !result && attempt < MaxHookAttempts; ++attempt) {
					Util::Log("Waiting for hook thread: attempt %d; timeout: %d\n", attempt, waitTimeout);

					switch(WaitForSingleObject(hookThread, waitTimeout))  // g_options.m_threadTimeout
					{
						case WAIT_OBJECT_0:
							Util::Log("Hook Thread complete\n");
							result = true;
							break;

						case WAIT_ABANDONED:
							_injectError = "Hook Thread WAIT_ABANDONED";
							break;

						case WAIT_TIMEOUT:
							// Possible lock contention.
							// Resume all threads, sleep for a bit then suspend them all again.  Then resume hook thread and retry.
							Util::Log("Timeout\n");
							SuspendProcessThreads(processId,false);
							Sleep(SuspendSleepTime);
							SuspendProcessThreads(processId,true);
							ResumeThread(hookThread);
							break;

						case WAIT_FAILED:
							_injectError = "Hook Thread WAIT_FAILED";
							break;
						default:
							_injectError = "Hook Thread Unknown wait state";

					}
				}

				if (!result) {
					_injectError = "Unable to complete hook thread after several attempts";
				}

				CloseHandle(hookThread);
			}
			else {
				//http://stackoverflow.com/questions/3006229/get-a-text-from-the-error-code-returns-from-the-getlasterror-function
				DWORD   dwLastError = ::GetLastError();
				const DWORD BufSize = 256;
				TCHAR   lpBuffer[BufSize] = _T("?");
				if(dwLastError != 0)    // Don't want to see a "operation done successfully" error ;-)
				::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,                 // Its a system error
                     NULL,                                      // No string to be formatted needed
                     dwLastError,                               // Hey Windows: Please explain this error!
                     MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),  // Do it in the standard language
                     lpBuffer,              // Put the message here
                     BufSize-1,                     // Number of bytes to store the message
                     NULL);

				_injectError = string("CreateRemoteThread failed: ") + string(lpBuffer);
			}

			// the size parameter must be 0 when using MEM_RELEASE (CodeAnalysis C6333)
			VirtualFreeEx(process, (LPVOID)hookBase, 0, MEM_RELEASE);
		}
		else
			_injectError = "Process::InstallHook: couldn't allocate memory in target process";

		CloseHandle(process);
	}
	else
		_injectError = "Process::InstallHook: couldn't get process handle.  You may need to run MMLoader as an adminstrator.";

	return result;
}
<|endoftext|>


<commit_before>#include "susi/duktape/DuktapeEngine.h"

std::string Susi::Duktape::susiJS = R"SUSIJS(

var susi = {
    _consumerCallbacks: [],
    _processorCallbacks: [],

    _processorTopicCounter: {},
    _consumerTopicCounter: {},

    _publishCallbacks: {},
    _processorProcesses: {},

    _processed: [],

    registerConsumer: function(topic,callback) {
        var id = this._genID();
        this._consumerCallbacks.push({topic: topic, callback: callback, id: id});
        var count = this._consumerTopicCounter[topic] || 0;
        count++;
        this._consumerTopicCounter[topic] = count;
        if(count == 1){
            _registerConsumer(topic);
        }
        return id;
    },

    registerProcessor: function(topic,callback) {
        var id = this._genID();
        this._processorCallbacks.push({topic: topic, callback: callback, id: id});
        var count = this._processorTopicCounter[topic] || 0;
        count++;
        this._processorTopicCounter[topic] = count;
        if(count == 1){
            _registerProcessor(topic);
        }
        return id;
    },

    unregisterConsumer: function(id){
        for(var i=0;i<this._consumerCallbacks;i++){
            if(this._consumerCallbacks[i].id === id){
                var topic = this._consumerCallbacks[i].topic;
                this._consumerCallbacks.splice(i,1);
                var count = this._consumerTopicCounter[topic];
                count--;
                if(count === 0){
                    delete(this._consumerTopicCounter[topic]);
                    _unregisterConsumer(topic);
                }else{
                    this._consumerTopicCounter[topic] = count;
                }
                return true;
            }
        }
        return false;
    },

    unregisterProcessor: function(id){
        for(var i=0;i<this._processorCallbacks;i++){
            if(this._processorCallbacks[i].id === id){
                var topic = this._processorCallbacks[i].topic;
                this._processorCallbacks.splice(i,1);
                var count = this._processorTopicCounter[topic];
                count--;
                if(count === 0){
                    delete(this._processorTopicCounter[topic]);
                    _unregisterProcessor(topic);
                }else{
                    this._processorTopicCounter[topic] = count;
                }
                return true;
            }
        }
        return false;
    },

    publish: function(event,callback) {
        if(event.id === undefined){
            event.id = ''+this._genID();
        }
        if(callback !== undefined) {
            this._publishCallbacks[event.id] = callback;
        }
        _publish(JSON.stringify(event));
    },

    ack: function(event){
        var process = this._processorProcesses[event.id];
        if(process.next >= process.processors.length){
            delete this._processorProcesses[event.id];
            _ack(JSON.stringify(event));
        }else{
            process.next++;
            process.processors[process.next-1](event);
        }
    },

    dismiss: function(event){
        delete(this._processorProcesses[event.id]);
        _dismiss(JSON.stringify(event));
    },

    //used by js to interact with c++ part
    _processConsumerEvent: function(event,topic){
        event = JSON.parse(event);
        for(var i=0;i<this._consumerCallbacks.length;i++){
            if(topic.match(this._consumerCallbacks[i].topic)){
                this._consumerCallbacks[i].callback(event);
            }
        }
    },

    _processProcessorEvent: function(event,topic){
        event = JSON.parse(event);
        if(this._processed.indexOf(event.id) !== -1){
            _ack(JSON.stringify(event));
            return;
        }
        this._processed.push(event.id);
        if(this._processed.length > 64){
            this._processed.splice(0,1);
        }
        Duktape.fin(event,function(event){
            susi.ack(event);
        });
        var process = {
            processors: [],
            next: 0
        };

        for (var i = 0; i<this._processorCallbacks.length; i++) {
            if(event.topic.match(this._processorCallbacks[i].topic)){
                process.processors.push(this._processorCallbacks[i].callback);
            }
        }

        this._processorProcesses[event.id] = process;
        this.ack(event);
        Duktape.gc();
    },

    _processAck: function(event){
        event = JSON.parse(event);
        var cb = this._publishCallbacks[event.id];
        if(cb !== undefined) {
            cb(event);
            delete this._publishCallbacks[event.id];
        }
    },

    _genID: function(){
        return Math.floor(Math.random()*1000000000000);
    }
};

//called by c++ part
function _processConsumerEvent(event,topic){
    susi._processConsumerEvent(event,topic);
}

function _processProcessorEvent(event,topic){
    susi._processProcessorEvent(event,topic)
}

function _processAck(event){
    susi._processAck(event);
}

var duktapeLogger = new Duktape.Logger('susi-js');
duktapeLogger.l = 0;

var console = {
    _prepareArguments: function(args){
        var newArgs = [];
        for(var i=0;i<args.length;i++){
            if(typeof args[i] === 'object'){
                newArgs.push(Duktape.enc('jx',args[i]));
            }else{
                newArgs.push(args[i]);
            }
        }
        return newArgs;
    },
    _getLine: function(){
        var e = new Error(arguments);
        return e.stack.split('\n')[3].trim().split(' ')[1];
    },
    log: function(){
        duktapeLogger.info.apply(duktapeLogger,this._prepareArguments(arguments));
    },
    debug: function(){
        duktapeLogger.n = 'susi-js: '+this._getLine();
        duktapeLogger.debug.apply(duktapeLogger,this._prepareArguments(arguments));
        duktapeLogger.n = 'susi-js';
    },
    error: function(){
        duktapeLogger.n = 'susi-js: '+this._getLine();
        duktapeLogger.error.apply(duktapeLogger,this._prepareArguments(arguments));
        duktapeLogger.n = 'susi-js';
    }
};

)SUSIJS";
<commit_msg>[susi-duktape] fixed header location;<commit_after>#include "susi/DuktapeEngine.h"

std::string Susi::Duktape::susiJS = R"SUSIJS(

var susi = {
    _consumerCallbacks: [],
    _processorCallbacks: [],

    _processorTopicCounter: {},
    _consumerTopicCounter: {},

    _publishCallbacks: {},
    _processorProcesses: {},

    _processed: [],

    registerConsumer: function(topic,callback) {
        var id = this._genID();
        this._consumerCallbacks.push({topic: topic, callback: callback, id: id});
        var count = this._consumerTopicCounter[topic] || 0;
        count++;
        this._consumerTopicCounter[topic] = count;
        if(count == 1){
            _registerConsumer(topic);
        }
        return id;
    },

    registerProcessor: function(topic,callback) {
        var id = this._genID();
        this._processorCallbacks.push({topic: topic, callback: callback, id: id});
        var count = this._processorTopicCounter[topic] || 0;
        count++;
        this._processorTopicCounter[topic] = count;
        if(count == 1){
            _registerProcessor(topic);
        }
        return id;
    },

    unregisterConsumer: function(id){
        for(var i=0;i<this._consumerCallbacks;i++){
            if(this._consumerCallbacks[i].id === id){
                var topic = this._consumerCallbacks[i].topic;
                this._consumerCallbacks.splice(i,1);
                var count = this._consumerTopicCounter[topic];
                count--;
                if(count === 0){
                    delete(this._consumerTopicCounter[topic]);
                    _unregisterConsumer(topic);
                }else{
                    this._consumerTopicCounter[topic] = count;
                }
                return true;
            }
        }
        return false;
    },

    unregisterProcessor: function(id){
        for(var i=0;i<this._processorCallbacks;i++){
            if(this._processorCallbacks[i].id === id){
                var topic = this._processorCallbacks[i].topic;
                this._processorCallbacks.splice(i,1);
                var count = this._processorTopicCounter[topic];
                count--;
                if(count === 0){
                    delete(this._processorTopicCounter[topic]);
                    _unregisterProcessor(topic);
                }else{
                    this._processorTopicCounter[topic] = count;
                }
                return true;
            }
        }
        return false;
    },

    publish: function(event,callback) {
        if(event.id === undefined){
            event.id = ''+this._genID();
        }
        if(callback !== undefined) {
            this._publishCallbacks[event.id] = callback;
        }
        _publish(JSON.stringify(event));
    },

    ack: function(event){
        var process = this._processorProcesses[event.id];
        if(process.next >= process.processors.length){
            delete this._processorProcesses[event.id];
            _ack(JSON.stringify(event));
        }else{
            process.next++;
            process.processors[process.next-1](event);
        }
    },

    dismiss: function(event){
        delete(this._processorProcesses[event.id]);
        _dismiss(JSON.stringify(event));
    },

    //used by js to interact with c++ part
    _processConsumerEvent: function(event,topic){
        event = JSON.parse(event);
        for(var i=0;i<this._consumerCallbacks.length;i++){
            if(topic.match(this._consumerCallbacks[i].topic)){
                this._consumerCallbacks[i].callback(event);
            }
        }
    },

    _processProcessorEvent: function(event,topic){
        event = JSON.parse(event);
        if(this._processed.indexOf(event.id) !== -1){
            _ack(JSON.stringify(event));
            return;
        }
        this._processed.push(event.id);
        if(this._processed.length > 64){
            this._processed.splice(0,1);
        }
        Duktape.fin(event,function(event){
            susi.ack(event);
        });
        var process = {
            processors: [],
            next: 0
        };

        for (var i = 0; i<this._processorCallbacks.length; i++) {
            if(event.topic.match(this._processorCallbacks[i].topic)){
                process.processors.push(this._processorCallbacks[i].callback);
            }
        }

        this._processorProcesses[event.id] = process;
        this.ack(event);
        Duktape.gc();
    },

    _processAck: function(event){
        event = JSON.parse(event);
        var cb = this._publishCallbacks[event.id];
        if(cb !== undefined) {
            cb(event);
            delete this._publishCallbacks[event.id];
        }
    },

    _genID: function(){
        return Math.floor(Math.random()*1000000000000);
    }
};

//called by c++ part
function _processConsumerEvent(event,topic){
    susi._processConsumerEvent(event,topic);
}

function _processProcessorEvent(event,topic){
    susi._processProcessorEvent(event,topic)
}

function _processAck(event){
    susi._processAck(event);
}

var duktapeLogger = new Duktape.Logger('susi-js');
duktapeLogger.l = 0;

var console = {
    _prepareArguments: function(args){
        var newArgs = [];
        for(var i=0;i<args.length;i++){
            if(typeof args[i] === 'object'){
                newArgs.push(Duktape.enc('jx',args[i]));
            }else{
                newArgs.push(args[i]);
            }
        }
        return newArgs;
    },
    _getLine: function(){
        var e = new Error(arguments);
        return e.stack.split('\n')[3].trim().split(' ')[1];
    },
    log: function(){
        duktapeLogger.info.apply(duktapeLogger,this._prepareArguments(arguments));
    },
    debug: function(){
        duktapeLogger.n = 'susi-js: '+this._getLine();
        duktapeLogger.debug.apply(duktapeLogger,this._prepareArguments(arguments));
        duktapeLogger.n = 'susi-js';
    },
    error: function(){
        duktapeLogger.n = 'susi-js: '+this._getLine();
        duktapeLogger.error.apply(duktapeLogger,this._prepareArguments(arguments));
        duktapeLogger.n = 'susi-js';
    }
};

)SUSIJS";
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: textdoc.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 21:02:18 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _TEXTDOC_HXX
#define _TEXTDOC_HXX

#ifndef _SVARRAY_HXX
#include <svarray.hxx>
#endif

#ifndef _TEXTDATA_HXX
#include <textdata.hxx>
#endif

#ifndef _TXTATTR_HXX
#include <txtattr.hxx>
#endif

#include <tools/debug.hxx>

#ifndef _STRING_HXX //autogen
#include <tools/string.hxx>
#endif

#ifndef _LIST_HXX //autogen
#include <tools/list.hxx>
#endif

typedef TextCharAttrib* TextCharAttribPtr;
SV_DECL_PTRARR_DEL( TextCharAttribs, TextCharAttribPtr, 0, 4 )

class TextCharAttribList : private TextCharAttribs
{
private:
    BOOL            mbHasEmptyAttribs;

                    TextCharAttribList( const TextCharAttribList& ) : TextCharAttribs() {}

public:
                    TextCharAttribList();
                    ~TextCharAttribList();

    void            Clear( BOOL bDestroyAttribs );
    USHORT          Count() const               { return TextCharAttribs::Count(); }

    TextCharAttrib* GetAttrib( USHORT n ) const { return TextCharAttribs::GetObject( n ); }
    void            RemoveAttrib( USHORT n )    { TextCharAttribs::Remove( n, 1 ); }

    void            InsertAttrib( TextCharAttrib* pAttrib );

    void            DeleteEmptyAttribs();
    void            ResortAttribs();

    BOOL            HasEmptyAttribs() const { return mbHasEmptyAttribs; }
    BOOL&           HasEmptyAttribs()       { return mbHasEmptyAttribs; }

    TextCharAttrib* FindAttrib( USHORT nWhich, USHORT nPos );
    TextCharAttrib* FindNextAttrib( USHORT nWhich, USHORT nFromPos, USHORT nMaxPos = 0xFFFF ) const;
    TextCharAttrib* FindEmptyAttrib( USHORT nWhich, USHORT nPos );
    BOOL            HasAttrib( USHORT nWhich ) const;
    BOOL            HasBoundingAttrib( USHORT nBound );

#ifdef  DBG_UTIL
    BOOL            DbgCheckAttribs();
#endif
};

class TextNode
{
private:
    String              maText;
    TextCharAttribList  maCharAttribs;

                        TextNode( const TextNode& ) {;}
protected:
    void                ExpandAttribs( USHORT nIndex, USHORT nNewChars );
    void                CollapsAttribs( USHORT nIndex, USHORT nDelChars );

public:
                        TextNode( const String& rText );

    const String&               GetText() const         { return maText; }

    const TextCharAttribList&   GetCharAttribs() const  { return maCharAttribs; }
    TextCharAttribList&         GetCharAttribs()        { return maCharAttribs; }

    void                InsertText( USHORT nPos, const String& rText );
    void                InsertText( USHORT nPos, sal_Unicode c );
    void                RemoveText( USHORT nPos, USHORT nChars );

    TextNode*           Split( USHORT nPos, BOOL bKeepEndigAttribs );
    void                Append( const TextNode& rNode );
};

class TextDoc
{
private:
    ToolsList<TextNode*> maTextNodes;
    USHORT              mnLeftMargin;

protected:
    void                DestroyTextNodes();

public:
                        TextDoc();
                        ~TextDoc();

    void                Clear();

    ToolsList<TextNode*>&       GetNodes()              { return maTextNodes; }
    const ToolsList<TextNode*>& GetNodes() const        { return maTextNodes; }

    TextPaM             RemoveChars( const TextPaM& rPaM, USHORT nChars );
    TextPaM             InsertText( const TextPaM& rPaM, sal_Unicode c );
    TextPaM             InsertText( const TextPaM& rPaM, const String& rStr );

    TextPaM             InsertParaBreak( const TextPaM& rPaM, BOOL bKeepEndingAttribs );
    TextPaM             ConnectParagraphs( TextNode* pLeft, TextNode* pRight );

    ULONG               GetTextLen( const sal_Unicode* pSep, const TextSelection* pSel = NULL ) const;
    String              GetText( const sal_Unicode* pSep ) const;
    String              GetText( ULONG nPara ) const;

    void                SetLeftMargin( USHORT n )   { mnLeftMargin = n; }
    USHORT              GetLeftMargin() const       { return mnLeftMargin; }

//  BOOL                RemoveAttribs( TextNode* pNode, USHORT nStart, USHORT nEnd ), USHORT nWhich = 0 );
//  BOOL                RemoveAttribs( TextNode* pNode, USHORT nStart, USHORT nEnd, TextCharAttrib*& rpStarting, TextCharAttrib*& rpEnding, USHORT nWhich = 0 );
//  void                InsertAttrib( const EditCharAttrib* pAttr );
//  void                InsertAttribInSelection( const EditCharAttrib* pAttr );
//  void                FindAttribs( TextNode* pNode, USHORT nStartPos, USHORT nEndPos, SfxItemSet& rCurSet );

    BOOL                IsValidPaM( const TextPaM& rPaM );
};

#endif // _TEXTDOC_HXX
<commit_msg>INTEGRATION: CWS vgbugs07 (1.4.298); FILE MERGED 2007/06/04 13:31:35 vg 1.4.298.1: #i76605# Remove -I .../inc/module hack introduced by hedaburemove01<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: textdoc.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 21:31:18 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _TEXTDOC_HXX
#define _TEXTDOC_HXX

#ifndef _SVARRAY_HXX
#include <svtools/svarray.hxx>
#endif

#ifndef _TEXTDATA_HXX
#include <svtools/textdata.hxx>
#endif

#ifndef _TXTATTR_HXX
#include <txtattr.hxx>
#endif

#include <tools/debug.hxx>

#ifndef _STRING_HXX //autogen
#include <tools/string.hxx>
#endif

#ifndef _LIST_HXX //autogen
#include <tools/list.hxx>
#endif

typedef TextCharAttrib* TextCharAttribPtr;
SV_DECL_PTRARR_DEL( TextCharAttribs, TextCharAttribPtr, 0, 4 )

class TextCharAttribList : private TextCharAttribs
{
private:
    BOOL            mbHasEmptyAttribs;

                    TextCharAttribList( const TextCharAttribList& ) : TextCharAttribs() {}

public:
                    TextCharAttribList();
                    ~TextCharAttribList();

    void            Clear( BOOL bDestroyAttribs );
    USHORT          Count() const               { return TextCharAttribs::Count(); }

    TextCharAttrib* GetAttrib( USHORT n ) const { return TextCharAttribs::GetObject( n ); }
    void            RemoveAttrib( USHORT n )    { TextCharAttribs::Remove( n, 1 ); }

    void            InsertAttrib( TextCharAttrib* pAttrib );

    void            DeleteEmptyAttribs();
    void            ResortAttribs();

    BOOL            HasEmptyAttribs() const { return mbHasEmptyAttribs; }
    BOOL&           HasEmptyAttribs()       { return mbHasEmptyAttribs; }

    TextCharAttrib* FindAttrib( USHORT nWhich, USHORT nPos );
    TextCharAttrib* FindNextAttrib( USHORT nWhich, USHORT nFromPos, USHORT nMaxPos = 0xFFFF ) const;
    TextCharAttrib* FindEmptyAttrib( USHORT nWhich, USHORT nPos );
    BOOL            HasAttrib( USHORT nWhich ) const;
    BOOL            HasBoundingAttrib( USHORT nBound );

#ifdef  DBG_UTIL
    BOOL            DbgCheckAttribs();
#endif
};

class TextNode
{
private:
    String              maText;
    TextCharAttribList  maCharAttribs;

                        TextNode( const TextNode& ) {;}
protected:
    void                ExpandAttribs( USHORT nIndex, USHORT nNewChars );
    void                CollapsAttribs( USHORT nIndex, USHORT nDelChars );

public:
                        TextNode( const String& rText );

    const String&               GetText() const         { return maText; }

    const TextCharAttribList&   GetCharAttribs() const  { return maCharAttribs; }
    TextCharAttribList&         GetCharAttribs()        { return maCharAttribs; }

    void                InsertText( USHORT nPos, const String& rText );
    void                InsertText( USHORT nPos, sal_Unicode c );
    void                RemoveText( USHORT nPos, USHORT nChars );

    TextNode*           Split( USHORT nPos, BOOL bKeepEndigAttribs );
    void                Append( const TextNode& rNode );
};

class TextDoc
{
private:
    ToolsList<TextNode*> maTextNodes;
    USHORT              mnLeftMargin;

protected:
    void                DestroyTextNodes();

public:
                        TextDoc();
                        ~TextDoc();

    void                Clear();

    ToolsList<TextNode*>&       GetNodes()              { return maTextNodes; }
    const ToolsList<TextNode*>& GetNodes() const        { return maTextNodes; }

    TextPaM             RemoveChars( const TextPaM& rPaM, USHORT nChars );
    TextPaM             InsertText( const TextPaM& rPaM, sal_Unicode c );
    TextPaM             InsertText( const TextPaM& rPaM, const String& rStr );

    TextPaM             InsertParaBreak( const TextPaM& rPaM, BOOL bKeepEndingAttribs );
    TextPaM             ConnectParagraphs( TextNode* pLeft, TextNode* pRight );

    ULONG               GetTextLen( const sal_Unicode* pSep, const TextSelection* pSel = NULL ) const;
    String              GetText( const sal_Unicode* pSep ) const;
    String              GetText( ULONG nPara ) const;

    void                SetLeftMargin( USHORT n )   { mnLeftMargin = n; }
    USHORT              GetLeftMargin() const       { return mnLeftMargin; }

//  BOOL                RemoveAttribs( TextNode* pNode, USHORT nStart, USHORT nEnd ), USHORT nWhich = 0 );
//  BOOL                RemoveAttribs( TextNode* pNode, USHORT nStart, USHORT nEnd, TextCharAttrib*& rpStarting, TextCharAttrib*& rpEnding, USHORT nWhich = 0 );
//  void                InsertAttrib( const EditCharAttrib* pAttr );
//  void                InsertAttribInSelection( const EditCharAttrib* pAttr );
//  void                FindAttribs( TextNode* pNode, USHORT nStartPos, USHORT nEndPos, SfxItemSet& rCurSet );

    BOOL                IsValidPaM( const TextPaM& rPaM );
};

#endif // _TEXTDOC_HXX
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: rtfout.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2005-05-10 07:55:10 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef _STREAM_HXX
#include <tools/stream.hxx>
#endif
#ifndef _STRING_HXX
#include <tools/string.hxx>
#endif
#ifndef _RTL_STRING_HXX_
#include <rtl/string.hxx>
#endif
#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#ifndef _RTFKEYWD_HXX
#include <rtfkeywd.hxx>
#endif
#ifndef _RTFOUT_HXX
#include <rtfout.hxx>
#endif

using namespace rtl;

#if defined(MAC)
const sal_Char RTFOutFuncs::sNewLine = '\015';
#elif defined(UNX)
const sal_Char RTFOutFuncs::sNewLine = '\012';
#else
const sal_Char __FAR_DATA RTFOutFuncs::sNewLine[] = "\015\012";
#endif

SvStream& RTFOutFuncs::Out_Char(SvStream& rStream, sal_Unicode c,
    int *pUCMode, rtl_TextEncoding eDestEnc, BOOL bWriteHelpFile)
{
    const sal_Char* pStr = 0;
    switch (c)
    {
    case 0x1:
    case 0x2:
        // this are control character of our textattributes and will never be
        // written
        break;
    case 0xA0:
        rStream << "\\~";
        break;
    case 0xAD:
        rStream << "\\-";
        break;
    case 0x2011:
        rStream << "\\_";
        break;
    case '\n':
        pStr = sRTF_LINE;
        break;
    case '\t':
        pStr = sRTF_TAB;
        break;
    default:
        if(!bWriteHelpFile)
        {
            switch(c)
            {
                case 149:
                    pStr = sRTF_BULLET;
                    break;
                case 150:
                    pStr = sRTF_ENDASH;
                    break;
                case 151:
                    pStr = sRTF_EMDASH;
                    break;
                case 145:
                    pStr = sRTF_LQUOTE;
                    break;
                case 146:
                    pStr = sRTF_RQUOTE;
                    break;
                case 147:
                    pStr = sRTF_LDBLQUOTE;
                    break;
                case 148:
                    pStr = sRTF_RDBLQUOTE;
                    break;
            }

            if (pStr)
                break;
        }

        switch (c)
        {
            case '\\':
            case '}':
            case '{':
                rStream << '\\' << (sal_Char)c;
                break;
            default:
                if (c >= ' ' && c <= '~')
                    rStream << (sal_Char)c;
                else
                {
                    //If we can't convert to the dest encoding, or if
                    //its an uncommon multibyte sequence which most
                    //readers won't be able to handle correctly, then
                    //If we can't convert to the dest encoding, then
                    //export as unicode
                    OUString sBuf(&c, 1);
                    OString sConverted;
                    sal_uInt32 nFlags =
                        RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
                        RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR;
                    bool bWriteAsUnicode = !(sBuf.convertToString(&sConverted,
                                         eDestEnc, nFlags))
                                            || (RTL_TEXTENCODING_UTF8==eDestEnc); // #i43933# do not export UTF-8 chars in RTF;
                    if (bWriteAsUnicode)
                    {
                        sBuf.convertToString(&sConverted,
                            eDestEnc, OUSTRING_TO_OSTRING_CVTFLAGS);
                    }
                    const sal_Int32 nLen = sConverted.getLength();

                    if (bWriteAsUnicode && pUCMode)
                    {
                        // then write as unicode - character
                        if (*pUCMode != nLen)
                        {
                          rStream << "\\uc" << ByteString::CreateFromInt32(nLen).GetBuffer() << " "; // #i47831# add an additional whitespace, so that "document whitespaces" are not ignored.;
                            *pUCMode = nLen;
                        }
                        ByteString sNo(ByteString::CreateFromInt32(c));
                         rStream << "\\u" << sNo.GetBuffer();
                    }

                    for (sal_Int32 nI = 0; nI < nLen; ++nI)
                    {
                        rStream << "\\'";
                        Out_Hex(rStream, sConverted.getStr()[nI], 2);
                    }
                }
                break;
        }
        break;
    }

    if (pStr)
        rStream << pStr << ' ';

    return rStream;
}

SvStream& RTFOutFuncs::Out_String( SvStream& rStream, const String& rStr,
    rtl_TextEncoding eDestEnc, BOOL bWriteHelpFile)
{
    int nUCMode = 1;
    for (xub_StrLen n = 0; n < rStr.Len(); ++n)
        Out_Char(rStream, rStr.GetChar(n), &nUCMode, eDestEnc, bWriteHelpFile);
    if (nUCMode != 1)
      rStream << "\\uc1"<< " "; // #i47831# add an additional whitespace, so that "document whitespaces" are not ignored.;
    return rStream;
}

SvStream& RTFOutFuncs::Out_Fontname(SvStream& rStream, const String& rStr,
    rtl_TextEncoding eDestEnc, BOOL bWriteHelpFile)
{
    //Fontnames in word have a quirk in that \uc and usage of ansi replacement
    //chars after a \u don't work and in wordpad \u doesn't work, so we are
    //left with forcing ansi characters only for fontnames
    for (xub_StrLen n = 0; n < rStr.Len(); ++n)
        Out_Char(rStream, rStr.GetChar(n), 0, eDestEnc, bWriteHelpFile);
    return rStream;
}

SvStream& RTFOutFuncs::Out_Hex( SvStream& rStream, ULONG nHex, BYTE nLen )
{
    sal_Char aNToABuf[] = "0000000000000000";

    DBG_ASSERT( nLen < sizeof(aNToABuf), "zu viele Stellen" );
    if( nLen >= sizeof(aNToABuf) )
        nLen = (sizeof(aNToABuf)-1);

    // Pointer an das Bufferende setzen
    sal_Char* pStr = aNToABuf + (sizeof(aNToABuf)-1);
    for( BYTE n = 0; n < nLen; ++n )
    {
        *(--pStr) = (sal_Char)(nHex & 0xf ) + 48;
        if( *pStr > '9' )
            *pStr += 39;
        nHex >>= 4;
    }
    return rStream << pStr;
}

<commit_msg>INTEGRATION: CWS ooo19126 (1.7.114); FILE MERGED 2005/09/05 14:54:19 rt 1.7.114.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: rtfout.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 16:50:06 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef _STREAM_HXX
#include <tools/stream.hxx>
#endif
#ifndef _STRING_HXX
#include <tools/string.hxx>
#endif
#ifndef _RTL_STRING_HXX_
#include <rtl/string.hxx>
#endif
#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#ifndef _RTFKEYWD_HXX
#include <rtfkeywd.hxx>
#endif
#ifndef _RTFOUT_HXX
#include <rtfout.hxx>
#endif

using namespace rtl;

#if defined(MAC)
const sal_Char RTFOutFuncs::sNewLine = '\015';
#elif defined(UNX)
const sal_Char RTFOutFuncs::sNewLine = '\012';
#else
const sal_Char __FAR_DATA RTFOutFuncs::sNewLine[] = "\015\012";
#endif

SvStream& RTFOutFuncs::Out_Char(SvStream& rStream, sal_Unicode c,
    int *pUCMode, rtl_TextEncoding eDestEnc, BOOL bWriteHelpFile)
{
    const sal_Char* pStr = 0;
    switch (c)
    {
    case 0x1:
    case 0x2:
        // this are control character of our textattributes and will never be
        // written
        break;
    case 0xA0:
        rStream << "\\~";
        break;
    case 0xAD:
        rStream << "\\-";
        break;
    case 0x2011:
        rStream << "\\_";
        break;
    case '\n':
        pStr = sRTF_LINE;
        break;
    case '\t':
        pStr = sRTF_TAB;
        break;
    default:
        if(!bWriteHelpFile)
        {
            switch(c)
            {
                case 149:
                    pStr = sRTF_BULLET;
                    break;
                case 150:
                    pStr = sRTF_ENDASH;
                    break;
                case 151:
                    pStr = sRTF_EMDASH;
                    break;
                case 145:
                    pStr = sRTF_LQUOTE;
                    break;
                case 146:
                    pStr = sRTF_RQUOTE;
                    break;
                case 147:
                    pStr = sRTF_LDBLQUOTE;
                    break;
                case 148:
                    pStr = sRTF_RDBLQUOTE;
                    break;
            }

            if (pStr)
                break;
        }

        switch (c)
        {
            case '\\':
            case '}':
            case '{':
                rStream << '\\' << (sal_Char)c;
                break;
            default:
                if (c >= ' ' && c <= '~')
                    rStream << (sal_Char)c;
                else
                {
                    //If we can't convert to the dest encoding, or if
                    //its an uncommon multibyte sequence which most
                    //readers won't be able to handle correctly, then
                    //If we can't convert to the dest encoding, then
                    //export as unicode
                    OUString sBuf(&c, 1);
                    OString sConverted;
                    sal_uInt32 nFlags =
                        RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
                        RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR;
                    bool bWriteAsUnicode = !(sBuf.convertToString(&sConverted,
                                         eDestEnc, nFlags))
                                            || (RTL_TEXTENCODING_UTF8==eDestEnc); // #i43933# do not export UTF-8 chars in RTF;
                    if (bWriteAsUnicode)
                    {
                        sBuf.convertToString(&sConverted,
                            eDestEnc, OUSTRING_TO_OSTRING_CVTFLAGS);
                    }
                    const sal_Int32 nLen = sConverted.getLength();

                    if (bWriteAsUnicode && pUCMode)
                    {
                        // then write as unicode - character
                        if (*pUCMode != nLen)
                        {
                          rStream << "\\uc" << ByteString::CreateFromInt32(nLen).GetBuffer() << " "; // #i47831# add an additional whitespace, so that "document whitespaces" are not ignored.;
                            *pUCMode = nLen;
                        }
                        ByteString sNo(ByteString::CreateFromInt32(c));
                         rStream << "\\u" << sNo.GetBuffer();
                    }

                    for (sal_Int32 nI = 0; nI < nLen; ++nI)
                    {
                        rStream << "\\'";
                        Out_Hex(rStream, sConverted.getStr()[nI], 2);
                    }
                }
                break;
        }
        break;
    }

    if (pStr)
        rStream << pStr << ' ';

    return rStream;
}

SvStream& RTFOutFuncs::Out_String( SvStream& rStream, const String& rStr,
    rtl_TextEncoding eDestEnc, BOOL bWriteHelpFile)
{
    int nUCMode = 1;
    for (xub_StrLen n = 0; n < rStr.Len(); ++n)
        Out_Char(rStream, rStr.GetChar(n), &nUCMode, eDestEnc, bWriteHelpFile);
    if (nUCMode != 1)
      rStream << "\\uc1"<< " "; // #i47831# add an additional whitespace, so that "document whitespaces" are not ignored.;
    return rStream;
}

SvStream& RTFOutFuncs::Out_Fontname(SvStream& rStream, const String& rStr,
    rtl_TextEncoding eDestEnc, BOOL bWriteHelpFile)
{
    //Fontnames in word have a quirk in that \uc and usage of ansi replacement
    //chars after a \u don't work and in wordpad \u doesn't work, so we are
    //left with forcing ansi characters only for fontnames
    for (xub_StrLen n = 0; n < rStr.Len(); ++n)
        Out_Char(rStream, rStr.GetChar(n), 0, eDestEnc, bWriteHelpFile);
    return rStream;
}

SvStream& RTFOutFuncs::Out_Hex( SvStream& rStream, ULONG nHex, BYTE nLen )
{
    sal_Char aNToABuf[] = "0000000000000000";

    DBG_ASSERT( nLen < sizeof(aNToABuf), "zu viele Stellen" );
    if( nLen >= sizeof(aNToABuf) )
        nLen = (sizeof(aNToABuf)-1);

    // Pointer an das Bufferende setzen
    sal_Char* pStr = aNToABuf + (sizeof(aNToABuf)-1);
    for( BYTE n = 0; n < nLen; ++n )
    {
        *(--pStr) = (sal_Char)(nHex & 0xf ) + 48;
        if( *pStr > '9' )
            *pStr += 39;
        nHex >>= 4;
    }
    return rStream << pStr;
}

<|endoftext|>


<commit_before><commit_msg>when beforeFirst/afterLast, there is no value, so none to notify<commit_after><|endoftext|>


<commit_before>#include "playercontrols.h"

#include <QBoxLayout>
#include <QSlider>
#include <QStyle>
#include <QToolButton>
#include <QComboBox>

// constructor
PlayerControls::PlayerControls(QWidget *parent) :
    QWidget(parent),
    playerState(QMediaPlayer::StoppedState),
    playerMuted(false),
    playButton(NULL),
    stopButton(NULL),
    nextButton(NULL),
    previousButton(NULL),
    muteButton(NULL),
    volumeSlider(NULL),
    rateBox(NULL)
{
    playButton = new QToolButton(this);
    playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
    connect(playButton, SIGNAL(clicked()), this, SLOT(playClicked()));

    stopButton = new QToolButton(this);
    stopButton->setIcon(style()->standardIcon(QStyle::SP_MediaStop));
    stopButton->setEnabled(false);
    connect(stopButton, SIGNAL(clicked()), this, SIGNAL(stop()));

    nextButton = new QToolButton(this);
    nextButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipForward));
    connect(nextButton, SIGNAL(clicked()), this, SIGNAL(next()));

    previousButton = new QToolButton(this);
    previousButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipBackward));
    connect(previousButton, SIGNAL(clicked()), this, SIGNAL(previous()));

    muteButton = new QToolButton(this);
    muteButton->setIcon(style()->standardIcon(QStyle::SP_MediaVolume));
    connect(muteButton, SIGNAL(clicked()), this, SLOT(muteClicked()));

    volumeSlider = new QSlider(Qt::Horizontal, this);
    volumeSlider->setRange(0, 100);
    volumeSlider->setFixedSize(volumeSlider->sizeHint());
    connect(volumeSlider, SIGNAL(sliderMoved(int)), this, SIGNAL(changeVolume(int)));

    // playback rate box chooser
    /* Works like the following:
     * 1) whenver the box is "activiated" - user choosing something, call updateRate()
     * 2) updateRate() calls changeRate() on playbackRate();
     *      - playbackRate() is used to figure out which one is selected from the rateBox
     * 3) The changeRate() signal is caught by the setPlaybackRate() slot.
     * 4) The argment to setPlaybackRate() is the index of the item chosen. The slot then
     *    compares the index with the values in the box and set it.
     */
    rateBox = new QComboBox(this);
    rateBox->addItem("0.5x", QVariant(0.5));
    rateBox->addItem("1.0x", QVariant(1.0));
    rateBox->addItem("2.0x", QVariant(2.0));
    rateBox->setCurrentIndex(1);
    rateBox->setFixedSize(rateBox->sizeHint());
    connect(rateBox, SIGNAL(activated(int)), SLOT(updateRate()));

    // layout stuff
    QBoxLayout *layout = new QHBoxLayout;
    layout->setMargin(0);
    layout->addWidget(stopButton);
    layout->addWidget(previousButton);
    layout->addWidget(playButton);
    layout->addWidget(nextButton);
    layout->addWidget(muteButton);
    layout->addStretch();
    layout->setSpacing(0);

    QBoxLayout *rightEndLayout = new QHBoxLayout;
    rightEndLayout->setDirection(QBoxLayout::RightToLeft);
    rightEndLayout->addWidget(rateBox);
    rightEndLayout->addWidget(volumeSlider);

    layout->addLayout(rightEndLayout);
    setLayout(layout);
}

PlayerControls::~PlayerControls() {
    delete playButton;
    delete stopButton;
    delete nextButton;
    delete previousButton;
    delete muteButton;
    delete volumeSlider;
    delete rateBox;
}

QMediaPlayer::State PlayerControls::state() const {
    return playerState;
}

void PlayerControls::setState(QMediaPlayer::State state) {
    // change button styles on different states
    if (state != playerState) {
        playerState = state;

        switch(state) {
            case QMediaPlayer::StoppedState:
                stopButton->setEnabled(false);
                playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
                break;
            case QMediaPlayer::PlayingState:
                stopButton->setEnabled(true);
                playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause));
                break;
            case QMediaPlayer::PausedState:
                stopButton->setEnabled(true);
                playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
                break;
        }
    }
}

int PlayerControls::volume() const {
    return volumeSlider ? volumeSlider->value() : 0;
}

void PlayerControls::setVolume(int volume) {
    if (volumeSlider)
        volumeSlider->setValue(volume);
}

bool PlayerControls::isMuted() const {
    return playerMuted;
}

void PlayerControls::setMuted(bool muted) {
    if (muted != playerMuted) {
        playerMuted = muted;

        muteButton->setIcon(style()->standardIcon(muted ?
                    QStyle::SP_MediaVolumeMuted : QStyle::SP_MediaVolume));
    }
}

void PlayerControls::playClicked() {
    switch (playerState) {
        case QMediaPlayer::StoppedState:
        case QMediaPlayer::PausedState:
            emit play();
            break;
        case QMediaPlayer::PlayingState:
            emit pause();
            break;
    }
}

void PlayerControls::muteClicked() {
    emit changeMuting(!playerMuted);
}

qreal PlayerControls::playbackRate() const {
    return rateBox->itemData(rateBox->currentIndex()).toDouble();
}

void PlayerControls::setPlaybackRate(float rate) {
    for (int i=0; i<rateBox->count(); ++i) {
        if (qFuzzyCompare(rate, float(rateBox->itemData(i).toDouble()))) {
            rateBox->setCurrentIndex(i);
            return;
        }
    }

    rateBox->addItem(QString("%1x").arg(rate),QVariant(rate));
    rateBox->setCurrentIndex(rateBox->count() - 1);
}

void PlayerControls::updateRate() {
    emit changeRate(playbackRate());
}

<commit_msg>Adjusted volume control+rateBox spacing.<commit_after>#include "playercontrols.h"

#include <QBoxLayout>
#include <QSlider>
#include <QStyle>
#include <QToolButton>
#include <QComboBox>

// constructor
PlayerControls::PlayerControls(QWidget *parent) :
    QWidget(parent),
    playerState(QMediaPlayer::StoppedState),
    playerMuted(false),
    playButton(NULL),
    stopButton(NULL),
    nextButton(NULL),
    previousButton(NULL),
    muteButton(NULL),
    volumeSlider(NULL),
    rateBox(NULL)
{
    playButton = new QToolButton(this);
    playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
    connect(playButton, SIGNAL(clicked()), this, SLOT(playClicked()));

    stopButton = new QToolButton(this);
    stopButton->setIcon(style()->standardIcon(QStyle::SP_MediaStop));
    stopButton->setEnabled(false);
    connect(stopButton, SIGNAL(clicked()), this, SIGNAL(stop()));

    nextButton = new QToolButton(this);
    nextButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipForward));
    connect(nextButton, SIGNAL(clicked()), this, SIGNAL(next()));

    previousButton = new QToolButton(this);
    previousButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipBackward));
    connect(previousButton, SIGNAL(clicked()), this, SIGNAL(previous()));

    muteButton = new QToolButton(this);
    muteButton->setIcon(style()->standardIcon(QStyle::SP_MediaVolume));
    connect(muteButton, SIGNAL(clicked()), this, SLOT(muteClicked()));

    volumeSlider = new QSlider(Qt::Horizontal, this);
    volumeSlider->setRange(0, 100);
    volumeSlider->setFixedSize(volumeSlider->sizeHint());
    connect(volumeSlider, SIGNAL(sliderMoved(int)), this, SIGNAL(changeVolume(int)));

    // playback rate box chooser
    /* Works like the following:
     * 1) whenver the box is "activiated" - user choosing something, call updateRate()
     * 2) updateRate() calls changeRate() on playbackRate();
     *      - playbackRate() is used to figure out which one is selected from the rateBox
     * 3) The changeRate() signal is caught by the setPlaybackRate() slot.
     * 4) The argment to setPlaybackRate() is the index of the item chosen. The slot then
     *    compares the index with the values in the box and set it.
     */
    rateBox = new QComboBox(this);
    rateBox->addItem("0.5x", QVariant(0.5));
    rateBox->addItem("1.0x", QVariant(1.0));
    rateBox->addItem("2.0x", QVariant(2.0));
    rateBox->setCurrentIndex(1);
    rateBox->setFixedSize(rateBox->sizeHint());
    connect(rateBox, SIGNAL(activated(int)), SLOT(updateRate()));

    // layout stuff
    QBoxLayout *layout = new QHBoxLayout;
    layout->setMargin(0);
    layout->addWidget(stopButton);
    layout->addWidget(previousButton);
    layout->addWidget(playButton);
    layout->addWidget(nextButton);
    layout->addStretch();
    layout->setSpacing(0);

    QBoxLayout *rightEndLayout = new QHBoxLayout;
    rightEndLayout->setDirection(QBoxLayout::RightToLeft);
    rightEndLayout->addWidget(rateBox);
    rightEndLayout->setSpacing(2);
    rightEndLayout->addWidget(volumeSlider);
    rightEndLayout->addWidget(muteButton);

    layout->addLayout(rightEndLayout);
    setLayout(layout);
}

PlayerControls::~PlayerControls() {
    delete playButton;
    delete stopButton;
    delete nextButton;
    delete previousButton;
    delete muteButton;
    delete volumeSlider;
    delete rateBox;
}

QMediaPlayer::State PlayerControls::state() const {
    return playerState;
}

void PlayerControls::setState(QMediaPlayer::State state) {
    // change button styles on different states
    if (state != playerState) {
        playerState = state;

        switch(state) {
            case QMediaPlayer::StoppedState:
                stopButton->setEnabled(false);
                playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
                break;
            case QMediaPlayer::PlayingState:
                stopButton->setEnabled(true);
                playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause));
                break;
            case QMediaPlayer::PausedState:
                stopButton->setEnabled(true);
                playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
                break;
        }
    }
}

int PlayerControls::volume() const {
    return volumeSlider ? volumeSlider->value() : 0;
}

void PlayerControls::setVolume(int volume) {
    if (volumeSlider)
        volumeSlider->setValue(volume);
}

bool PlayerControls::isMuted() const {
    return playerMuted;
}

void PlayerControls::setMuted(bool muted) {
    if (muted != playerMuted) {
        playerMuted = muted;

        muteButton->setIcon(style()->standardIcon(muted ?
                    QStyle::SP_MediaVolumeMuted : QStyle::SP_MediaVolume));
    }
}

void PlayerControls::playClicked() {
    switch (playerState) {
        case QMediaPlayer::StoppedState:
        case QMediaPlayer::PausedState:
            emit play();
            break;
        case QMediaPlayer::PlayingState:
            emit pause();
            break;
    }
}

void PlayerControls::muteClicked() {
    emit changeMuting(!playerMuted);
}

qreal PlayerControls::playbackRate() const {
    return rateBox->itemData(rateBox->currentIndex()).toDouble();
}

void PlayerControls::setPlaybackRate(float rate) {
    for (int i=0; i<rateBox->count(); ++i) {
        if (qFuzzyCompare(rate, float(rateBox->itemData(i).toDouble()))) {
            rateBox->setCurrentIndex(i);
            return;
        }
    }

    rateBox->addItem(QString("%1x").arg(rate),QVariant(rate));
    rateBox->setCurrentIndex(rateBox->count() - 1);
}

void PlayerControls::updateRate() {
    emit changeRate(playbackRate());
}

<|endoftext|>


<commit_before>#include <phypp.hpp>

int main(int argc, char* argv[]) {
    if (argc < 2) {
        print("usage: make_skymaker gencat.fits band=... maglim=... out=...");
        return 1;
    }

    std::string band;
    std::string out_file;
    double maglim = dnan;
    double aspix = 0.06;

    read_args(argc-1, argv+1, arg_list(band, name(out_file, "out"), maglim, aspix));

    struct {
        vec1d ra, dec;

        vec1f disk_angle,  disk_radius,  disk_ratio;
        vec1f bulge_angle, bulge_radius, bulge_ratio;

        vec2f flux_disk, flux_bulge;
        vec1s bands;
    } cat;

    fits::read_table(argv[1], cat);

    vec1u idb = where(cat.bands == band);
    if (idb.empty()) {
        error("no band named '", band, "' in this catalog");
        return 1;
    } else if (idb.size() > 1) {
        error("multiple bands named '", band, "' in this catalog");
        return 1;
    }

    uint_t b = idb[0];

    vec1f mag = uJy2mag(cat.flux_disk(_,b)+cat.flux_bulge(_,b));
    vec1f bt = cat.flux_bulge(_,b)/(cat.flux_disk(_,b)+cat.flux_bulge(_,b));

    fits::make_wcs_header_params wcs_params;
    wcs_params.pixel_scale = aspix;
    wcs_params.pixel_ref_x = 0.0; wcs_params.pixel_ref_y = 0.0;
    wcs_params.sky_ref_ra = max(cat.ra); wcs_params.sky_ref_dec = min(cat.dec);
    move_ra_dec(wcs_params.sky_ref_ra, wcs_params.sky_ref_dec, +5.0, -5.0);

    fits::header hdr;
    if (!fits::make_wcs_header(wcs_params, hdr)) {
        error("could not make WCS header");
        return 1;
    }

    vec1d x, y;
    fits::ad2xy(fits::wcs(hdr), cat.ra, cat.dec, x, y);

    vec1u ids;
    if (finite(maglim)) {
        ids = where(mag < maglim);
        if (ids.empty()) {
            error("no source brighter than ", maglim);
            note("maximum magnitude is ", max(mag));
            return 1;
        }
    } else {
        ids = uindgen(x.size());
        vec1u idbad = where(!finite(mag));
        mag[idbad] = 99;
    }

    if (out_file.empty()) {
        out_file = erase_end(argv[1], ".fits")+"-"+band+".cat";
    }

    file::mkdir(file::get_directory(out_file));

    file::write_table_hdr(out_file, 16,
        {"type", "x", "y", "mag", "bt",
        "bulge_radius", "bulge_ratio", "bulge_angle",
        "disk_radius", "disk_ratio", "disk_angle"},
        replicate(200u, ids.size()), x[ids], y[ids],
        mag[ids], bt[ids],
        cat.bulge_radius[ids], cat.bulge_ratio[ids], cat.bulge_angle[ids],
        cat.disk_radius[ids], cat.disk_ratio[ids], cat.disk_angle[ids]
    );

    // Write FITS header to a file
    {
        std::ofstream ohdr(erase_end(out_file, ".cat")+"-hdr.txt");
        vec1s shdr = cut(hdr, 80);
        for (auto& s : shdr) {
            ohdr << s << "\n";
        }
    }

    return 0;
}
<commit_msg>Removed use reflection feature in make_skymaker<commit_after>#include <phypp.hpp>

int main(int argc, char* argv[]) {
    if (argc < 2) {
        print("usage: make_skymaker gencat.fits band=... maglim=... out=...");
        return 1;
    }

    std::string band;
    std::string out_file;
    double maglim = dnan;
    double aspix = 0.06;

    read_args(argc-1, argv+1, arg_list(band, name(out_file, "out"), maglim, aspix));

    struct {
        vec1d ra, dec;

        vec1f disk_angle,  disk_radius,  disk_ratio;
        vec1f bulge_angle, bulge_radius, bulge_ratio;

        vec2f flux_disk, flux_bulge;
        vec1s bands;
    } cat;

    fits::read_table(argv[1], ftable(
        cat.ra, cat.dec,
        cat.disk_angle, cat.disk_radius, cat.disk_ratio,
        cat.bulge_angle, cat.bulge_radius, cat.bulge_ratio,
        cat.flux_disk, cat.flux_bulge, cat.bands
    ));

    vec1u idb = where(cat.bands == band);
    if (idb.empty()) {
        error("no band named '", band, "' in this catalog");
        return 1;
    } else if (idb.size() > 1) {
        error("multiple bands named '", band, "' in this catalog");
        return 1;
    }

    uint_t b = idb[0];

    vec1f mag = uJy2mag(cat.flux_disk(_,b)+cat.flux_bulge(_,b));
    vec1f bt = cat.flux_bulge(_,b)/(cat.flux_disk(_,b)+cat.flux_bulge(_,b));

    fits::make_wcs_header_params wcs_params;
    wcs_params.pixel_scale = aspix;
    wcs_params.pixel_ref_x = 0.0; wcs_params.pixel_ref_y = 0.0;
    wcs_params.sky_ref_ra = max(cat.ra); wcs_params.sky_ref_dec = min(cat.dec);
    move_ra_dec(wcs_params.sky_ref_ra, wcs_params.sky_ref_dec, +5.0, -5.0);

    fits::header hdr;
    if (!fits::make_wcs_header(wcs_params, hdr)) {
        error("could not make WCS header");
        return 1;
    }

    vec1d x, y;
    fits::ad2xy(fits::wcs(hdr), cat.ra, cat.dec, x, y);

    vec1u ids;
    if (finite(maglim)) {
        ids = where(mag < maglim);
        if (ids.empty()) {
            error("no source brighter than ", maglim);
            note("maximum magnitude is ", max(mag));
            return 1;
        }
    } else {
        ids = uindgen(x.size());
        vec1u idbad = where(!finite(mag));
        mag[idbad] = 99;
    }

    if (out_file.empty()) {
        out_file = erase_end(argv[1], ".fits")+"-"+band+".cat";
    }

    file::mkdir(file::get_directory(out_file));

    file::write_table_hdr(out_file, 16,
        {"type", "x", "y", "mag", "bt",
        "bulge_radius", "bulge_ratio", "bulge_angle",
        "disk_radius", "disk_ratio", "disk_angle"},
        replicate(200u, ids.size()), x[ids], y[ids],
        mag[ids], bt[ids],
        cat.bulge_radius[ids], cat.bulge_ratio[ids], cat.bulge_angle[ids],
        cat.disk_radius[ids], cat.disk_ratio[ids], cat.disk_angle[ids]
    );

    // Write FITS header to a file
    {
        std::ofstream ohdr(erase_end(out_file, ".cat")+"-hdr.txt");
        vec1s shdr = cut(hdr, 80);
        for (auto& s : shdr) {
            ohdr << s << "\n";
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: svdomedia.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: pjunck $ $Date: 2004-11-03 11:00:50 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "svdomedia.hxx"
#include "svdglob.hxx"
#include "svdstr.hrc"

#ifndef _SDR_CONTACT_VIEWCONTACTOFSDRMEDIAOBJ_HXX
#include <svx/sdr/contact/viewcontactofsdrmediaobj.hxx>
#endif

// ---------------
// - SdrMediaObj -
// ---------------

TYPEINIT1( SdrMediaObj, SdrRectObj );

// ------------------------------------------------------------------------------

SdrMediaObj::SdrMediaObj()
{
}

// ------------------------------------------------------------------------------

SdrMediaObj::SdrMediaObj( const Rectangle& rRect ) :
    SdrRectObj( rRect )
{
}

// ------------------------------------------------------------------------------

SdrMediaObj::~SdrMediaObj()
{
}

// ------------------------------------------------------------------------------

FASTBOOL SdrMediaObj::HasTextEdit() const
{
    return FALSE;
}

// ------------------------------------------------------------------------------

sdr::contact::ViewContact* SdrMediaObj::CreateObjectSpecificViewContact()
{
    return new ::sdr::contact::ViewContactOfSdrMediaObj( *this );
}

// ------------------------------------------------------------------------------

void SdrMediaObj::TakeObjInfo( SdrObjTransformInfoRec& rInfo ) const
{
    rInfo.bSelectAllowed = true;
    rInfo.bMoveAllowed = true;
    rInfo.bResizeFreeAllowed = true;
    rInfo.bResizePropAllowed = true;
    rInfo.bRotateFreeAllowed = false;
    rInfo.bRotate90Allowed = false;
    rInfo.bMirrorFreeAllowed = false;
    rInfo.bMirror45Allowed = false;
    rInfo.bMirror90Allowed = false;
    rInfo.bTransparenceAllowed = false;
    rInfo.bGradientAllowed = false;
    rInfo.bShearAllowed = false;
    rInfo.bEdgeRadiusAllowed = false;
    rInfo.bNoOrthoDesired = false;
    rInfo.bNoContortion = false;
    rInfo.bCanConvToPath = false;
    rInfo.bCanConvToPoly = false;
    rInfo.bCanConvToContour = false;
    rInfo.bCanConvToPathLineToArea = false;
    rInfo.bCanConvToPolyLineToArea = false;
}

// ------------------------------------------------------------------------------

UINT16 SdrMediaObj::GetObjIdentifier() const
{
    return UINT16( OBJ_MEDIA );
}

// ------------------------------------------------------------------------------

sal_Bool SdrMediaObj::DoPaintObject(XOutputDevice& rXOut, const SdrPaintInfoRec& rInfoRec) const
{
    return true;
}

// ------------------------------------------------------------------------------

void SdrMediaObj::TakeObjNameSingul(XubString& rName) const
{
    rName=ImpGetResStr(STR_ObjNameSingulMEDIA);

    String aName( GetName() );

    if(aName.Len())
    {
        rName += sal_Unicode(' ');
        rName += sal_Unicode('\'');
        rName += aName;
        rName += sal_Unicode('\'');
    }
}

// ------------------------------------------------------------------------------

void SdrMediaObj::TakeObjNamePlural(XubString& rName) const
{
    rName=ImpGetResStr(STR_ObjNamePluralMEDIA);
}

// ------------------------------------------------------------------------------

void SdrMediaObj::operator=(const SdrObject& rObj)
{
    SdrRectObj::operator=( rObj );

    if( rObj.ISA( SdrMediaObj ) )
        setMediaProperties( static_cast< const SdrMediaObj& >( rObj ).getMediaProperties() );
}

// ------------------------------------------------------------------------------

void SdrMediaObj::setURL( const ::rtl::OUString& rURL )
{
    ::avmedia::MediaItem aURLItem;

    aURLItem.setURL( rURL );
    setMediaProperties( aURLItem );
}

// ------------------------------------------------------------------------------

const ::rtl::OUString& SdrMediaObj::getURL() const
{
    return getMediaProperties().getURL();
}

// ------------------------------------------------------------------------------

void SdrMediaObj::setMediaProperties( const ::avmedia::MediaItem& rState )
{
    mediaPropertiesChanged( rState );
    static_cast< ::sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).executeMediaItem( getMediaProperties() );
}

// ------------------------------------------------------------------------------

const ::avmedia::MediaItem& SdrMediaObj::getMediaProperties() const
{
    return maMediaProperties;
}

// ------------------------------------------------------------------------------

bool SdrMediaObj::hasPreferredSize() const
{
    return static_cast< ::sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).hasPreferredSize();
}

// ------------------------------------------------------------------------------

Size SdrMediaObj::getPreferredSize() const
{
    return static_cast< ::sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).getPreferredSize();
}

// ------------------------------------------------------------------------------

void SdrMediaObj::mediaPropertiesChanged( const ::avmedia::MediaItem& rNewProperties )
{
    const sal_uInt32 nMaskSet = rNewProperties.getMaskSet();

    // use only a subset of MediaItem properties for own own properties
    if( AVMEDIA_SETMASK_URL & nMaskSet )
        maMediaProperties.setURL( rNewProperties.getURL() );

    if( AVMEDIA_SETMASK_LOOP & nMaskSet )
        maMediaProperties.setLoop( rNewProperties.isLoop() );

    if( AVMEDIA_SETMASK_MUTE & nMaskSet )
        maMediaProperties.setMute( rNewProperties.isMute() );

    if( AVMEDIA_SETMASK_VOLUMEDB & nMaskSet )
        maMediaProperties.setVolumeDB( rNewProperties.getVolumeDB() );

    if( AVMEDIA_SETMASK_ZOOM & nMaskSet )
        maMediaProperties.setZoom( rNewProperties.getZoom() );
}
<commit_msg>INTEGRATION: CWS jmf5 (1.3.130); FILE MERGED 2005/01/21 14:31:24 ka 1.3.130.1: #i37255#: use FrameGrabber<commit_after>/*************************************************************************
 *
 *  $RCSfile: svdomedia.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: vg $ $Date: 2005-03-23 12:42:54 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "svdomedia.hxx"
#include "svdglob.hxx"
#include "svdstr.hrc"

#ifndef _SDR_CONTACT_VIEWCONTACTOFSDRMEDIAOBJ_HXX
#include <svx/sdr/contact/viewcontactofsdrmediaobj.hxx>
#endif
#ifndef _AVMEDIA_MEDIAWINDOW_HXX
#include <avmedia/mediawindow.hxx>
#endif

// ---------------
// - SdrMediaObj -
// ---------------

TYPEINIT1( SdrMediaObj, SdrRectObj );

// ------------------------------------------------------------------------------

SdrMediaObj::SdrMediaObj()
{
}

// ------------------------------------------------------------------------------

SdrMediaObj::SdrMediaObj( const Rectangle& rRect ) :
    SdrRectObj( rRect )
{
}

// ------------------------------------------------------------------------------

SdrMediaObj::~SdrMediaObj()
{
}

// ------------------------------------------------------------------------------

FASTBOOL SdrMediaObj::HasTextEdit() const
{
    return FALSE;
}

// ------------------------------------------------------------------------------

sdr::contact::ViewContact* SdrMediaObj::CreateObjectSpecificViewContact()
{
    return new ::sdr::contact::ViewContactOfSdrMediaObj( *this );
}

// ------------------------------------------------------------------------------

void SdrMediaObj::TakeObjInfo( SdrObjTransformInfoRec& rInfo ) const
{
    rInfo.bSelectAllowed = true;
    rInfo.bMoveAllowed = true;
    rInfo.bResizeFreeAllowed = true;
    rInfo.bResizePropAllowed = true;
    rInfo.bRotateFreeAllowed = false;
    rInfo.bRotate90Allowed = false;
    rInfo.bMirrorFreeAllowed = false;
    rInfo.bMirror45Allowed = false;
    rInfo.bMirror90Allowed = false;
    rInfo.bTransparenceAllowed = false;
    rInfo.bGradientAllowed = false;
    rInfo.bShearAllowed = false;
    rInfo.bEdgeRadiusAllowed = false;
    rInfo.bNoOrthoDesired = false;
    rInfo.bNoContortion = false;
    rInfo.bCanConvToPath = false;
    rInfo.bCanConvToPoly = false;
    rInfo.bCanConvToContour = false;
    rInfo.bCanConvToPathLineToArea = false;
    rInfo.bCanConvToPolyLineToArea = false;
}

// ------------------------------------------------------------------------------

UINT16 SdrMediaObj::GetObjIdentifier() const
{
    return UINT16( OBJ_MEDIA );
}

// ------------------------------------------------------------------------------

sal_Bool SdrMediaObj::DoPaintObject(XOutputDevice& rXOut, const SdrPaintInfoRec& rInfoRec) const
{
    return true;
}

// ------------------------------------------------------------------------------

void SdrMediaObj::TakeObjNameSingul(XubString& rName) const
{
    rName=ImpGetResStr(STR_ObjNameSingulMEDIA);

    String aName( GetName() );

    if(aName.Len())
    {
        rName += sal_Unicode(' ');
        rName += sal_Unicode('\'');
        rName += aName;
        rName += sal_Unicode('\'');
    }
}

// ------------------------------------------------------------------------------

void SdrMediaObj::TakeObjNamePlural(XubString& rName) const
{
    rName=ImpGetResStr(STR_ObjNamePluralMEDIA);
}

// ------------------------------------------------------------------------------

void SdrMediaObj::operator=(const SdrObject& rObj)
{
    SdrRectObj::operator=( rObj );

    if( rObj.ISA( SdrMediaObj ) )
    {
        const SdrMediaObj& rMediaObj = static_cast< const SdrMediaObj& >( rObj );

        setMediaProperties( rMediaObj.getMediaProperties() );
        setGraphic( rMediaObj.mapGraphic.get() );
    }
}

// ------------------------------------------------------------------------------

void SdrMediaObj::setURL( const ::rtl::OUString& rURL )
{
    ::avmedia::MediaItem aURLItem;

    aURLItem.setURL( rURL );
    setMediaProperties( aURLItem );
}

// ------------------------------------------------------------------------------

const ::rtl::OUString& SdrMediaObj::getURL() const
{
    return getMediaProperties().getURL();
}

// ------------------------------------------------------------------------------

void SdrMediaObj::setMediaProperties( const ::avmedia::MediaItem& rState )
{
    mediaPropertiesChanged( rState );
    static_cast< ::sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).executeMediaItem( getMediaProperties() );
}

// ------------------------------------------------------------------------------

const ::avmedia::MediaItem& SdrMediaObj::getMediaProperties() const
{
    return maMediaProperties;
}

// ------------------------------------------------------------------------------

bool SdrMediaObj::hasPreferredSize() const
{
    return static_cast< ::sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).hasPreferredSize();
}

// ------------------------------------------------------------------------------

Size SdrMediaObj::getPreferredSize() const
{
    return static_cast< ::sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).getPreferredSize();
}

// ------------------------------------------------------------------------------

const Graphic& SdrMediaObj::getGraphic() const
{
    if( !mapGraphic.get() )
        const_cast< SdrMediaObj* >( this )->mapGraphic.reset( new Graphic( ::avmedia::MediaWindow::grabFrame( getURL(), true ) ) );

    return *mapGraphic;
}

// ------------------------------------------------------------------------------

void SdrMediaObj::setGraphic( const Graphic* pGraphic )
{
    mapGraphic.reset( pGraphic ? new Graphic( *pGraphic ) : NULL );
}

// ------------------------------------------------------------------------------

void SdrMediaObj::mediaPropertiesChanged( const ::avmedia::MediaItem& rNewProperties )
{
    const sal_uInt32 nMaskSet = rNewProperties.getMaskSet();

    // use only a subset of MediaItem properties for own own properties
    if( ( AVMEDIA_SETMASK_URL & nMaskSet ) &&
        ( rNewProperties.getURL() != getURL() ) )
    {
        setGraphic();
        maMediaProperties.setURL( rNewProperties.getURL() );
    }

    if( AVMEDIA_SETMASK_LOOP & nMaskSet )
        maMediaProperties.setLoop( rNewProperties.isLoop() );

    if( AVMEDIA_SETMASK_MUTE & nMaskSet )
        maMediaProperties.setMute( rNewProperties.isMute() );

    if( AVMEDIA_SETMASK_VOLUMEDB & nMaskSet )
        maMediaProperties.setVolumeDB( rNewProperties.getVolumeDB() );

    if( AVMEDIA_SETMASK_ZOOM & nMaskSet )
        maMediaProperties.setZoom( rNewProperties.getZoom() );
}
<|endoftext|>


<commit_before>/*
 * Copyright 2007-2019 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "FifoBufferIstream.hxx"
#include "Bucket.hxx"
#include "fb_pool.hxx"

#include <string.h>

size_t
FifoBufferIstream::Push(ConstBuffer<void> src) noexcept
{
	buffer.AllocateIfNull(fb_pool_get());

	auto w = buffer.Write();
	size_t nbytes = std::min(w.size, src.size);
	memcpy(w.data, src.data, nbytes);
	buffer.Append(nbytes);
	return nbytes;
}

void
FifoBufferIstream::SetEof() noexcept
{
	eof = true;
	SubmitBuffer();
}

void
FifoBufferIstream::SubmitBuffer() noexcept
{
	while (!buffer.empty()) {
		size_t nbytes = SendFromBuffer(buffer);
		if (nbytes == 0)
			return;

		handler.OnFifoBufferIstreamConsumed(nbytes);

		if (buffer.empty() && !eof)
			handler.OnFifoBufferIstreamDrained();
	}

	if (buffer.empty()) {
		if (eof)
			DestroyEof();
		else
			buffer.FreeIfDefined();
	}
}

off_t
FifoBufferIstream::_Skip(off_t length) noexcept
{
	size_t nbytes = std::min<decltype(length)>(length, buffer.GetAvailable());
	buffer.Consume(nbytes);
	buffer.FreeIfEmpty();
	Consumed(nbytes);
	handler.OnFifoBufferIstreamConsumed(nbytes);
	return nbytes;
}

void
FifoBufferIstream::_Read() noexcept
{
	SubmitBuffer();
}

void
FifoBufferIstream::_FillBucketList(IstreamBucketList &list) noexcept
{
	auto r = buffer.Read();
	if (!r.empty())
		list.Push(r.ToVoid());

	if (!eof)
		list.SetMore();
}

size_t
FifoBufferIstream::_ConsumeBucketList(size_t nbytes) noexcept
{
	size_t consumed = std::min(nbytes, buffer.GetAvailable());
	buffer.Consume(consumed);
	Consumed(nbytes);
	handler.OnFifoBufferIstreamConsumed(consumed);

	if (consumed > 0 && buffer.empty() && !eof) {
		handler.OnFifoBufferIstreamDrained();

		if (buffer.empty())
			buffer.Free();
	}

	return nbytes - consumed;
}
<commit_msg>istream/FifoBufferIstream: add missing `eof` checks before invoking handler<commit_after>/*
 * Copyright 2007-2019 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "FifoBufferIstream.hxx"
#include "Bucket.hxx"
#include "fb_pool.hxx"

#include <string.h>

size_t
FifoBufferIstream::Push(ConstBuffer<void> src) noexcept
{
	buffer.AllocateIfNull(fb_pool_get());

	auto w = buffer.Write();
	size_t nbytes = std::min(w.size, src.size);
	memcpy(w.data, src.data, nbytes);
	buffer.Append(nbytes);
	return nbytes;
}

void
FifoBufferIstream::SetEof() noexcept
{
	eof = true;
	SubmitBuffer();
}

void
FifoBufferIstream::SubmitBuffer() noexcept
{
	while (!buffer.empty()) {
		size_t nbytes = SendFromBuffer(buffer);
		if (nbytes == 0)
			return;

		if (!eof) {
			handler.OnFifoBufferIstreamConsumed(nbytes);
			if (buffer.empty())
				handler.OnFifoBufferIstreamDrained();
		}
	}

	if (buffer.empty()) {
		if (eof)
			DestroyEof();
		else
			buffer.FreeIfDefined();
	}
}

off_t
FifoBufferIstream::_Skip(off_t length) noexcept
{
	size_t nbytes = std::min<decltype(length)>(length, buffer.GetAvailable());
	buffer.Consume(nbytes);
	buffer.FreeIfEmpty();
	Consumed(nbytes);

	if (nbytes > 0 && !eof) {
		handler.OnFifoBufferIstreamConsumed(nbytes);
		if (buffer.empty())
			handler.OnFifoBufferIstreamDrained();
	}

	return nbytes;
}

void
FifoBufferIstream::_Read() noexcept
{
	SubmitBuffer();
}

void
FifoBufferIstream::_FillBucketList(IstreamBucketList &list) noexcept
{
	auto r = buffer.Read();
	if (!r.empty())
		list.Push(r.ToVoid());

	if (!eof)
		list.SetMore();
}

size_t
FifoBufferIstream::_ConsumeBucketList(size_t nbytes) noexcept
{
	size_t consumed = std::min(nbytes, buffer.GetAvailable());
	buffer.Consume(consumed);
	Consumed(consumed);

	if (consumed > 0 && !eof) {
		handler.OnFifoBufferIstreamConsumed(consumed);
		if (buffer.empty())
			handler.OnFifoBufferIstreamDrained();

		if (buffer.empty())
			buffer.Free();
	}

	return nbytes - consumed;
}
<|endoftext|>