<commit_before>/*
 * Copyright (C) 2012, British Broadcasting Corporation
 * All Rights Reserved.
 *
 * Author: Philip de Nier
 *
 * 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.
 *     * Neither the name of the British Broadcasting Corporation nor the names
 *       of its contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * 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 COPYRIGHT OWNER 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.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#define __STDC_LIMIT_MACROS

#include <cstring>

#include <bmx/wave/WaveWriter.h>
#include <bmx/Utils.h>
#include <bmx/BMXException.h>
#include <bmx/Logging.h>

using namespace std;
using namespace bmx;

// prevent buffer size exceeding 50MB
#define MAX_BUFFER_SIZE     (50 * 1000 * 1000)

WaveWriter::WaveWriter(WaveIO *output, bool take_ownership)
{
    mOutput = output;
    mOwnOutput = take_ownership;
    mStartTimecodeSet = false;
    mSetSampleCount = -1;
    mBEXT = new WaveBEXT();
    mSamplingRate = SAMPLING_RATE_48K;
    mSamplingRateSet = false;
    mQuantizationBits = 16;
    mQuantizationBitsSet = false;
    mChannelCount = 0;
    mChannelBlockAlign = (mQuantizationBits + 7) / 8;
    mBlockAlign = 0;
    mBufferSize = 0;
    mSampleCount = 0;
    mJunkChunkFilePosition = 0;
    mBEXTFilePosition = 0;
    mDataChunkFilePosition = 0;
    mFactChunkFilePosition = 0;
    mUseRF64 = false;
    mSetSize = -1;
    mSetDataSize = -1;
}

WaveWriter::~WaveWriter()
{
    delete mBEXT;
    if (mOwnOutput)
        delete mOutput;

    size_t i;
    for (i = 0; i < mBufferSegments.size(); i++)
        delete mBufferSegments[i];

    for (i = 0; i < mTracks.size(); i++)
        delete mTracks[i];
}

void WaveWriter::SetStartTimecode(Timecode start_timecode)
{
    mStartTimecode = start_timecode;
    mStartTimecodeSet = true;
}

void WaveWriter::SetSampleCount(int64_t count)
{
    mSetSampleCount = count;
}

WaveTrackWriter* WaveWriter::CreateTrack()
{
    mTracks.push_back(new WaveTrackWriter(this, (uint32_t)mTracks.size()));
    return mTracks.back();
}

void WaveWriter::PrepareWrite()
{
    size_t i;
    for (i = 0; i < mTracks.size(); i++) {
        mTracks[i]->mStartChannel = mChannelCount;
        mChannelCount += mTracks[i]->mChannelCount;
    }
    mBlockAlign = mChannelBlockAlign * mChannelCount;

    if (mStartTimecodeSet) {
        mBEXT->SetTimeReference(convert_position(mStartTimecode.GetOffset(),
                                                 mSamplingRate.numerator,
                                                 mStartTimecode.GetRoundedTCBase(),
                                                 ROUND_AUTO));
    }

    if (mSetSampleCount >= 0) {
        mSetDataSize = mSetSampleCount * mBlockAlign;
        mSetSize = 4 + (8 + 28) + (8 + mBEXT->GetSize()) + (8 + 16) + (8 + 4) + (8 + mSetDataSize);
        if (mSetSize > UINT32_MAX)
            mUseRF64 = true;
    }

    if (mUseRF64) {
        mOutput->WriteTag("RF64");
        mOutput->WriteSize(-1);
    } else {
        mOutput->WriteTag("RIFF");
        if (mSetSize >= 0)
            mOutput->WriteSize(mSetSize);
        else
            mOutput->WriteSize(0);
    }
    mOutput->WriteTag("WAVE");

    mJunkChunkFilePosition = mOutput->Tell();
    if (mUseRF64) {
        mOutput->WriteTag("ds64");
        mOutput->WriteSize(28);
        mOutput->WriteUInt64((uint64_t)mSetSize);
        mOutput->WriteUInt64((uint64_t)mSetDataSize);
        mOutput->WriteUInt64((uint64_t)mSetSampleCount);
        mOutput->WriteUInt32(0);
    } else {
        mOutput->WriteTag("JUNK");
        mOutput->WriteSize(28);
        mOutput->WriteZeros(28);
    }

    mBEXTFilePosition = mOutput->Tell();
    mBEXT->Write(mOutput);

    mOutput->WriteTag("fmt ");
    mOutput->WriteSize(16);
    mOutput->WriteUInt16(1); // PCM
    mOutput->WriteUInt16(mChannelCount);
    mOutput->WriteUInt32(mSamplingRate.numerator);
    mOutput->WriteUInt32(mBlockAlign * mSamplingRate.numerator); // bytes per second
    mOutput->WriteUInt16(mBlockAlign);
    mOutput->WriteUInt16(mQuantizationBits);

    mFactChunkFilePosition = mOutput->Tell();
    mOutput->WriteTag("fact");
    mOutput->WriteSize(4);
    if (mSetSampleCount >= 0)
        mOutput->WriteUInt32(mSetSampleCount);
    else
        mOutput->WriteUInt32(0);

    mDataChunkFilePosition = mOutput->Tell();
    mOutput->WriteTag("data");
    if (mUseRF64)
        mOutput->WriteSize(-1);
    else if (mSetDataSize >= 0)
        mOutput->WriteSize(mSetDataSize);
    else
        mOutput->WriteSize(0);
}

void WaveWriter::WriteSamples(uint32_t track_index, const unsigned char *data, uint32_t size, uint32_t num_samples)
{
    if (size == 0)
        return;

    WaveTrackWriter *track = GetTrack(track_index);
    uint16_t track_block_align = track->mChannelCount * mChannelBlockAlign;
    BMX_CHECK(size >= num_samples * track_block_align);

    uint32_t input_sample_count = 0;
    uint32_t output_sample_count = 0;

    if (mTracks.size() == 1) {
        // no buffering required
        mOutput->Write(data, num_samples * track_block_align);
        input_sample_count = num_samples;
        output_sample_count = num_samples;
    } else {
        // need to buffer
        BufferSegment *segment;
        size_t segment_index;
        uint32_t segment_offset;
        if (track->mSampleCount == mSampleCount) {
            // create new segment
            BMX_CHECK(mBufferSize < MAX_BUFFER_SIZE);
            mBufferSegments.push_back(new BufferSegment);
            segment = mBufferSegments.back();
            segment->start_sample_count = mSampleCount;
            segment->num_samples = num_samples;
            segment->channel_count = 0;
            segment->data.Allocate(mBlockAlign * num_samples);
            segment->data.SetSize(mBlockAlign * num_samples);
            memset(segment->data.GetBytes(), 0, segment->data.GetSize());

            mBufferSize += mBlockAlign * num_samples;
            segment_index = 0;
            segment_offset = 0;
            input_sample_count = num_samples;
            output_sample_count = num_samples;
        } else {
            // get existing segment
            BMX_ASSERT(!mBufferSegments.empty());
            for (segment_index = 0; segment_index < mBufferSegments.size() - 1; segment_index++) {
                if (track->mSampleCount < mBufferSegments[segment_index + 1]->start_sample_count)
                    break;
            }
            segment = mBufferSegments[segment_index];
            segment_offset = (uint32_t)(track->mSampleCount - segment->start_sample_count);
            input_sample_count = segment->num_samples - segment_offset;
            if (input_sample_count > num_samples)
                input_sample_count = num_samples;
        }

        // copy samples to segment
        unsigned char *output_ptr = segment->data.GetBytes() + segment_offset * mBlockAlign +
                                    track->mStartChannel * mChannelBlockAlign;
        const unsigned char *input_ptr = data;
        uint32_t i;
        for (i = 0; i < input_sample_count; i++) {
            memcpy(output_ptr, input_ptr, track_block_align);
            output_ptr += mBlockAlign;
            input_ptr += track_block_align;
        }
        if (segment_offset + input_sample_count == segment->num_samples)
            segment->channel_count += track->mChannelCount;

        // write complete buffer segments
        if (segment_index == 0 && segment->channel_count == mChannelCount) {
            mOutput->Write(segment->data.GetBytes(), segment->data.GetSize());
            mBufferSize -= segment->data.GetSize();
            delete segment;
            mBufferSegments.pop_front();
        }
    }

    track->mSampleCount += input_sample_count;
    mSampleCount += output_sample_count;

    if (input_sample_count < num_samples) {
        WriteSamples(track_index, data + input_sample_count * track_block_align,
                     (num_samples - input_sample_count) * track_block_align,
                     num_samples - input_sample_count);
    }
}

void WaveWriter::CompleteWrite()
{
    // write remaining buffered samples
    if (!mBufferSegments.empty()) {
        log_warn("Wave tracks with unequal duration\n");

        size_t i;
        for (i = 0; i < mBufferSegments.size(); i++) {
            mOutput->Write(mBufferSegments[i]->data.GetBytes(), mBufferSegments[i]->data.GetSize());
            mBufferSize -= mBufferSegments[i]->data.GetSize();
            delete mBufferSegments[i];
        }
        mBufferSegments.clear();
    }

    if (mStartTimecodeSet) {
        mBEXT->SetTimeReference(convert_position(mStartTimecode.GetOffset(),
                                                 mSamplingRate.numerator,
                                                 mStartTimecode.GetRoundedTCBase(),
                                                 ROUND_AUTO));
    }

    int64_t riff_size = mOutput->Size() - 8;
    int64_t data_size = riff_size - mDataChunkFilePosition;

    // add pad byte if data size is odd
    if ((data_size & 1))
        mOutput->PutChar(0);

    if (mUseRF64 || riff_size > UINT32_MAX) {
        if (!mUseRF64) {
            mOutput->Seek(mDataChunkFilePosition + 4, SEEK_SET);
            mOutput->WriteSize((uint32_t)(-1));

            mOutput->Seek(mFactChunkFilePosition + 8, SEEK_SET);
            mOutput->WriteUInt32((uint32_t)(-1));
        }

        if (mBEXT->WasUpdated()) {
            mOutput->Seek(mBEXTFilePosition, SEEK_SET);
            mBEXT->Write(mOutput);
        }

        if (!mUseRF64 || riff_size != mSetSize || mSampleCount != mSetSampleCount) {
            mOutput->Seek(mJunkChunkFilePosition, SEEK_SET);
            mOutput->WriteTag("ds64");
            mOutput->WriteSize(28);
            mOutput->WriteUInt64((uint64_t)riff_size);
            mOutput->WriteUInt64((uint64_t)data_size);
            mOutput->WriteUInt64((uint64_t)mSampleCount);
            mOutput->WriteUInt32(0);
        }

        if (!mUseRF64) {
            mOutput->Seek(0, SEEK_SET);
            mOutput->WriteTag("RF64");
            mOutput->WriteSize((uint32_t)(-1));
        }
    } else {
        if (riff_size != mSetSize) {
            mOutput->Seek(mDataChunkFilePosition + 4, SEEK_SET);
            mOutput->WriteSize((uint32_t)data_size);
        }

        if (mSampleCount != mSetSampleCount) {
            mOutput->Seek(mFactChunkFilePosition + 8, SEEK_SET);
            mOutput->WriteUInt32((uint32_t)mSampleCount);
        }

        if (mBEXT->WasUpdated()) {
            mOutput->Seek(mBEXTFilePosition, SEEK_SET);
            mBEXT->Write(mOutput);
        }

        if (riff_size != mSetSize) {
            mOutput->Seek(4, SEEK_SET);
            mOutput->WriteSize((uint32_t)riff_size);
        }
    }
}

WaveTrackWriter* WaveWriter::GetTrack(uint32_t track_index)
{
    BMX_CHECK(track_index < mTracks.size());
    return mTracks[track_index];
}

void WaveWriter::SetSamplingRate(Rational sampling_rate)
{
    BMX_CHECK(sampling_rate.denominator == 1);
    BMX_CHECK_M(!mSamplingRateSet || sampling_rate == mSamplingRate,
                ("Variable sampling rate not supported in wave writer"));

    mSamplingRate = sampling_rate;
    mSamplingRateSet = true;
}

void WaveWriter::SetQuantizationBits(uint16_t bits)
{
    BMX_CHECK(bits > 0 && bits <= 32);
    BMX_CHECK_M(!mQuantizationBitsSet || bits == mQuantizationBits,
                ("Variable quantization bits not supported in wave writer"));

    mQuantizationBits = bits;
    mQuantizationBitsSet = true;

    mChannelBlockAlign = (mQuantizationBits + 7) / 8;
}

<commit_msg>wave: explicit casts for msvc<commit_after>/*
 * Copyright (C) 2012, British Broadcasting Corporation
 * All Rights Reserved.
 *
 * Author: Philip de Nier
 *
 * 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.
 *     * Neither the name of the British Broadcasting Corporation nor the names
 *       of its contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * 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 COPYRIGHT OWNER 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.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#define __STDC_LIMIT_MACROS

#include <cstring>

#include <bmx/wave/WaveWriter.h>
#include <bmx/Utils.h>
#include <bmx/BMXException.h>
#include <bmx/Logging.h>

using namespace std;
using namespace bmx;

// prevent buffer size exceeding 50MB
#define MAX_BUFFER_SIZE     (50 * 1000 * 1000)

WaveWriter::WaveWriter(WaveIO *output, bool take_ownership)
{
    mOutput = output;
    mOwnOutput = take_ownership;
    mStartTimecodeSet = false;
    mSetSampleCount = -1;
    mBEXT = new WaveBEXT();
    mSamplingRate = SAMPLING_RATE_48K;
    mSamplingRateSet = false;
    mQuantizationBits = 16;
    mQuantizationBitsSet = false;
    mChannelCount = 0;
    mChannelBlockAlign = (mQuantizationBits + 7) / 8;
    mBlockAlign = 0;
    mBufferSize = 0;
    mSampleCount = 0;
    mJunkChunkFilePosition = 0;
    mBEXTFilePosition = 0;
    mDataChunkFilePosition = 0;
    mFactChunkFilePosition = 0;
    mUseRF64 = false;
    mSetSize = -1;
    mSetDataSize = -1;
}

WaveWriter::~WaveWriter()
{
    delete mBEXT;
    if (mOwnOutput)
        delete mOutput;

    size_t i;
    for (i = 0; i < mBufferSegments.size(); i++)
        delete mBufferSegments[i];

    for (i = 0; i < mTracks.size(); i++)
        delete mTracks[i];
}

void WaveWriter::SetStartTimecode(Timecode start_timecode)
{
    mStartTimecode = start_timecode;
    mStartTimecodeSet = true;
}

void WaveWriter::SetSampleCount(int64_t count)
{
    mSetSampleCount = count;
}

WaveTrackWriter* WaveWriter::CreateTrack()
{
    mTracks.push_back(new WaveTrackWriter(this, (uint32_t)mTracks.size()));
    return mTracks.back();
}

void WaveWriter::PrepareWrite()
{
    size_t i;
    for (i = 0; i < mTracks.size(); i++) {
        mTracks[i]->mStartChannel = mChannelCount;
        mChannelCount += mTracks[i]->mChannelCount;
    }
    mBlockAlign = mChannelBlockAlign * mChannelCount;

    if (mStartTimecodeSet) {
        mBEXT->SetTimeReference(convert_position(mStartTimecode.GetOffset(),
                                                 mSamplingRate.numerator,
                                                 mStartTimecode.GetRoundedTCBase(),
                                                 ROUND_AUTO));
    }

    if (mSetSampleCount >= 0) {
        mSetDataSize = mSetSampleCount * mBlockAlign;
        mSetSize = 4 + (8 + 28) + (8 + mBEXT->GetSize()) + (8 + 16) + (8 + 4) + (8 + mSetDataSize);
        if (mSetSize > UINT32_MAX)
            mUseRF64 = true;
    }

    if (mUseRF64) {
        mOutput->WriteTag("RF64");
        mOutput->WriteSize(-1);
    } else {
        mOutput->WriteTag("RIFF");
        if (mSetSize >= 0)
            mOutput->WriteSize((uint32_t)mSetSize);
        else
            mOutput->WriteSize(0);
    }
    mOutput->WriteTag("WAVE");

    mJunkChunkFilePosition = mOutput->Tell();
    if (mUseRF64) {
        mOutput->WriteTag("ds64");
        mOutput->WriteSize(28);
        mOutput->WriteUInt64((uint64_t)mSetSize);
        mOutput->WriteUInt64((uint64_t)mSetDataSize);
        mOutput->WriteUInt64((uint64_t)mSetSampleCount);
        mOutput->WriteUInt32(0);
    } else {
        mOutput->WriteTag("JUNK");
        mOutput->WriteSize(28);
        mOutput->WriteZeros(28);
    }

    mBEXTFilePosition = mOutput->Tell();
    mBEXT->Write(mOutput);

    mOutput->WriteTag("fmt ");
    mOutput->WriteSize(16);
    mOutput->WriteUInt16(1); // PCM
    mOutput->WriteUInt16(mChannelCount);
    mOutput->WriteUInt32(mSamplingRate.numerator);
    mOutput->WriteUInt32(mBlockAlign * mSamplingRate.numerator); // bytes per second
    mOutput->WriteUInt16(mBlockAlign);
    mOutput->WriteUInt16(mQuantizationBits);

    mFactChunkFilePosition = mOutput->Tell();
    mOutput->WriteTag("fact");
    mOutput->WriteSize(4);
    if (mSetSampleCount >= 0)
        mOutput->WriteUInt32((uint32_t)mSetSampleCount);
    else
        mOutput->WriteUInt32(0);

    mDataChunkFilePosition = mOutput->Tell();
    mOutput->WriteTag("data");
    if (mUseRF64)
        mOutput->WriteSize(-1);
    else if (mSetDataSize >= 0)
        mOutput->WriteSize((uint32_t)mSetDataSize);
    else
        mOutput->WriteSize(0);
}

void WaveWriter::WriteSamples(uint32_t track_index, const unsigned char *data, uint32_t size, uint32_t num_samples)
{
    if (size == 0)
        return;

    WaveTrackWriter *track = GetTrack(track_index);
    uint16_t track_block_align = track->mChannelCount * mChannelBlockAlign;
    BMX_CHECK(size >= num_samples * track_block_align);

    uint32_t input_sample_count = 0;
    uint32_t output_sample_count = 0;

    if (mTracks.size() == 1) {
        // no buffering required
        mOutput->Write(data, num_samples * track_block_align);
        input_sample_count = num_samples;
        output_sample_count = num_samples;
    } else {
        // need to buffer
        BufferSegment *segment;
        size_t segment_index;
        uint32_t segment_offset;
        if (track->mSampleCount == mSampleCount) {
            // create new segment
            BMX_CHECK(mBufferSize < MAX_BUFFER_SIZE);
            mBufferSegments.push_back(new BufferSegment);
            segment = mBufferSegments.back();
            segment->start_sample_count = mSampleCount;
            segment->num_samples = num_samples;
            segment->channel_count = 0;
            segment->data.Allocate(mBlockAlign * num_samples);
            segment->data.SetSize(mBlockAlign * num_samples);
            memset(segment->data.GetBytes(), 0, segment->data.GetSize());

            mBufferSize += mBlockAlign * num_samples;
            segment_index = 0;
            segment_offset = 0;
            input_sample_count = num_samples;
            output_sample_count = num_samples;
        } else {
            // get existing segment
            BMX_ASSERT(!mBufferSegments.empty());
            for (segment_index = 0; segment_index < mBufferSegments.size() - 1; segment_index++) {
                if (track->mSampleCount < mBufferSegments[segment_index + 1]->start_sample_count)
                    break;
            }
            segment = mBufferSegments[segment_index];
            segment_offset = (uint32_t)(track->mSampleCount - segment->start_sample_count);
            input_sample_count = segment->num_samples - segment_offset;
            if (input_sample_count > num_samples)
                input_sample_count = num_samples;
        }

        // copy samples to segment
        unsigned char *output_ptr = segment->data.GetBytes() + segment_offset * mBlockAlign +
                                    track->mStartChannel * mChannelBlockAlign;
        const unsigned char *input_ptr = data;
        uint32_t i;
        for (i = 0; i < input_sample_count; i++) {
            memcpy(output_ptr, input_ptr, track_block_align);
            output_ptr += mBlockAlign;
            input_ptr += track_block_align;
        }
        if (segment_offset + input_sample_count == segment->num_samples)
            segment->channel_count += track->mChannelCount;

        // write complete buffer segments
        if (segment_index == 0 && segment->channel_count == mChannelCount) {
            mOutput->Write(segment->data.GetBytes(), segment->data.GetSize());
            mBufferSize -= segment->data.GetSize();
            delete segment;
            mBufferSegments.pop_front();
        }
    }

    track->mSampleCount += input_sample_count;
    mSampleCount += output_sample_count;

    if (input_sample_count < num_samples) {
        WriteSamples(track_index, data + input_sample_count * track_block_align,
                     (num_samples - input_sample_count) * track_block_align,
                     num_samples - input_sample_count);
    }
}

void WaveWriter::CompleteWrite()
{
    // write remaining buffered samples
    if (!mBufferSegments.empty()) {
        log_warn("Wave tracks with unequal duration\n");

        size_t i;
        for (i = 0; i < mBufferSegments.size(); i++) {
            mOutput->Write(mBufferSegments[i]->data.GetBytes(), mBufferSegments[i]->data.GetSize());
            mBufferSize -= mBufferSegments[i]->data.GetSize();
            delete mBufferSegments[i];
        }
        mBufferSegments.clear();
    }

    if (mStartTimecodeSet) {
        mBEXT->SetTimeReference(convert_position(mStartTimecode.GetOffset(),
                                                 mSamplingRate.numerator,
                                                 mStartTimecode.GetRoundedTCBase(),
                                                 ROUND_AUTO));
    }

    int64_t riff_size = mOutput->Size() - 8;
    int64_t data_size = riff_size - mDataChunkFilePosition;

    // add pad byte if data size is odd
    if ((data_size & 1))
        mOutput->PutChar(0);

    if (mUseRF64 || riff_size > UINT32_MAX) {
        if (!mUseRF64) {
            mOutput->Seek(mDataChunkFilePosition + 4, SEEK_SET);
            mOutput->WriteSize((uint32_t)(-1));

            mOutput->Seek(mFactChunkFilePosition + 8, SEEK_SET);
            mOutput->WriteUInt32((uint32_t)(-1));
        }

        if (mBEXT->WasUpdated()) {
            mOutput->Seek(mBEXTFilePosition, SEEK_SET);
            mBEXT->Write(mOutput);
        }

        if (!mUseRF64 || riff_size != mSetSize || mSampleCount != mSetSampleCount) {
            mOutput->Seek(mJunkChunkFilePosition, SEEK_SET);
            mOutput->WriteTag("ds64");
            mOutput->WriteSize(28);
            mOutput->WriteUInt64((uint64_t)riff_size);
            mOutput->WriteUInt64((uint64_t)data_size);
            mOutput->WriteUInt64((uint64_t)mSampleCount);
            mOutput->WriteUInt32(0);
        }

        if (!mUseRF64) {
            mOutput->Seek(0, SEEK_SET);
            mOutput->WriteTag("RF64");
            mOutput->WriteSize((uint32_t)(-1));
        }
    } else {
        if (riff_size != mSetSize) {
            mOutput->Seek(mDataChunkFilePosition + 4, SEEK_SET);
            mOutput->WriteSize((uint32_t)data_size);
        }

        if (mSampleCount != mSetSampleCount) {
            mOutput->Seek(mFactChunkFilePosition + 8, SEEK_SET);
            mOutput->WriteUInt32((uint32_t)mSampleCount);
        }

        if (mBEXT->WasUpdated()) {
            mOutput->Seek(mBEXTFilePosition, SEEK_SET);
            mBEXT->Write(mOutput);
        }

        if (riff_size != mSetSize) {
            mOutput->Seek(4, SEEK_SET);
            mOutput->WriteSize((uint32_t)riff_size);
        }
    }
}

WaveTrackWriter* WaveWriter::GetTrack(uint32_t track_index)
{
    BMX_CHECK(track_index < mTracks.size());
    return mTracks[track_index];
}

void WaveWriter::SetSamplingRate(Rational sampling_rate)
{
    BMX_CHECK(sampling_rate.denominator == 1);
    BMX_CHECK_M(!mSamplingRateSet || sampling_rate == mSamplingRate,
                ("Variable sampling rate not supported in wave writer"));

    mSamplingRate = sampling_rate;
    mSamplingRateSet = true;
}

void WaveWriter::SetQuantizationBits(uint16_t bits)
{
    BMX_CHECK(bits > 0 && bits <= 32);
    BMX_CHECK_M(!mQuantizationBitsSet || bits == mQuantizationBits,
                ("Variable quantization bits not supported in wave writer"));

    mQuantizationBits = bits;
    mQuantizationBitsSet = true;

    mChannelBlockAlign = (mQuantizationBits + 7) / 8;
}

<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
//$Id$

// boost
#include <boost/python.hpp>
#include <boost/python/def.hpp>
#include <boost/python/exception_translator.hpp>
#include <boost/python/manage_new_object.hpp>
// mapnik
#include <mapnik/geometry.hpp>
#include <mapnik/wkt/wkt_factory.hpp>

namespace {

using mapnik::from_wkt;
using mapnik::geometry_type;

geometry_type * make_from_wkt(std::string const& wkt)
{
    std::pair<bool,geometry_type*> result = from_wkt(wkt);
    if (result.first)
    {
        return result.second;
    }
    throw std::runtime_error("Failed to parse WKT");
}

}

void export_geometry()
{
    using namespace boost::python;

    enum_<mapnik::eGeomType>("GeometryType")
        .value("Point",mapnik::Point)
        .value("LineString",mapnik::LineString)
        .value("Polygon",mapnik::Polygon)
        .value("MultiPoint",mapnik::MultiPoint)
        .value("MultiLineString",mapnik::MultiLineString)
        .value("MultiPolygon",mapnik::MultiPolygon)
        ;

    using mapnik::geometry_type;
    class_<geometry_type, std::auto_ptr<geometry_type>,boost::noncopyable>("Geometry2d",no_init)
        // factory method
        .def("from_wkt",make_from_wkt,return_value_policy<manage_new_object>())
        .staticmethod("from_wkt")
        .def("envelope",&geometry_type::envelope)
        // .def("__str__",&geometry_type::to_string)
        .def("type",&geometry_type::type)
        // TODO add other geometry_type methods
        ;
}
<commit_msg>+ reflect 'area' method<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
//$Id$

// boost
#include <boost/python.hpp>
#include <boost/python/def.hpp>
#include <boost/python/exception_translator.hpp>
#include <boost/python/manage_new_object.hpp>
// mapnik
#include <mapnik/geometry.hpp>
#include <mapnik/wkt/wkt_factory.hpp>

namespace {

using mapnik::from_wkt;
using mapnik::geometry_type;

geometry_type * make_from_wkt(std::string const& wkt)
{
    std::pair<bool,geometry_type*> result = from_wkt(wkt);
    if (result.first)
    {
        return result.second;
    }
    throw std::runtime_error("Failed to parse WKT");
}

}

void export_geometry()
{
    using namespace boost::python;

    enum_<mapnik::eGeomType>("GeometryType")
        .value("Point",mapnik::Point)
        .value("LineString",mapnik::LineString)
        .value("Polygon",mapnik::Polygon)
        .value("MultiPoint",mapnik::MultiPoint)
        .value("MultiLineString",mapnik::MultiLineString)
        .value("MultiPolygon",mapnik::MultiPolygon)
        ;

    using mapnik::geometry_type;
    class_<geometry_type, std::auto_ptr<geometry_type>,boost::noncopyable>("Geometry2d",no_init)
        // factory method
        .def("from_wkt",make_from_wkt,return_value_policy<manage_new_object>())
        .staticmethod("from_wkt")
        .def("envelope",&geometry_type::envelope)
        // .def("__str__",&geometry_type::to_string)
        .def("type",&geometry_type::type)
        .def("area",&geometry_type::area)
        // TODO add other geometry_type methods
        ;
}
<|endoftext|>


<commit_before>/*      _______   __   __   __   ______   __   __   _______   __   __
 *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
 *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
 *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
 *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
 *
 * Copyright (c) 2004, 2005 darkbits                        Js_./
 * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
 * Olof Naessn a.k.a jansem/yakslem                _asww7!uY`>  )\a//
 *                                                 _Qhm`] _f "'c  1!5m
 * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
 *                                               .)j(] .d_/ '-(  P .   S
 * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
 * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
 * binary forms, with or without                 )4d[#7r, .   '     )d`)[
 * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
 * that the following conditions are met:       j<<WP+k/);.        _W=j f
 * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
 *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
 *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
 *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
 * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
 *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
 *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
 *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
 *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
 *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
 * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
 *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
 *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
 *    from this software without specific        (js, \[QQW$QWW#?!V"".
 *    prior written permission.                    ]y:.<\..          .
 *                                                 -]n w/ '         [.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
 * 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.
 */

/*
 * For comments regarding functions please see the header file.
 */

#include "guichan/widgets/listbox.hpp"

#include "guichan/basiccontainer.hpp"
#include "guichan/font.hpp"
#include "guichan/graphics.hpp"
#include "guichan/key.hpp"
#include "guichan/listmodel.hpp"
#include "guichan/mouseinput.hpp"

namespace gcn
{
    ListBox::ListBox()
    {
        mSelected = -1;
        mListModel = NULL;
        setWidth(100);
        setFocusable(true);

        addMouseListener(this);
        addKeyListener(this);
    }

    ListBox::ListBox(ListModel *listModel)
    {
        mSelected = -1;
        setWidth(100);
        setListModel(listModel);
        setFocusable(true);

        addMouseListener(this);
        addKeyListener(this);
    }

    void ListBox::draw(Graphics* graphics)
    {
        graphics->setColor(getBackgroundColor());
        graphics->fillRectangle(Rectangle(0, 0, getWidth(), getHeight()));

        if (mListModel == NULL)
        {
            return;
        }

        graphics->setColor(getForegroundColor());
        graphics->setFont(getFont());

        int i, fontHeight;
        int y = 0;

        fontHeight = getFont()->getHeight();

        /**
         * @todo Check cliprects so we do not have to iterate over elements in the list model
         */
        for (i = 0; i < mListModel->getNumberOfElements(); ++i)
        {
            if (i == mSelected)
            {
                graphics->drawRectangle(Rectangle(0, y, getWidth(), fontHeight));
            }

            graphics->drawText(mListModel->getElementAt(i), 1, y);

            y += fontHeight;
        }
    }

    void ListBox::drawBorder(Graphics* graphics)
    {
        Color faceColor = getBaseColor();
        Color highlightColor, shadowColor;
        int alpha = getBaseColor().a;
        int width = getWidth() + getBorderSize() * 2 - 1;
        int height = getHeight() + getBorderSize() * 2 - 1;
        highlightColor = faceColor + 0x303030;
        highlightColor.a = alpha;
        shadowColor = faceColor - 0x303030;
        shadowColor.a = alpha;

        unsigned int i;
        for (i = 0; i < getBorderSize(); ++i)
        {
            graphics->setColor(shadowColor);
            graphics->drawLine(i,i, width - i, i);
            graphics->drawLine(i,i + 1, i, height - i - 1);
            graphics->setColor(highlightColor);
            graphics->drawLine(width - i,i + 1, width - i, height - i);
            graphics->drawLine(i,height - i, width - i - 1, height - i);
        }
    }

    void ListBox::logic()
    {
        adjustSize();
    }

    int ListBox::getSelected()
    {
        return mSelected;
    }

    void ListBox::setSelected(int selected)
    {
        if (mListModel == NULL)
        {
            mSelected = -1;
        }
        else
        {
            if (selected < 0)
            {
                mSelected = -1;
            }
            else if (selected >= mListModel->getNumberOfElements())
            {
                mSelected = mListModel->getNumberOfElements() - 1;
            }
            else
            {
                mSelected = selected;
            }

            BasicContainer *par = getParent();
            if (par == NULL)
            {
                return;
            }

            Rectangle scroll;

            if (mSelected < 0)
            {
                scroll.y = 0;
            }
            else
            {
                scroll.y = getFont()->getHeight() * mSelected;
            }

            scroll.y = getFont()->getHeight() * mSelected;
            scroll.height = getFont()->getHeight();
            par->showWidgetPart(this, scroll);
        }
    }

    void ListBox::keyPress(const Key& key)
    {
        if (key.getValue() == Key::ENTER || key.getValue() == Key::SPACE)
        {
            generateAction();
        }
        else if (key.getValue() == Key::UP)
        {
            setSelected(mSelected - 1);

            if (mSelected == -1)
            {
                setSelected(0);
            }
        }
        else if (key.getValue() == Key::DOWN)
        {
            setSelected(mSelected + 1);
        }
    }

    void ListBox::mousePress(int x, int y, int button)
    {
        if (button == MouseInput::LEFT && hasMouse())
        {
            setSelected(y / getFont()->getHeight());
            generateAction();
        }
    }

    void ListBox::setListModel(ListModel *listModel)
    {
        mSelected = -1;
        mListModel = listModel;
        adjustSize();
    }

    ListModel* ListBox::getListModel()
    {
        return mListModel;
    }

    void ListBox::adjustSize()
    {
        if (mListModel != NULL)
        {
            setHeight(getFont()->getHeight() * mListModel->getNumberOfElements());
        }
    }
}
<commit_msg>Ability to wrap keyboard selection has been added.<commit_after>/*      _______   __   __   __   ______   __   __   _______   __   __
 *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
 *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
 *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
 *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
 *
 * Copyright (c) 2004, 2005 darkbits                        Js_./
 * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
 * Olof Naessn a.k.a jansem/yakslem                _asww7!uY`>  )\a//
 *                                                 _Qhm`] _f "'c  1!5m
 * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
 *                                               .)j(] .d_/ '-(  P .   S
 * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
 * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
 * binary forms, with or without                 )4d[#7r, .   '     )d`)[
 * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
 * that the following conditions are met:       j<<WP+k/);.        _W=j f
 * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
 *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
 *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
 *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
 * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
 *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
 *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
 *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
 *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
 *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
 * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
 *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
 *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
 *    from this software without specific        (js, \[QQW$QWW#?!V"".
 *    prior written permission.                    ]y:.<\..          .
 *                                                 -]n w/ '         [.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
 * 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.
 */

/*
 * For comments regarding functions please see the header file.
 */

#include "guichan/widgets/listbox.hpp"

#include "guichan/basiccontainer.hpp"
#include "guichan/font.hpp"
#include "guichan/graphics.hpp"
#include "guichan/key.hpp"
#include "guichan/listmodel.hpp"
#include "guichan/mouseinput.hpp"

namespace gcn
{
    ListBox::ListBox()
    {
        mSelected = -1;
        mListModel = NULL;
        mWrappingKeyboardSelection = false;
        setWidth(100);
        setFocusable(true);

        addMouseListener(this);
        addKeyListener(this);
    }

    ListBox::ListBox(ListModel *listModel)
    {
        mSelected = -1;
        mWrappingKeyboardSelection = false;
        setWidth(100);
        setListModel(listModel);
        setFocusable(true);

        addMouseListener(this);
        addKeyListener(this);
    }

    void ListBox::draw(Graphics* graphics)
    {
        graphics->setColor(getBackgroundColor());
        graphics->fillRectangle(Rectangle(0, 0, getWidth(), getHeight()));

        if (mListModel == NULL)
        {
            return;
        }

        graphics->setColor(getForegroundColor());
        graphics->setFont(getFont());

        int i, fontHeight;
        int y = 0;

        fontHeight = getFont()->getHeight();

        /**
         * @todo Check cliprects so we do not have to iterate over elements in the list model
         */
        for (i = 0; i < mListModel->getNumberOfElements(); ++i)
        {
            if (i == mSelected)
            {
                graphics->drawRectangle(Rectangle(0, y, getWidth(), fontHeight));
            }

            graphics->drawText(mListModel->getElementAt(i), 1, y);

            y += fontHeight;
        }
    }

    void ListBox::drawBorder(Graphics* graphics)
    {
        Color faceColor = getBaseColor();
        Color highlightColor, shadowColor;
        int alpha = getBaseColor().a;
        int width = getWidth() + getBorderSize() * 2 - 1;
        int height = getHeight() + getBorderSize() * 2 - 1;
        highlightColor = faceColor + 0x303030;
        highlightColor.a = alpha;
        shadowColor = faceColor - 0x303030;
        shadowColor.a = alpha;

        unsigned int i;
        for (i = 0; i < getBorderSize(); ++i)
        {
            graphics->setColor(shadowColor);
            graphics->drawLine(i,i, width - i, i);
            graphics->drawLine(i,i + 1, i, height - i - 1);
            graphics->setColor(highlightColor);
            graphics->drawLine(width - i,i + 1, width - i, height - i);
            graphics->drawLine(i,height - i, width - i - 1, height - i);
        }
    }

    void ListBox::logic()
    {
        adjustSize();
    }

    int ListBox::getSelected()
    {
        return mSelected;
    }

    void ListBox::setSelected(int selected)
    {
        if (mListModel == NULL)
        {
            mSelected = -1;
        }
        else
        {
            if (selected < 0)
            {
                mSelected = -1;
            }
            else if (selected >= mListModel->getNumberOfElements())
            {
                mSelected = mListModel->getNumberOfElements() - 1;
            }
            else
            {
                mSelected = selected;
            }

            BasicContainer *par = getParent();
            if (par == NULL)
            {
                return;
            }

            Rectangle scroll;

            if (mSelected < 0)
            {
                scroll.y = 0;
            }
            else
            {
                scroll.y = getFont()->getHeight() * mSelected;
            }

            scroll.y = getFont()->getHeight() * mSelected;
            scroll.height = getFont()->getHeight();
            par->showWidgetPart(this, scroll);
        }
    }

    void ListBox::keyPress(const Key& key)
    {
        if (key.getValue() == Key::ENTER || key.getValue() == Key::SPACE)
        {
            generateAction();
        }
        else if (key.getValue() == Key::UP)
        {
            setSelected(mSelected - 1);

            if (mSelected == -1)
            {
                if (isWrappingKeyboardSelection())
                {
                    setSelected(getListModel().getNumberOfElements() - 1);
                }
                else
                {
                    setSelected(0);
                }
            }
        }
        else if (key.getValue() == Key::DOWN)
        {
            if (isWrappingKeyboardSelection()
                && getSelected() == getListModel().getNumberOfElements() - 1)
            {
                setSelected(0);
            }
            else
            {
                setSelected(selected + 1);
            }
        }
    }

    void ListBox::mousePress(int x, int y, int button)
    {
        if (button == MouseInput::LEFT && hasMouse())
        {
            setSelected(y / getFont()->getHeight());
            generateAction();
        }
    }

    void ListBox::setListModel(ListModel *listModel)
    {
        mSelected = -1;
        mListModel = listModel;
        adjustSize();
    }

    ListModel* ListBox::getListModel()
    {
        return mListModel;
    }

    void ListBox::adjustSize()
    {
        if (mListModel != NULL)
        {
            setHeight(getFont()->getHeight() * mListModel->getNumberOfElements());
        }
    }

    bool isWrappingKeyboardSelection()
    {
        return mWrappingKeyboardSelection;
    }

    void setWrappingKeyboardSelection(bool wrapping)
    {
        mWrappingKeyboardSelection = wrapping;
    }
}
<|endoftext|>


<commit_before>// RUN: mkdir -p %T/compilation-database-test/include
// RUN: mkdir -p %T/compilation-database-test/a
// RUN: mkdir -p %T/compilation-database-test/b
// RUN: echo 'int *AA = 0;' > %T/compilation-database-test/a/a.cpp
// RUN: echo 'int *AB = 0;' > %T/compilation-database-test/a/b.cpp
// RUN: echo 'int *BB = 0;' > %T/compilation-database-test/b/b.cpp
// RUN: echo 'int *BC = 0;' > %T/compilation-database-test/b/c.cpp
// RUN: echo 'int *HP = 0;' > %T/compilation-database-test/include/header.h
// RUN: echo '#include "header.h"' > %T/compilation-database-test/b/d.cpp
// RUN: sed 's|test_dir|%/T/compilation-database-test|g' %S/Inputs/compilation-database/template.json > %T/compile_commands.json

// Regression test: shouldn't crash.
// RUN: not clang-tidy --checks=-*,modernize-use-nullptr -p %T %T/compilation-database-test/b/not-exist -header-filter=.* 2>&1 | FileCheck %s -check-prefix=CHECK-NOT-EXIST
// CHECK-NOT-EXIST: Error while processing {{.*}}/not-exist.
// CHECK-NOT-EXIST: unable to handle compilation
// CHECK-NOT-EXIST: Found compiler error

// RUN: clang-tidy --checks=-*,modernize-use-nullptr -p %T %T/compilation-database-test/a/a.cpp %T/compilation-database-test/a/b.cpp %T/compilation-database-test/b/b.cpp %T/compilation-database-test/b/c.cpp %T/compilation-database-test/b/d.cpp -header-filter=.* -fix
// RUN: FileCheck -input-file=%T/compilation-database-test/a/a.cpp %s -check-prefix=CHECK-FIX1
// RUN: FileCheck -input-file=%T/compilation-database-test/a/b.cpp %s -check-prefix=CHECK-FIX2
// RUN: FileCheck -input-file=%T/compilation-database-test/b/b.cpp %s -check-prefix=CHECK-FIX3
// RUN: FileCheck -input-file=%T/compilation-database-test/b/c.cpp %s -check-prefix=CHECK-FIX4
// RUN: FileCheck -input-file=%T/compilation-database-test/include/header.h %s -check-prefix=CHECK-FIX5

// CHECK-FIX1: int *AA = nullptr;
// CHECK-FIX2: int *AB = nullptr;
// CHECK-FIX3: int *BB = nullptr;
// CHECK-FIX4: int *BC = nullptr;
// CHECK-FIX5: int *HP = nullptr;
<commit_msg>[fix][clang-tidy] fix for r345961 that introduced a test failure on Windows builds<commit_after>// RUN: mkdir -p %T/compilation-database-test/include
// RUN: mkdir -p %T/compilation-database-test/a
// RUN: mkdir -p %T/compilation-database-test/b
// RUN: echo 'int *AA = 0;' > %T/compilation-database-test/a/a.cpp
// RUN: echo 'int *AB = 0;' > %T/compilation-database-test/a/b.cpp
// RUN: echo 'int *BB = 0;' > %T/compilation-database-test/b/b.cpp
// RUN: echo 'int *BC = 0;' > %T/compilation-database-test/b/c.cpp
// RUN: echo 'int *HP = 0;' > %T/compilation-database-test/include/header.h
// RUN: echo '#include "header.h"' > %T/compilation-database-test/b/d.cpp
// RUN: sed 's|test_dir|%/T/compilation-database-test|g' %S/Inputs/compilation-database/template.json > %T/compile_commands.json

// Regression test: shouldn't crash.
// RUN: not clang-tidy --checks=-*,modernize-use-nullptr -p %T %T/compilation-database-test/b/not-exist -header-filter=.* 2>&1 | FileCheck %s -check-prefix=CHECK-NOT-EXIST
// CHECK-NOT-EXIST: Error while processing {{.*[/\\]}}not-exist.
// CHECK-NOT-EXIST: unable to handle compilation
// CHECK-NOT-EXIST: Found compiler error

// RUN: clang-tidy --checks=-*,modernize-use-nullptr -p %T %T/compilation-database-test/a/a.cpp %T/compilation-database-test/a/b.cpp %T/compilation-database-test/b/b.cpp %T/compilation-database-test/b/c.cpp %T/compilation-database-test/b/d.cpp -header-filter=.* -fix
// RUN: FileCheck -input-file=%T/compilation-database-test/a/a.cpp %s -check-prefix=CHECK-FIX1
// RUN: FileCheck -input-file=%T/compilation-database-test/a/b.cpp %s -check-prefix=CHECK-FIX2
// RUN: FileCheck -input-file=%T/compilation-database-test/b/b.cpp %s -check-prefix=CHECK-FIX3
// RUN: FileCheck -input-file=%T/compilation-database-test/b/c.cpp %s -check-prefix=CHECK-FIX4
// RUN: FileCheck -input-file=%T/compilation-database-test/include/header.h %s -check-prefix=CHECK-FIX5

// CHECK-FIX1: int *AA = nullptr;
// CHECK-FIX2: int *AB = nullptr;
// CHECK-FIX3: int *BB = nullptr;
// CHECK-FIX4: int *BC = nullptr;
// CHECK-FIX5: int *HP = nullptr;
<|endoftext|>


<commit_before><commit_msg>debugging<commit_after><|endoftext|>


<commit_before>#include "rsys/common.h"
#include "rsys/host.h"
#include "rsys/vdriver.h"
#include "rsys/cquick.h" /* for ROMlib_log2 */
#include "rsys/adb.h"
#include "rsys/osevent.h"
#include "OSEvent.h"
#include "ToolboxEvent.h"
#include "SegmentLdr.h"

#include <SDL.h>

namespace Executor
{
/* These variables are required by the vdriver interface. */
uint8_t *vdriver_fbuf;
int vdriver_row_bytes;
int vdriver_width = 1024;
int vdriver_height = 768;
int vdriver_bpp = 8, vdriver_log2_bpp;
int vdriver_max_bpp, vdriver_log2_max_bpp;
vdriver_modes_t *vdriver_mode_list;

int host_cursor_depth = 1;
}

using namespace Executor;

namespace
{
vdriver_modes_t sdl_impotent_modes = { 0, 0 };
SDL_Window *sdlWindow;
SDL_Renderer *sdlRenderer;
SDL_Texture *sdlTexture;
SDL_Surface *sdlSurface;
}

void Executor::vdriver_opt_register(void)
{
}
bool Executor::vdriver_init(int _max_width, int _max_height, int _max_bpp,
                            bool fixed_p, int *argc, char *argv[])
{
    if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0)
    {
        SDL_Log("Failed to initialize SDL: %s", SDL_GetError());
        return false;
    }
    return true;
}

bool Executor::vdriver_acceptable_mode_p(int width, int height, int bpp,
                                         bool grayscale_p, bool exact_match_p)
{
    if(bpp == 1 || bpp == 4 || bpp == 8 || bpp == 16 || bpp == 32)
        return true;
    else
        return false;
}

bool Executor::vdriver_set_mode(int width, int height, int bpp, bool grayscale_p)
{
    printf("set_mode: %d %d %d", width, height, bpp);
    if(vdriver_fbuf)
        delete[] vdriver_fbuf;

    if(width)
        vdriver_width = width;
    if(height)
        vdriver_height = height;
    if(bpp)
        vdriver_bpp = bpp;
    vdriver_row_bytes = vdriver_width * vdriver_bpp / 8;
    vdriver_log2_bpp = ROMlib_log2[vdriver_bpp];
    vdriver_mode_list = &sdl_impotent_modes;

    vdriver_max_bpp = 8; //32;
    vdriver_log2_max_bpp = 3; //5;

    sdlWindow = SDL_CreateWindow("Window",
                                 SDL_WINDOWPOS_UNDEFINED,
                                 SDL_WINDOWPOS_UNDEFINED,
                                 vdriver_width, vdriver_height,
                                 0);
    //SDL_WINDOW_FULLSCREEN_DESKTOP);

    /*sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, 0);

    SDL_RenderSetLogicalSize(sdlRenderer, vdriver_width, vdriver_height);
    SDL_SetRenderDrawColor(sdlRenderer, 128, 128, 128, 255);
    SDL_RenderClear(sdlRenderer);
    SDL_RenderPresent(sdlRenderer);*/

    uint32_t pixelFormat;

    switch(vdriver_bpp)
    {
        case 1:
            pixelFormat = SDL_PIXELFORMAT_INDEX1LSB;
            break;
        case 4:
            pixelFormat = SDL_PIXELFORMAT_INDEX4LSB;
            break;
        case 8:
            pixelFormat = SDL_PIXELFORMAT_INDEX8;
            break;
        case 16:
            pixelFormat = SDL_PIXELFORMAT_RGB555;
            break;
        case 32:
            pixelFormat = SDL_PIXELFORMAT_BGRX8888;
            break;
    }
    /*
    sdlTexture = SDL_CreateTexture(sdlRenderer,
                                   //SDL_PIXELTYPE_INDEX8,
                                   //SDL_PIXELFORMAT_ARGB8888,
                                   SDL_PIXELFORMAT_BGRA8888,
                                   SDL_TEXTUREACCESS_STREAMING,
                                   vdriver_width, vdriver_height);
*/
    vdriver_fbuf = new uint8_t[vdriver_width * vdriver_height * 4];

    sdlSurface = SDL_CreateRGBSurfaceWithFormatFrom(
        vdriver_fbuf,
        vdriver_width, vdriver_height,
        vdriver_bpp,
        vdriver_row_bytes,
        pixelFormat);

    return true;
}
void Executor::vdriver_set_colors(int first_color, int num_colors, const ColorSpec *colors)
{
    SDL_Color *sdlColors = (SDL_Color *)alloca(sizeof(SDL_Color) * num_colors);
    for(int i = 0; i < num_colors; i++)
    {
        sdlColors[i].a = 255;
        sdlColors[i].r = CW(colors[i].rgb.red) >> 8;
        sdlColors[i].g = CW(colors[i].rgb.green) >> 8;
        sdlColors[i].b = CW(colors[i].rgb.blue) >> 8;
    }

    SDL_SetPaletteColors(sdlSurface->format->palette, sdlColors, first_color, num_colors);
}

void Executor::vdriver_get_colors(int first_color, int num_colors, ColorSpec *colors)
{
    SDL_Color *sdlColors = sdlSurface->format->palette->colors;
    for(int i = 0; i < num_colors; i++)
    {
        SDL_Color &c = sdlColors[first_color + i];

        colors[i].value = CW(first_color + i);
        colors[i].rgb.red = CW(c.r << 8 | c.r);
        colors[i].rgb.green = CW(c.g << 8 | c.g);
        colors[i].rgb.blue = CW(c.b << 8 | c.b);
    }
}
int Executor::vdriver_update_screen_rects(int num_rects, const vdriver_rect_t *r,
                                          bool cursor_p)
{
    /*SDL_UpdateTexture(sdlTexture, NULL, vdriver_fbuf, vdriver_row_bytes);
    SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);
    SDL_RenderPresent(sdlRenderer);*/
    SDL_BlitSurface(sdlSurface, NULL, SDL_GetWindowSurface(sdlWindow), NULL);
    SDL_UpdateWindowSurface(sdlWindow);
}

int Executor::vdriver_update_screen(int top, int left, int bottom, int right,
                                    bool cursor_p)
{
    /*SDL_UpdateTexture(sdlTexture, NULL, vdriver_fbuf, vdriver_row_bytes);
    SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);
    SDL_RenderPresent(sdlRenderer);*/
    SDL_BlitSurface(sdlSurface, NULL, SDL_GetWindowSurface(sdlWindow), NULL);
    SDL_UpdateWindowSurface(sdlWindow);
}

void Executor::vdriver_flush_display(void)
{
}

void Executor::vdriver_shutdown(void)
{
}

void Executor::host_flush_shadow_screen(void)
{
}

static bool ConfirmQuit()
{
    const SDL_MessageBoxButtonData buttons[] = {
        { SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 2, "Cancel" },
        { SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 1, "Force Quit" },
    };
    const SDL_MessageBoxData messageboxdata = {
        SDL_MESSAGEBOX_INFORMATION, /* .flags */
        sdlWindow, /* .window */
        "Quit", /* .title */
        "Do you want to quit Executor?", /* .message */
        SDL_arraysize(buttons), /* .numbuttons */
        buttons, /* .buttons */
        NULL /* .colorScheme */
    };
    int buttonid;
    SDL_ShowMessageBox(&messageboxdata, &buttonid);
    return buttonid == 1;
}

void Executor::vdriver_pump_events()
{
    SDL_Event event;
    static uint16_t keymod = 0;

    while(SDL_PollEvent(&event))
    {
        switch(event.type)
        {
            case SDL_MOUSEMOTION:
                MouseLocation.h = CW(event.motion.x);
                MouseLocation.v = CW(event.motion.y);

                adb_apeiron_hack(false);
                break;
            case SDL_MOUSEBUTTONDOWN:
            case SDL_MOUSEBUTTONUP:
            {
                bool down_p;
                int32 when;
                Point where;

                down_p = (event.button.state == SDL_PRESSED);
                if(down_p)
                    keymod &= ~btnState;
                else
                    keymod |= btnState;
                when = TickCount();
                where.h = event.button.x;
                where.v = event.button.y;
                ROMlib_PPostEvent(down_p ? mouseDown : mouseUp,
                                  0, (GUEST<EvQElPtr> *)0, when, where,
                                  keymod);
                adb_apeiron_hack(false);
            }
            break;
            case SDL_QUIT:
                if(ConfirmQuit())
                    ExitToShell();
                break;
        }
    }
}

extern "C" void
ROMlib_SetTitle(char *title)
{
}

extern "C" char *
ROMlib_GetTitle(void)
{
    static char str[] = "Foo";
    return str;
}

extern "C" void
ROMlib_FreeTitle(char *title)
{
}

void Executor::host_set_cursor(char *cursor_data,
                               unsigned short cursor_mask[16],
                               int hotspot_x, int hotspot_y)
{
}

int Executor::host_set_cursor_visible(int show_p)
{
    return 0;
}
<commit_msg>SDL2: cursors<commit_after>#include "rsys/common.h"
#include "rsys/host.h"
#include "rsys/vdriver.h"
#include "rsys/cquick.h" /* for ROMlib_log2 */
#include "rsys/adb.h"
#include "rsys/osevent.h"
#include "OSEvent.h"
#include "ToolboxEvent.h"
#include "SegmentLdr.h"

#include <SDL.h>

namespace Executor
{
/* These variables are required by the vdriver interface. */
uint8_t *vdriver_fbuf;
int vdriver_row_bytes;
int vdriver_width = 1024;
int vdriver_height = 768;
int vdriver_bpp = 8, vdriver_log2_bpp;
int vdriver_max_bpp, vdriver_log2_max_bpp;
vdriver_modes_t *vdriver_mode_list;

int host_cursor_depth = 1;
}

using namespace Executor;

namespace
{
vdriver_modes_t sdl_impotent_modes = { 0, 0 };
SDL_Window *sdlWindow;
SDL_Renderer *sdlRenderer;
SDL_Texture *sdlTexture;
SDL_Surface *sdlSurface;
}

void Executor::vdriver_opt_register(void)
{
}
bool Executor::vdriver_init(int _max_width, int _max_height, int _max_bpp,
                            bool fixed_p, int *argc, char *argv[])
{
    if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0)
    {
        SDL_Log("Failed to initialize SDL: %s", SDL_GetError());
        return false;
    }
    return true;
}

bool Executor::vdriver_acceptable_mode_p(int width, int height, int bpp,
                                         bool grayscale_p, bool exact_match_p)
{
    if(bpp == 1 || bpp == 4 || bpp == 8 || bpp == 16 || bpp == 32)
        return true;
    else
        return false;
}

bool Executor::vdriver_set_mode(int width, int height, int bpp, bool grayscale_p)
{
    printf("set_mode: %d %d %d", width, height, bpp);
    if(vdriver_fbuf)
        delete[] vdriver_fbuf;

    if(width)
        vdriver_width = width;
    if(height)
        vdriver_height = height;
    if(bpp)
        vdriver_bpp = bpp;
    vdriver_row_bytes = vdriver_width * vdriver_bpp / 8;
    vdriver_log2_bpp = ROMlib_log2[vdriver_bpp];
    vdriver_mode_list = &sdl_impotent_modes;

    vdriver_max_bpp = 8; //32;
    vdriver_log2_max_bpp = 3; //5;

    sdlWindow = SDL_CreateWindow("Window",
                                 SDL_WINDOWPOS_UNDEFINED,
                                 SDL_WINDOWPOS_UNDEFINED,
                                 vdriver_width, vdriver_height,
                                 0);
    //SDL_WINDOW_FULLSCREEN_DESKTOP);

    /*sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, 0);

    SDL_RenderSetLogicalSize(sdlRenderer, vdriver_width, vdriver_height);
    SDL_SetRenderDrawColor(sdlRenderer, 128, 128, 128, 255);
    SDL_RenderClear(sdlRenderer);
    SDL_RenderPresent(sdlRenderer);*/

    uint32_t pixelFormat;

    switch(vdriver_bpp)
    {
        case 1:
            pixelFormat = SDL_PIXELFORMAT_INDEX1LSB;
            break;
        case 4:
            pixelFormat = SDL_PIXELFORMAT_INDEX4LSB;
            break;
        case 8:
            pixelFormat = SDL_PIXELFORMAT_INDEX8;
            break;
        case 16:
            pixelFormat = SDL_PIXELFORMAT_RGB555;
            break;
        case 32:
            pixelFormat = SDL_PIXELFORMAT_BGRX8888;
            break;
    }
    /*
    sdlTexture = SDL_CreateTexture(sdlRenderer,
                                   //SDL_PIXELTYPE_INDEX8,
                                   //SDL_PIXELFORMAT_ARGB8888,
                                   SDL_PIXELFORMAT_BGRA8888,
                                   SDL_TEXTUREACCESS_STREAMING,
                                   vdriver_width, vdriver_height);
*/
    vdriver_fbuf = new uint8_t[vdriver_width * vdriver_height * 4];

    sdlSurface = SDL_CreateRGBSurfaceWithFormatFrom(
        vdriver_fbuf,
        vdriver_width, vdriver_height,
        vdriver_bpp,
        vdriver_row_bytes,
        pixelFormat);

    return true;
}
void Executor::vdriver_set_colors(int first_color, int num_colors, const ColorSpec *colors)
{
    SDL_Color *sdlColors = (SDL_Color *)alloca(sizeof(SDL_Color) * num_colors);
    for(int i = 0; i < num_colors; i++)
    {
        sdlColors[i].a = 255;
        sdlColors[i].r = CW(colors[i].rgb.red) >> 8;
        sdlColors[i].g = CW(colors[i].rgb.green) >> 8;
        sdlColors[i].b = CW(colors[i].rgb.blue) >> 8;
    }

    SDL_SetPaletteColors(sdlSurface->format->palette, sdlColors, first_color, num_colors);
}

void Executor::vdriver_get_colors(int first_color, int num_colors, ColorSpec *colors)
{
    SDL_Color *sdlColors = sdlSurface->format->palette->colors;
    for(int i = 0; i < num_colors; i++)
    {
        SDL_Color &c = sdlColors[first_color + i];

        colors[i].value = CW(first_color + i);
        colors[i].rgb.red = CW(c.r << 8 | c.r);
        colors[i].rgb.green = CW(c.g << 8 | c.g);
        colors[i].rgb.blue = CW(c.b << 8 | c.b);
    }
}
int Executor::vdriver_update_screen_rects(int num_rects, const vdriver_rect_t *r,
                                          bool cursor_p)
{
    /*SDL_UpdateTexture(sdlTexture, NULL, vdriver_fbuf, vdriver_row_bytes);
    SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);
    SDL_RenderPresent(sdlRenderer);*/
    SDL_BlitSurface(sdlSurface, NULL, SDL_GetWindowSurface(sdlWindow), NULL);
    SDL_UpdateWindowSurface(sdlWindow);
}

int Executor::vdriver_update_screen(int top, int left, int bottom, int right,
                                    bool cursor_p)
{
    /*SDL_UpdateTexture(sdlTexture, NULL, vdriver_fbuf, vdriver_row_bytes);
    SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);
    SDL_RenderPresent(sdlRenderer);*/
    SDL_BlitSurface(sdlSurface, NULL, SDL_GetWindowSurface(sdlWindow), NULL);
    SDL_UpdateWindowSurface(sdlWindow);
}

void Executor::vdriver_flush_display(void)
{
}

void Executor::vdriver_shutdown(void)
{
}

void Executor::host_flush_shadow_screen(void)
{
}

static bool ConfirmQuit()
{
    const SDL_MessageBoxButtonData buttons[] = {
        { SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 2, "Cancel" },
        { SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 1, "Force Quit" },
    };
    const SDL_MessageBoxData messageboxdata = {
        SDL_MESSAGEBOX_INFORMATION, /* .flags */
        sdlWindow, /* .window */
        "Quit", /* .title */
        "Do you want to quit Executor?", /* .message */
        SDL_arraysize(buttons), /* .numbuttons */
        buttons, /* .buttons */
        NULL /* .colorScheme */
    };
    int buttonid;
    SDL_ShowMessageBox(&messageboxdata, &buttonid);
    return buttonid == 1;
}

void Executor::vdriver_pump_events()
{
    SDL_Event event;
    static uint16_t keymod = 0;

    while(SDL_PollEvent(&event))
    {
        switch(event.type)
        {
            case SDL_MOUSEMOTION:
                MouseLocation.h = CW(event.motion.x);
                MouseLocation.v = CW(event.motion.y);

                adb_apeiron_hack(false);
                break;
            case SDL_MOUSEBUTTONDOWN:
            case SDL_MOUSEBUTTONUP:
            {
                bool down_p;
                int32 when;
                Point where;

                down_p = (event.button.state == SDL_PRESSED);
                if(down_p)
                    keymod &= ~btnState;
                else
                    keymod |= btnState;
                when = TickCount();
                where.h = event.button.x;
                where.v = event.button.y;
                ROMlib_PPostEvent(down_p ? mouseDown : mouseUp,
                                  0, (GUEST<EvQElPtr> *)0, when, where,
                                  keymod);
                adb_apeiron_hack(false);
            }
            break;
            case SDL_QUIT:
                if(ConfirmQuit())
                    ExitToShell();
                break;
        }
    }
}

extern "C" void
ROMlib_SetTitle(char *title)
{
}

extern "C" char *
ROMlib_GetTitle(void)
{
    static char str[] = "Foo";
    return str;
}

extern "C" void
ROMlib_FreeTitle(char *title)
{
}

/* This is really inefficient.  We should hash the cursors */
void Executor::host_set_cursor(char *cursor_data,
                               unsigned short cursor_mask[16],
                               int hotspot_x, int hotspot_y)
{
    SDL_Cursor *old_cursor, *new_cursor;

    old_cursor = SDL_GetCursor();
    new_cursor = SDL_CreateCursor((unsigned char *)cursor_data,
                                  (unsigned char *)cursor_mask,
                                  16, 16, hotspot_x, hotspot_y);
    if(new_cursor != NULL)
    {
        SDL_SetCursor(new_cursor);
        SDL_FreeCursor(old_cursor);
    }
}

int Executor::host_set_cursor_visible(int show_p)
{
    return (SDL_ShowCursor(show_p));
}
<|endoftext|>


<commit_before>//===-- DataflowDiagnostics.cpp - Emits diagnostics based on SIL analysis -===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/Subsystems.h"

#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILModule.h"
#include "swift/SILPasses/Utils/Local.h"

void swift::performSILCleanup(SILModule *M) {
  for (auto &Fn : *M)
    for (auto &BB : Fn) {
      auto I = BB.begin(), E = BB.end();
      while (I != E) {
        // Make sure there is no iterator invalidation if the inspected
        // instruction gets removed from the block.
        SILInstruction *Inst = I++;

        // Remove calls to Builtin.staticReport().
        if (ApplyInst *AI = dyn_cast<ApplyInst>(Inst))
          if (BuiltinFunctionRefInst *FR =
              dyn_cast<BuiltinFunctionRefInst>(AI->getCallee().getDef())) {
            const BuiltinInfo &B =
                              M->getBuiltinInfo(FR->getReferencedFunction());
            if (B.ID == BuiltinValueKind::StaticReport) {
              // The call to the builtin should get removed before we reach
              // IRGen.
              recursivelyDeleteTriviallyDeadInstructions(AI, /* Force */true);
            }
          }
      }
    }
}
<commit_msg>Fix the file name in the comment.<commit_after>//===-- SILCleanup.cpp ---------- Emits diagnostics based on SIL analysis -===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/Subsystems.h"

#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILModule.h"
#include "swift/SILPasses/Utils/Local.h"

void swift::performSILCleanup(SILModule *M) {
  for (auto &Fn : *M)
    for (auto &BB : Fn) {
      auto I = BB.begin(), E = BB.end();
      while (I != E) {
        // Make sure there is no iterator invalidation if the inspected
        // instruction gets removed from the block.
        SILInstruction *Inst = I++;

        // Remove calls to Builtin.staticReport().
        if (ApplyInst *AI = dyn_cast<ApplyInst>(Inst))
          if (BuiltinFunctionRefInst *FR =
              dyn_cast<BuiltinFunctionRefInst>(AI->getCallee().getDef())) {
            const BuiltinInfo &B =
                              M->getBuiltinInfo(FR->getReferencedFunction());
            if (B.ID == BuiltinValueKind::StaticReport) {
              // The call to the builtin should get removed before we reach
              // IRGen.
              recursivelyDeleteTriviallyDeadInstructions(AI, /* Force */true);
            }
          }
      }
    }
}
<|endoftext|>


<commit_before>/* This is free and unencumbered software released into the public domain. */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "error.h"

#include <array>   /* for std::array */
#include <cassert> /* for assert() */
#include <cerrno>  /* for E*, errno */
#include <cstdio>  /* for std::snprintf() */
#include <cstring> /* for std::strerror(), stpncpy() */

using namespace posix;

error::error() noexcept
  : std::system_error(errno, std::system_category()) {}

bad_descriptor::bad_descriptor() noexcept
  : logic_error(EBADF) {}

bad_descriptor::bad_descriptor(const char* const origin) noexcept
  : logic_error(EBADF, std::generic_category(), origin) {}

bad_address::bad_address() noexcept
  : logic_error(EFAULT) {}

bad_address::bad_address(const char* const origin) noexcept
  : logic_error(EFAULT, std::generic_category(), origin) {}

invalid_argument::invalid_argument() noexcept
  : logic_error(EINVAL) {}

invalid_argument::invalid_argument(const char* const origin) noexcept
  : logic_error(EINVAL, std::generic_category(), origin) {}

connection_refused::connection_refused() noexcept
  : runtime_error(ECONNREFUSED) {}

connection_refused::connection_refused(const char* const origin) noexcept
  : runtime_error(ECONNREFUSED, std::generic_category(), origin) {}

void
posix::throw_error() {
  throw_error(errno, nullptr);
}

void
posix::throw_error(const char* const origin) {
  throw_error(errno, origin);
}

void
posix::throw_error(const int code) {
  throw_error(code, nullptr);
}

void
posix::throw_error(const int code,
                   const char* const origin) {
  static thread_local std::array<char, 4096> buffer;

  if (origin) {
    std::snprintf(buffer.data(), buffer.size(),
      "%s [in %s]", std::strerror(code), origin);
  }
  else {
    stpncpy(buffer.data(), std::strerror(code), buffer.size());
    buffer.data()[buffer.size()-1] = '\0';
  }

  switch (code) {
    case EBADF:        /* Bad file descriptor */
      throw bad_descriptor(buffer.data());
    case ECONNREFUSED: /* Connection refused */
      throw connection_refused(buffer.data());
    case EFAULT:       /* Bad address */
      throw bad_address(buffer.data());
    case EINVAL:       /* Invalid argument */
      throw invalid_argument(buffer.data());
    case EMFILE:       /* Too many open files */
      throw posix::fatal_error(code, std::generic_category(), buffer.data());
    case EMSGSIZE:     /* Message too long */
      throw posix::logic_error(code, std::generic_category(), buffer.data());
    case ENAMETOOLONG: /* File name too long */
      throw posix::logic_error(code, std::generic_category(), buffer.data());
    case ENFILE:       /* Too many open files in system */
      throw posix::fatal_error(code, std::generic_category(), buffer.data());
    case ENOBUFS:      /* No buffer space available in kernel */
      throw posix::fatal_error(code, std::generic_category(), buffer.data());
    case ENOMEM:       /* Cannot allocate memory in kernel */
      throw posix::fatal_error(code, std::generic_category(), buffer.data());
    case ENOSPC:       /* No space left on device */
      throw posix::fatal_error(code, std::generic_category(), buffer.data());
    case ENOSYS:       /* Function not implemented */
      throw posix::logic_error(code, std::generic_category(), buffer.data());
    case ENOTDIR:      /* Not a directory */
      throw posix::logic_error(code, std::generic_category(), buffer.data());
    case EACCES:       /* Permission denied */
    case ELOOP:        /* Too many levels of symbolic links */
    case ENOENT:       /* No such file or directory */
    case ENOPROTOOPT:  /* Protocol not available */
    case ENOTCONN:     /* Transport endpoint is not connected */
    case ENOTSOCK:     /* Socket operation on non-socket */
    default:
      throw runtime_error(code, std::generic_category(), buffer.data());
  }
}
<commit_msg>Simplified error message construction.<commit_after>/* This is free and unencumbered software released into the public domain. */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "error.h"

#include <array>   /* for std::array */
#include <cassert> /* for assert() */
#include <cerrno>  /* for E*, errno */
#include <cstdio>  /* for std::snprintf() */
#include <cstring> /* for stpncpy() */

using namespace posix;

error::error() noexcept
  : std::system_error(errno, std::system_category()) {}

bad_descriptor::bad_descriptor() noexcept
  : logic_error(EBADF) {}

bad_descriptor::bad_descriptor(const char* const origin) noexcept
  : logic_error(EBADF, std::generic_category(), origin) {}

bad_address::bad_address() noexcept
  : logic_error(EFAULT) {}

bad_address::bad_address(const char* const origin) noexcept
  : logic_error(EFAULT, std::generic_category(), origin) {}

invalid_argument::invalid_argument() noexcept
  : logic_error(EINVAL) {}

invalid_argument::invalid_argument(const char* const origin) noexcept
  : logic_error(EINVAL, std::generic_category(), origin) {}

connection_refused::connection_refused() noexcept
  : runtime_error(ECONNREFUSED) {}

connection_refused::connection_refused(const char* const origin) noexcept
  : runtime_error(ECONNREFUSED, std::generic_category(), origin) {}

void
posix::throw_error() {
  throw_error(errno, nullptr);
}

void
posix::throw_error(const char* const origin) {
  throw_error(errno, origin);
}

void
posix::throw_error(const int code) {
  throw_error(code, nullptr);
}

void
posix::throw_error(const int code,
                   const char* const origin) {
  static thread_local std::array<char, 4096> buffer;

  const char* what = nullptr;
  if (origin) {
    std::snprintf(buffer.data(), buffer.size(), "%s", origin);
    what = buffer.data();
  }
  else {
    buffer.data()[0] = '\0';
    what = nullptr;
  }

  switch (code) {
    case EBADF:        /* Bad file descriptor */
      throw bad_descriptor(what);
    case ECONNREFUSED: /* Connection refused */
      throw connection_refused(what);
    case EFAULT:       /* Bad address */
      throw bad_address(what);
    case EINVAL:       /* Invalid argument */
      throw invalid_argument(what);
    case EMFILE:       /* Too many open files */
      throw posix::fatal_error(code, std::generic_category(), what);
    case EMSGSIZE:     /* Message too long */
      throw posix::logic_error(code, std::generic_category(), what);
    case ENAMETOOLONG: /* File name too long */
      throw posix::logic_error(code, std::generic_category(), what);
    case ENFILE:       /* Too many open files in system */
      throw posix::fatal_error(code, std::generic_category(), what);
    case ENOBUFS:      /* No buffer space available in kernel */
      throw posix::fatal_error(code, std::generic_category(), what);
    case ENOMEM:       /* Cannot allocate memory in kernel */
      throw posix::fatal_error(code, std::generic_category(), what);
    case ENOSPC:       /* No space left on device */
      throw posix::fatal_error(code, std::generic_category(), what);
    case ENOSYS:       /* Function not implemented */
      throw posix::logic_error(code, std::generic_category(), what);
    case ENOTDIR:      /* Not a directory */
      throw posix::logic_error(code, std::generic_category(), what);
    case EACCES:       /* Permission denied */
    case ELOOP:        /* Too many levels of symbolic links */
    case ENOENT:       /* No such file or directory */
    case ENOPROTOOPT:  /* Protocol not available */
    case ENOTCONN:     /* Transport endpoint is not connected */
    case ENOTSOCK:     /* Socket operation on non-socket */
    default:
      throw runtime_error(code, std::generic_category(), what);
  }
}
<|endoftext|>