<commit_before>/**
 * @file
 *
 * @brief Tests for yamlcpp plugin
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 *
 */

// -- Imports ------------------------------------------------------------------------------------------------------------------------------

#include "yamlcpp.hpp"

#include <kdbmodule.h>
#include <kdbprivate.h>

#include <tests.h>
#include <tests.hpp>

using ckdb::keyNew;

using CppKeySet = kdb::KeySet;
using CppKey = kdb::Key;

// -- Macros -------------------------------------------------------------------------------------------------------------------------------

#define OPEN_PLUGIN(parentName, filepath)                                                                                \
	CppKeySet modules{ 0, KS_END };                                                                                \
	CppKeySet config{ 0, KS_END };                                                                                \
	elektraModulesInit (modules.getKeySet (), 0);                                                                                \
	CppKey parent{ parentName, KEY_VALUE, filepath, KEY_END };                                                                         \
	Plugin * plugin = elektraPluginOpen ("yamlcpp", modules.getKeySet (), config.getKeySet (), *parent);                               \
	exit_if_fail (plugin != NULL, "Could not open yamlcpp plugin")

#define CLOSE_PLUGIN()                                                                                \
	elektraPluginClose (plugin, 0);                                                                                \
	elektraModulesClose (modules.getKeySet (), 0);                                                                                \
	ksDel (modules.release ());                                                                                \
	config.release ()

/* We use this prefix in all header files that contain test data. */
#define PREFIX "user/examples/yamlcpp/"

// -- Functions ----------------------------------------------------------------------------------------------------------------------------

TEST (yamlcpp, contract)
{
	OPEN_PLUGIN ("system/elektra/modules/yamlcpp", "file/path");

	CppKeySet keys;
	succeed_if_same (plugin->kdbGet (plugin, keys.getKeySet (), *parent), ELEKTRA_PLUGIN_STATUS_SUCCESS, "Call of `kdbGet` failed");

	CLOSE_PLUGIN ();
}

void update_parent (CppKeySet expected, string const filepath)
{
	// We replace the value of the parent key of expected keyset, if the header file specifies the value @CONFIG_FILEPATH@.
	// We could also do that via CMake, but the current solution should be easier for now.
	CppKey root = expected.lookup (PREFIX, KDB_O_POP);
	if (root)
	{
		if (root.getString () == "@CONFIG_FILEPATH@") root.setString (filepath);
		expected.append (root);
	}
}

static void test_read (string const & filename, CppKeySet expected, int const status = ELEKTRA_PLUGIN_STATUS_SUCCESS)
#ifdef __llvm__
	__attribute__ ((annotate ("oclint:suppress")))
#endif
{
	string filepath = srcdir_file (filename.c_str ());
	update_parent (expected, filepath);

	OPEN_PLUGIN (PREFIX, filepath.c_str ());

	CppKeySet keys;
	succeed_if_same (plugin->kdbGet (plugin, keys.getKeySet (), *parent), status, "Call of `kdbGet` failed");
	compare_keyset (keys, expected);

	CLOSE_PLUGIN ();
}

static void test_write_read (CppKeySet expected)
#ifdef __llvm__
	__attribute__ ((annotate ("oclint:suppress")))
#endif
{
	string filepath = elektraFilename ();
	update_parent (expected, filepath);

	OPEN_PLUGIN (PREFIX, filepath.c_str ());

	// Write key set to file
	succeed_if_same (plugin->kdbSet (plugin, expected.getKeySet (), *parent), ELEKTRA_PLUGIN_STATUS_SUCCESS, "Unable to write to file");

	// Read written data
	CppKeySet keySetRead;
	succeed_if_same (plugin->kdbGet (plugin, keySetRead.getKeySet (), *parent), ELEKTRA_PLUGIN_STATUS_SUCCESS,
			 "Unable to open or parse file");

	// Compare data
	compare_keyset (keySetRead, expected);

	// Clean up
	CLOSE_PLUGIN ();
}

TEST (yamlcpp, flat)
{
	test_read ("yamlcpp/flat_block_mapping.yaml",
#include "yamlcpp/flat_block_mapping.h"
	);
	test_write_read (
#include "yamlcpp/flat_block_mapping.h"
	);

	test_read ("yamlcpp/flat_flow_mapping.yaml",
#include "yamlcpp/flat_flow_mapping.h"
	);
	test_write_read (
#include "yamlcpp/flat_flow_mapping.h"
	);
}

TEST (yamlcpp, nested)
{
	test_read ("yamlcpp/nested_block_mapping.yaml",
#include "yamlcpp/nested_block_mapping.h"
	);
	test_write_read (
#include "yamlcpp/nested_block_mapping.h"
	);
	test_read ("yamlcpp/nested_mixed_mapping.yaml",
#include "yamlcpp/nested_mixed_mapping.h"
	);
	test_write_read (
#include "yamlcpp/nested_mixed_mapping.h"
	);
}

TEST (yamlcpp, array)
{
	test_read ("yamlcpp/simple_sequence.yaml",
#include "yamlcpp/simple_sequence.h"
	);
	test_write_read (
#include "yamlcpp/simple_sequence.h"
	);

	test_read ("yamlcpp/nested_sequences.yaml",
#include "yamlcpp/nested_sequences.h"
	);
	test_write_read (
#include "yamlcpp/nested_sequences.h"
	);
	test_write_read (
#include "yamlcpp/mapping_with_array_key.h"
	);
	test_write_read (
#include "yamlcpp/mixed.h"
	);
}

// -- Main ---------------------------------------------------------------------------------------------------------------------------------

int main (int argc, char * argv[])
{
	init (argc, argv); // Required for `srcdir_file` to work properly
	::testing::InitGoogleTest (&argc, argv);
	return RUN_ALL_TESTS ();
}
<commit_msg>YAML CPP: Improve error message of test<commit_after>/**
 * @file
 *
 * @brief Tests for yamlcpp plugin
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 *
 */

// -- Imports ------------------------------------------------------------------------------------------------------------------------------

#include "yamlcpp.hpp"

#include <kdbmodule.h>
#include <kdbprivate.h>

#include <tests.h>
#include <tests.hpp>

using ckdb::keyNew;

using CppKeySet = kdb::KeySet;
using CppKey = kdb::Key;

// -- Macros -------------------------------------------------------------------------------------------------------------------------------

#define OPEN_PLUGIN(parentName, filepath)                                                                                \
	CppKeySet modules{ 0, KS_END };                                                                                \
	CppKeySet config{ 0, KS_END };                                                                                \
	elektraModulesInit (modules.getKeySet (), 0);                                                                                \
	CppKey parent{ parentName, KEY_VALUE, filepath, KEY_END };                                                                         \
	Plugin * plugin = elektraPluginOpen ("yamlcpp", modules.getKeySet (), config.getKeySet (), *parent);                               \
	exit_if_fail (plugin != NULL, "Could not open yamlcpp plugin")

#define CLOSE_PLUGIN()                                                                                \
	elektraPluginClose (plugin, 0);                                                                                \
	elektraModulesClose (modules.getKeySet (), 0);                                                                                \
	ksDel (modules.release ());                                                                                \
	config.release ()

/* We use this prefix in all header files that contain test data. */
#define PREFIX "user/examples/yamlcpp/"

// -- Functions ----------------------------------------------------------------------------------------------------------------------------

TEST (yamlcpp, contract)
{
	OPEN_PLUGIN ("system/elektra/modules/yamlcpp", "file/path");

	CppKeySet keys;
	succeed_if_same (plugin->kdbGet (plugin, keys.getKeySet (), *parent), ELEKTRA_PLUGIN_STATUS_SUCCESS, "Call of `kdbGet` failed");

	CLOSE_PLUGIN ();
}

void update_parent (CppKeySet expected, string const filepath)
{
	// We replace the value of the parent key of expected keyset, if the header file specifies the value @CONFIG_FILEPATH@.
	// We could also do that via CMake, but the current solution should be easier for now.
	CppKey root = expected.lookup (PREFIX, KDB_O_POP);
	if (root)
	{
		if (root.getString () == "@CONFIG_FILEPATH@") root.setString (filepath);
		expected.append (root);
	}
}

static void test_read (string const & filename, CppKeySet expected, int const status = ELEKTRA_PLUGIN_STATUS_SUCCESS)
#ifdef __llvm__
	__attribute__ ((annotate ("oclint:suppress")))
#endif
{
	string filepath = srcdir_file (filename.c_str ());
	update_parent (expected, filepath);

	OPEN_PLUGIN (PREFIX, filepath.c_str ());

	CppKeySet keys;
	succeed_if_same (plugin->kdbGet (plugin, keys.getKeySet (), *parent), status, "Call of `kdbGet` failed");
	compare_keyset (keys, expected);

	CLOSE_PLUGIN ();
}

static void test_write_read (CppKeySet expected)
#ifdef __llvm__
	__attribute__ ((annotate ("oclint:suppress")))
#endif
{
	string filepath = elektraFilename ();
	update_parent (expected, filepath);

	OPEN_PLUGIN (PREFIX, filepath.c_str ());

	// Write key set to file
	succeed_if_same (plugin->kdbSet (plugin, expected.getKeySet (), *parent), ELEKTRA_PLUGIN_STATUS_SUCCESS, "Unable to write to file");

	// Read written data
	CppKeySet keySetRead;
	succeed_if_same (plugin->kdbGet (plugin, keySetRead.getKeySet (), *parent), ELEKTRA_PLUGIN_STATUS_SUCCESS,
			 parent.getString ().c_str ());

	// Compare data
	compare_keyset (keySetRead, expected);

	// Clean up
	CLOSE_PLUGIN ();
}

TEST (yamlcpp, flat)
{
	test_read ("yamlcpp/flat_block_mapping.yaml",
#include "yamlcpp/flat_block_mapping.h"
	);
	test_write_read (
#include "yamlcpp/flat_block_mapping.h"
	);

	test_read ("yamlcpp/flat_flow_mapping.yaml",
#include "yamlcpp/flat_flow_mapping.h"
	);
	test_write_read (
#include "yamlcpp/flat_flow_mapping.h"
	);
}

TEST (yamlcpp, nested)
{
	test_read ("yamlcpp/nested_block_mapping.yaml",
#include "yamlcpp/nested_block_mapping.h"
	);
	test_write_read (
#include "yamlcpp/nested_block_mapping.h"
	);
	test_read ("yamlcpp/nested_mixed_mapping.yaml",
#include "yamlcpp/nested_mixed_mapping.h"
	);
	test_write_read (
#include "yamlcpp/nested_mixed_mapping.h"
	);
}

TEST (yamlcpp, array)
{
	test_read ("yamlcpp/simple_sequence.yaml",
#include "yamlcpp/simple_sequence.h"
	);
	test_write_read (
#include "yamlcpp/simple_sequence.h"
	);

	test_read ("yamlcpp/nested_sequences.yaml",
#include "yamlcpp/nested_sequences.h"
	);
	test_write_read (
#include "yamlcpp/nested_sequences.h"
	);
	test_write_read (
#include "yamlcpp/mapping_with_array_key.h"
	);
	test_write_read (
#include "yamlcpp/mixed.h"
	);
}

// -- Main ---------------------------------------------------------------------------------------------------------------------------------

int main (int argc, char * argv[])
{
	init (argc, argv); // Required for `srcdir_file` to work properly
	::testing::InitGoogleTest (&argc, argv);
	return RUN_ALL_TESTS ();
}
<|endoftext|>


<commit_before>// thermostat_main.cpp                  -*-C++-*-
//
/// @file Setup and main loop for smart thermostat

#include "Settings.h"
#include "TempSensor.h"

const int tempSensorPort = D0;
const int heatRelayPort = D1;
const int coolRelayPort = D2;
const int fanRelayPort = D3;

TempSensor theTempSensor;
ThermostatCore theThermostatCore;

void setup()
{
    theTempSensor.initialize(tempSensorPort);
    // theThermostatCore.initialize(heatRelayPort, coolRelayPort, fanRelayPort);
}

// @brief calculate the target thermostat temperatures
// @inputs g_lowerTempSetC, g_upperTempSetC, g_lowerTempBoostC,
// g_upperTempBoostC
// @outputs g_lowerTempTargetC, g_upperTempTargetC
// Computes the target temperature range based on the schedule, manual
// settings, and boost settings.  Boost settings take precidence, followed by
// the normal global settings.  The global settings are set by the
// stored schedule but can be overridden manually or by the home/not home
// detection system.
void calcTargetTemp()
{
    static const float

    if (g_lowerTempBoostC > 0.0)
    {
        g_lowerTempTargetC = g_lowerTempBoostC;
    }
}

void loop()
{
    float currentTempC = theTempSensor.getTemperature();
    g_currentTempCF = theTempSensor.getTemperature(g_tempScale);
    g_currentHumidity = theTempSensor.getRelHumidity();

    float lowerTargetTempC, upperTargetTempC;
    calcTargetTemps(&lowerTargetTempC, &upperTargetTempC);
    theThermostatCore.setTargets(lowerTargetTempC, upperTargetTempC);
    theThermostatCore.runThermostat(currentTempC);
}

// End main.cpp
<commit_msg>Update main loop according to design document.  Dummy in module invocations.<commit_after>// thermostat_main.cpp                  -*-C++-*-
//
/// @file Setup and main loop for smart thermostat

#include "Settings.h"
#include "TempSensor.h"

#include <application.h>  // Arduino interface constants and functions

const int tempSensorPort = D0;
const int heatRelayPort  = D1;
const int coolRelayPort  = D2;
const int fanRelayPort   = D3;

/// @brief initialize the hardware and software modules
void setup()
{
    theCurrentSettings.initialize();
    theLastSettings = theCurrentSettings;
    theTempSensor.initialize(tempSensorPort);
    // theHvacControl.initialize(heatRelayPort, coolRelayPort, fanRelayPort);
    // theThermostatCore.initialize();
    // theDisplay.initialize();
    // theUserInput.initialize();
    // theSchedule.initialize();
    // theBoostManager.initialize();
    // theInternetCommands.initialize();
    // theLogger.initialize();
}

/// @brief main loop called from the Photon OS
/// This function is called repeatedly, approximately once per milisecond,
/// from the Photo OS. Between calls to this function, the OS handles its WiFi
/// connection and other house keeping.  If this loop takes to long to
/// execute, the OS will drop the WiFi connection.  It is therefore important
/// to keep the amount of work minimal in each execution of the loop.  If
/// heavier processing is needed, the code should directly call the OS every
/// once in a while, or else call `delay`, which also gives the OS an
/// opportunity to do its processing.
void loop()
{
    theLastSettings = theCurrentSettings;
    // theThermostatCore.run();
    // theDisplay.run();
    // theUserInput.run();
    // theSchedule.run();
    // theBoostManager.run();
    // theInternetCommands.run();
    // theLogger.run();
}

// End main.cpp
<|endoftext|>


<commit_before>#include "MicroBit.h"

/* The underlying Nordic libraries that support BLE do not compile cleanly with the stringent GCC settings we employ
 * If we're compiling under GCC, then we suppress any warnings generated from this code (but not the rest of the DAL)
 * The ARM cc compiler is more tolerant. We don't test __GNUC__ here to detect GCC as ARMCC also typically sets this
 * as a compatability option, but does not support the options used...
 */
#if !defined(__arm)
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif

#include "ble.h"

/*
 * Return to our predefined compiler settings.
 */
#if !defined(__arm)
#pragma GCC diagnostic pop
#endif

#define MICROBIT_BLE_ENABLE_BONDING 	true
#define MICROBIT_BLE_REQUIRE_MITM		true

#define MICROBIT_PAIRING_MODE_TIMEOUT	90
#define MICROBIT_PAIRING_FADE_SPEED		4

const char* MICROBIT_BLE_MANUFACTURER = "The Cast of W1A";
const char* MICROBIT_BLE_MODEL = "BBC micro:bit";
const char* MICROBIT_BLE_HARDWARE_VERSION = "1.0";
const char* MICROBIT_BLE_FIRMWARE_VERSION = MICROBIT_DAL_VERSION;
const char* MICROBIT_BLE_SOFTWARE_VERSION = NULL;

/*
 * Many of the mbed interfaces we need to use only support callbacks to plain C functions, rather than C++ methods.
 * So, we maintain a pointer to the MicroBitBLEManager that's in use. Ths way, we can still access resources on the micro:bit
 * whilst keeping the code modular.
 */
static MicroBitBLEManager *manager = NULL;

/**
  * Callback when a BLE GATT disconnect occurs.
  */
static void bleDisconnectionCallback(const Gap::DisconnectionCallbackParams_t *reason)
{
    (void) reason; /* -Wunused-param */

    if (manager)
	    manager->onDisconnectionCallback();

}

static void passkeyDisplayCallback(Gap::Handle_t handle, const SecurityManager::Passkey_t passkey)
{
    (void) handle; /* -Wunused-param */

	ManagedString passKey((const char *)passkey, SecurityManager::PASSKEY_LEN);

    if (manager)
	    manager->pairingRequested(passKey);
}

static void securitySetupCompletedCallback(Gap::Handle_t handle, SecurityManager::SecurityCompletionStatus_t status)
{
    (void) handle; /* -Wunused-param */

    if (manager)
	    manager->pairingComplete(status == SecurityManager::SEC_STATUS_SUCCESS);
}

/**
  * Constructor.
  *
  * Configure and manage the micro:bit's Bluetooth Low Energy (BLE) stack.
  * Note that the BLE stack *cannot*  be brought up in a static context.
  * (the software simply hangs or corrupts itself).
  * Hence, we bring it up in an explicit init() method, rather than in the constructor.
  */
MicroBitBLEManager::MicroBitBLEManager()
{
	manager = this;
	this->ble = NULL;
	this->pairingStatus = 0;
}

/**
  * Method that is called whenever a BLE device disconnects from us.
  * The nordic stack stops dvertising whenever a device connects, so we use
  * this callback to restart advertising.
  */
void MicroBitBLEManager::onDisconnectionCallback()
{
	if(ble)
    	ble->startAdvertising();
}

/**
  * Post constructor initialisation method.
  * After *MUCH* pain, it's noted that the BLE stack can't be brought up in a
  * static context, so we bring it up here rather than in the constructor.
  * n.b. This method *must* be called in main() or later, not before.
  *
  * Example:
  * @code
  * uBit.init();
  * @endcode
  */
void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumber)
{
	ManagedString BLEName("BBC micro:bit");

	this->deviceName = deviceName;

    // Start the BLE stack.
    ble = new BLEDevice();
    ble->init();

    // automatically restart advertising after a device disconnects.
    ble->onDisconnection(bleDisconnectionCallback);

    // configure the stack to hold on to CPU during critical timing events.
    // mbed-classic performs __disabe_irq calls in its timers, which can cause MIC failures
    // on secure BLE channels.
    ble_common_opt_radio_cpu_mutex_t opt;
    opt.enable = 1;
    sd_ble_opt_set(BLE_COMMON_OPT_RADIO_CPU_MUTEX, (const ble_opt_t *)&opt);

#if CONFIG_ENABLED(MICROBIT_BLE_PRIVATE_ADDRESSES)
	// Configure for private addresses, so kids' behaviour can't be easily tracked.
	ble->setAddress(Gap::ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE, NULL);
#endif

    // Setup our security requirements.
    ble->securityManager().onPasskeyDisplay(passkeyDisplayCallback);
    ble->securityManager().onSecuritySetupCompleted(securitySetupCompletedCallback);
    ble->securityManager().init(MICROBIT_BLE_ENABLE_BONDING, MICROBIT_BLE_REQUIRE_MITM, SecurityManager::IO_CAPS_DISPLAY_ONLY);

  // Bring up any configured auxiliary services.
#if CONFIG_ENABLED(MICROBIT_BLE_DFU_SERVICE)
    new MicroBitDFUService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_DEVICE_INFORMATION_SERVICE)
    DeviceInformationService ble_device_information_service (*ble, MICROBIT_BLE_MANUFACTURER, MICROBIT_BLE_MODEL, serialNumber.toCharArray(), MICROBIT_BLE_HARDWARE_VERSION, MICROBIT_BLE_FIRMWARE_VERSION, MICROBIT_BLE_SOFTWARE_VERSION);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_EVENT_SERVICE)
    new MicroBitEventService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_LED_SERVICE)
    new MicroBitLEDService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_ACCELEROMETER_SERVICE)
    new MicroBitAccelerometerService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_MAGNETOMETER_SERVICE)
    new MicroBitMagnetometerService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_BUTTON_SERVICE)
    new MicroBitButtonService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_IO_PIN_SERVICE)
    new MicroBitIOPinService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_TEMPERATURE_SERVICE)
    new MicroBitTemperatureService(*ble);
#endif

    // Configure for high speed mode where possible.
    Gap::ConnectionParams_t fast;
    ble->getPreferredConnectionParams(&fast);
    fast.minConnectionInterval = 8; // 10 ms
    fast.maxConnectionInterval = 16; // 20 ms
    fast.slaveLatency = 0;
    ble->setPreferredConnectionParams(&fast);

    // Setup advertising.
    ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble->accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)BLEName.toCharArray(), BLEName.length());
    ble->setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble->setAdvertisingInterval(200);
    ble->startAdvertising();
}

/**
 * A request to pair has been received from a BLE device.
 * If we're in pairing mode, display the passkey to the user.
 */
void MicroBitBLEManager::pairingRequested(ManagedString passKey)
{
	this->passKey = passKey;
	this->pairingStatus = MICROBIT_BLE_PAIR_REQUEST;
}

/**
 * A pairing request has been sucesfully completed.
 * If we're in pairing mode, display feedback to the user.
 */
void MicroBitBLEManager::pairingComplete(bool success)
{
	this->pairingStatus = MICROBIT_BLE_PAIR_COMPLETE;

	if(success)
		this->pairingStatus |= MICROBIT_BLE_PAIR_SUCCESSFUL;
}

/**
 * Enter pairing mode. This is mode is called to initiate pairing, and to enable FOTA programming
 * of the micro:bit in cases where BLE is disabled during normal operation.
 */
void MicroBitBLEManager::pairingMode(MicroBitDisplay &display)
{
	ManagedString namePrefix("BBC micro:bit [");
	ManagedString namePostfix("]");
	ManagedString BLEName = namePrefix + deviceName + namePostfix;

	ManagedString msg("PAIRING MODE!");

	int timeInPairingMode = 0;
	int brightness = 255;
	int fadeDirection = 0;

	// Update the advertised name of this micro:bit to include the device name
    ble->clearAdvertisingPayload();

    ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble->accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)BLEName.toCharArray(), BLEName.length());
    ble->setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble->setAdvertisingInterval(200);
    ble->startAdvertising();

	// Stop any running animations on the display
	display.stopAnimation();
	display.scroll(msg);

	// Display our name, visualised as a histogram in the display to aid identification.
	showNameHistogram(display);

	while(1)
	{
		if (pairingStatus & MICROBIT_BLE_PAIR_REQUEST)
		{
			timeInPairingMode = 0;
			MicroBitImage arrow("0,0,255,0,0\n0,255,0,0,0\n255,255,255,255,255\n0,255,0,0,0\n0,0,255,0,0\n");
			display.print(arrow,0,0,0);

			if (fadeDirection == 0)
				brightness -= MICROBIT_PAIRING_FADE_SPEED;
			else
				brightness += MICROBIT_PAIRING_FADE_SPEED;

			if (brightness <= 40)
				display.clear();

			if (brightness <= 0)
				fadeDirection = 1;

			if (brightness >= 255)
				fadeDirection = 0;

			if (uBit.buttonA.isPressed())
			{
				pairingStatus &= ~MICROBIT_BLE_PAIR_REQUEST;
				pairingStatus |= MICROBIT_BLE_PAIR_PASSCODE;
			}
		}

		if (pairingStatus & MICROBIT_BLE_PAIR_PASSCODE)
		{
			timeInPairingMode = 0;
			display.setBrightness(255);
			for (int i=0; i<passKey.length(); i++)
			{
				display.image.print(passKey.charAt(i),0,0);
				uBit.sleep(800);
				display.clear();
				uBit.sleep(200);

				if (pairingStatus & MICROBIT_BLE_PAIR_COMPLETE)
					break;
			}

			uBit.sleep(1000);
		}

		if (pairingStatus & MICROBIT_BLE_PAIR_COMPLETE)
		{
			if (pairingStatus & MICROBIT_BLE_PAIR_SUCCESSFUL)
			{
				MicroBitImage tick("0,0,0,0,0\n0,0,0,0,255\n0,0,0,255,0\n255,0,255,0,0\n0,255,0,0,0\n");
				display.print(tick,0,0,0);
			}
			else
			{
				MicroBitImage cross("255,0,0,0,255\n0,255,0,255,0\n0,0,255,0,0\n0,255,0,255,0\n255,0,0,0,255\n");
				display.print(cross,0,0,0);
			}
		}

		uBit.sleep(30);
		timeInPairingMode++;

		if (timeInPairingMode >= MICROBIT_PAIRING_MODE_TIMEOUT * 30)
			microbit_reset();
	}
}

/**
  * Displays the device's ID code as a histogram on the LED matrix display.
  */
void MicroBitBLEManager::showNameHistogram(MicroBitDisplay &display)
{
    uint32_t n = NRF_FICR->DEVICEID[1];
    int ld = 1;
    int d = MICROBIT_DFU_HISTOGRAM_HEIGHT;
    int h;

    display.clear();
    for (int i=0; i<MICROBIT_DFU_HISTOGRAM_WIDTH;i++)
    {
        h = (n % d) / ld;

        n -= h;
        d *= MICROBIT_DFU_HISTOGRAM_HEIGHT;
        ld *= MICROBIT_DFU_HISTOGRAM_HEIGHT;

        for (int j=0; j<h+1; j++)
            display.image.setPixelValue(MICROBIT_DFU_HISTOGRAM_WIDTH-i-1, MICROBIT_DFU_HISTOGRAM_HEIGHT-j-1, 255);
    }
}
<commit_msg>WIP: compiling but untested first cut at whitelisting code<commit_after>#include "MicroBit.h"

/* The underlying Nordic libraries that support BLE do not compile cleanly with the stringent GCC settings we employ
 * If we're compiling under GCC, then we suppress any warnings generated from this code (but not the rest of the DAL)
 * The ARM cc compiler is more tolerant. We don't test __GNUC__ here to detect GCC as ARMCC also typically sets this
 * as a compatability option, but does not support the options used...
 */
#if !defined(__arm)
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif

#include "ble.h"

/*
 * Return to our predefined compiler settings.
 */
#if !defined(__arm)
#pragma GCC diagnostic pop
#endif

#define MICROBIT_BLE_ENABLE_BONDING 	true
#define MICROBIT_BLE_REQUIRE_MITM		true

#define MICROBIT_PAIRING_MODE_TIMEOUT	90
#define MICROBIT_PAIRING_FADE_SPEED		4

const char* MICROBIT_BLE_MANUFACTURER = "The Cast of W1A";
const char* MICROBIT_BLE_MODEL = "BBC micro:bit";
const char* MICROBIT_BLE_HARDWARE_VERSION = "1.0";
const char* MICROBIT_BLE_FIRMWARE_VERSION = MICROBIT_DAL_VERSION;
const char* MICROBIT_BLE_SOFTWARE_VERSION = NULL;

/*
 * Many of the mbed interfaces we need to use only support callbacks to plain C functions, rather than C++ methods.
 * So, we maintain a pointer to the MicroBitBLEManager that's in use. Ths way, we can still access resources on the micro:bit
 * whilst keeping the code modular.
 */
static MicroBitBLEManager *manager = NULL;

/**
  * Callback when a BLE GATT disconnect occurs.
  */
static void bleDisconnectionCallback(const Gap::DisconnectionCallbackParams_t *reason)
{
    (void) reason; /* -Wunused-param */

    if (manager)
	    manager->onDisconnectionCallback();

}

static void passkeyDisplayCallback(Gap::Handle_t handle, const SecurityManager::Passkey_t passkey)
{
    (void) handle; /* -Wunused-param */

	ManagedString passKey((const char *)passkey, SecurityManager::PASSKEY_LEN);

    if (manager)
	    manager->pairingRequested(passKey);
}

static void securitySetupCompletedCallback(Gap::Handle_t handle, SecurityManager::SecurityCompletionStatus_t status)
{
    (void) handle; /* -Wunused-param */

    if (manager)
	    manager->pairingComplete(status == SecurityManager::SEC_STATUS_SUCCESS);
}

/**
  * Constructor.
  *
  * Configure and manage the micro:bit's Bluetooth Low Energy (BLE) stack.
  * Note that the BLE stack *cannot*  be brought up in a static context.
  * (the software simply hangs or corrupts itself).
  * Hence, we bring it up in an explicit init() method, rather than in the constructor.
  */
MicroBitBLEManager::MicroBitBLEManager()
{
	manager = this;
	this->ble = NULL;
	this->pairingStatus = 0;
}

/**
  * Method that is called whenever a BLE device disconnects from us.
  * The nordic stack stops dvertising whenever a device connects, so we use
  * this callback to restart advertising.
  */
void MicroBitBLEManager::onDisconnectionCallback()
{
	if(ble)
    	ble->startAdvertising();
}

/**
  * Post constructor initialisation method.
  * After *MUCH* pain, it's noted that the BLE stack can't be brought up in a
  * static context, so we bring it up here rather than in the constructor.
  * n.b. This method *must* be called in main() or later, not before.
  *
  * Example:
  * @code
  * uBit.init();
  * @endcode
  */
void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumber)
{
	ManagedString BLEName("BBC micro:bit");

	this->deviceName = deviceName;

    // Start the BLE stack.
    ble = new BLEDevice();
    ble->init();

    // automatically restart advertising after a device disconnects.
    ble->onDisconnection(bleDisconnectionCallback);

    // configure the stack to hold on to CPU during critical timing events.
    // mbed-classic performs __disabe_irq calls in its timers, which can cause MIC failures
    // on secure BLE channels.
    ble_common_opt_radio_cpu_mutex_t opt;
    opt.enable = 1;
    sd_ble_opt_set(BLE_COMMON_OPT_RADIO_CPU_MUTEX, (const ble_opt_t *)&opt);

#if CONFIG_ENABLED(MICROBIT_BLE_PRIVATE_ADDRESSES)
	// Configure for private addresses, so kids' behaviour can't be easily tracked.
	ble->setAddress(Gap::ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE, NULL);
#endif

    // Setup our security requirements.
    ble->securityManager().onPasskeyDisplay(passkeyDisplayCallback);
    ble->securityManager().onSecuritySetupCompleted(securitySetupCompletedCallback);
    ble->securityManager().init(MICROBIT_BLE_ENABLE_BONDING, MICROBIT_BLE_REQUIRE_MITM, SecurityManager::IO_CAPS_DISPLAY_ONLY);

    // Configure a whitelist to filter all traffic from unbonded devices. Most BLE stacks only permit one connection at a time,
    // so this prevents denial of service attacks.
    BLEProtocol::Address_t bondedAddresses[4];
    Gap::Whitelist_t whitelist;
    whitelist.addresses = bondedAddresses;
    whitelist.capacity = 4;

    ble->securityManager().getAddressesFromBondTable(whitelist);
    ble->gap().setWhitelist(whitelist);

    // Bring up any configured auxiliary services.
#if CONFIG_ENABLED(MICROBIT_BLE_DFU_SERVICE)
    new MicroBitDFUService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_DEVICE_INFORMATION_SERVICE)
    DeviceInformationService ble_device_information_service (*ble, MICROBIT_BLE_MANUFACTURER, MICROBIT_BLE_MODEL, serialNumber.toCharArray(), MICROBIT_BLE_HARDWARE_VERSION, MICROBIT_BLE_FIRMWARE_VERSION, MICROBIT_BLE_SOFTWARE_VERSION);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_EVENT_SERVICE)
    new MicroBitEventService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_LED_SERVICE)
    new MicroBitLEDService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_ACCELEROMETER_SERVICE)
    new MicroBitAccelerometerService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_MAGNETOMETER_SERVICE)
    new MicroBitMagnetometerService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_BUTTON_SERVICE)
    new MicroBitButtonService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_IO_PIN_SERVICE)
    new MicroBitIOPinService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_TEMPERATURE_SERVICE)
    new MicroBitTemperatureService(*ble);
#endif

    // Configure for high speed mode where possible.
    Gap::ConnectionParams_t fast;
    ble->getPreferredConnectionParams(&fast);
    fast.minConnectionInterval = 8; // 10 ms
    fast.maxConnectionInterval = 16; // 20 ms
    fast.slaveLatency = 0;
    ble->setPreferredConnectionParams(&fast);

    // Setup advertising.
    ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble->accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)BLEName.toCharArray(), BLEName.length());
    ble->setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble->setAdvertisingInterval(200);

    if (whitelist.size > 0)
        ble->startAdvertising();
}

/**
 * A request to pair has been received from a BLE device.
 * If we're in pairing mode, display the passkey to the user.
 */
void MicroBitBLEManager::pairingRequested(ManagedString passKey)
{
	this->passKey = passKey;
	this->pairingStatus = MICROBIT_BLE_PAIR_REQUEST;
}

/**
 * A pairing request has been sucesfully completed.
 * If we're in pairing mode, display feedback to the user.
 */
void MicroBitBLEManager::pairingComplete(bool success)
{
	this->pairingStatus = MICROBIT_BLE_PAIR_COMPLETE;

	if(success)
		this->pairingStatus |= MICROBIT_BLE_PAIR_SUCCESSFUL;
}

/**
 * Enter pairing mode. This is mode is called to initiate pairing, and to enable FOTA programming
 * of the micro:bit in cases where BLE is disabled during normal operation.
 */
void MicroBitBLEManager::pairingMode(MicroBitDisplay &display)
{
	ManagedString namePrefix("BBC micro:bit [");
	ManagedString namePostfix("]");
	ManagedString BLEName = namePrefix + deviceName + namePostfix;

	ManagedString msg("PAIRING MODE!");

	int timeInPairingMode = 0;
	int brightness = 255;
	int fadeDirection = 0;

    // Clear the whitelist, so we're discoverable by all BLE devices.
    BLEProtocol::Address_t addresses[4];
    Gap::Whitelist_t whitelist;
    whitelist.addresses = addresses;
    whitelist.capacity = 4;
    whitelist.size = 0;
    ble->gap().setWhitelist(whitelist);

	// Update the advertised name of this micro:bit to include the device name
    ble->clearAdvertisingPayload();

    ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble->accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)BLEName.toCharArray(), BLEName.length());
    ble->setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble->setAdvertisingInterval(200);
    ble->startAdvertising();

	// Stop any running animations on the display
	display.stopAnimation();
	display.scroll(msg);

	// Display our name, visualised as a histogram in the display to aid identification.
	showNameHistogram(display);

	while(1)
	{
		if (pairingStatus & MICROBIT_BLE_PAIR_REQUEST)
		{
			timeInPairingMode = 0;
			MicroBitImage arrow("0,0,255,0,0\n0,255,0,0,0\n255,255,255,255,255\n0,255,0,0,0\n0,0,255,0,0\n");
			display.print(arrow,0,0,0);

			if (fadeDirection == 0)
				brightness -= MICROBIT_PAIRING_FADE_SPEED;
			else
				brightness += MICROBIT_PAIRING_FADE_SPEED;

			if (brightness <= 40)
				display.clear();

			if (brightness <= 0)
				fadeDirection = 1;

			if (brightness >= 255)
				fadeDirection = 0;

			if (uBit.buttonA.isPressed())
			{
				pairingStatus &= ~MICROBIT_BLE_PAIR_REQUEST;
				pairingStatus |= MICROBIT_BLE_PAIR_PASSCODE;
			}
		}

		if (pairingStatus & MICROBIT_BLE_PAIR_PASSCODE)
		{
			timeInPairingMode = 0;
			display.setBrightness(255);
			for (int i=0; i<passKey.length(); i++)
			{
				display.image.print(passKey.charAt(i),0,0);
				uBit.sleep(800);
				display.clear();
				uBit.sleep(200);

				if (pairingStatus & MICROBIT_BLE_PAIR_COMPLETE)
					break;
			}

			uBit.sleep(1000);
		}

		if (pairingStatus & MICROBIT_BLE_PAIR_COMPLETE)
		{
			if (pairingStatus & MICROBIT_BLE_PAIR_SUCCESSFUL)
			{
				MicroBitImage tick("0,0,0,0,0\n0,0,0,0,255\n0,0,0,255,0\n255,0,255,0,0\n0,255,0,0,0\n");
				display.print(tick,0,0,0);
			}
			else
			{
				MicroBitImage cross("255,0,0,0,255\n0,255,0,255,0\n0,0,255,0,0\n0,255,0,255,0\n255,0,0,0,255\n");
				display.print(cross,0,0,0);
			}
		}

		uBit.sleep(30);
		timeInPairingMode++;

		if (timeInPairingMode >= MICROBIT_PAIRING_MODE_TIMEOUT * 30)
			microbit_reset();
	}
}

/**
  * Displays the device's ID code as a histogram on the LED matrix display.
  */
void MicroBitBLEManager::showNameHistogram(MicroBitDisplay &display)
{
    uint32_t n = NRF_FICR->DEVICEID[1];
    int ld = 1;
    int d = MICROBIT_DFU_HISTOGRAM_HEIGHT;
    int h;

    display.clear();
    for (int i=0; i<MICROBIT_DFU_HISTOGRAM_WIDTH;i++)
    {
        h = (n % d) / ld;

        n -= h;
        d *= MICROBIT_DFU_HISTOGRAM_HEIGHT;
        ld *= MICROBIT_DFU_HISTOGRAM_HEIGHT;

        for (int j=0; j<h+1; j++)
            display.image.setPixelValue(MICROBIT_DFU_HISTOGRAM_WIDTH-i-1, MICROBIT_DFU_HISTOGRAM_HEIGHT-j-1, 255);
    }
}
<|endoftext|>


<commit_before>#ifdef WIN32
    #include <windows.h>
#endif

#include "base.h"
#include <iostream>

using namespace std;

GLint width     = 400,
      height    = 400;

GLfloat ortho2D_minX = -400.0f,
        ortho2D_maxX =  400.0f,
        ortho2D_minY = -400.0f,
        ortho2D_maxY =  400.0f;

GLfloat angle  = 100,
        radius = 100;

Point p1, p2, p3, p4, pSelected;

int selected = 1;
float qtdPointsSpline = 10.0f;

void mouse(int x, int y)
{
        switch (selected)
            {
                case 1:
                    p1.X = (x * 2) - width;
                    pSelected.X = p1.X;
                    p1.Y = (y * -2) + height;
                    pSelected.Y = p1.Y;
                break;

                case 2:
                    p2.X = (x * 2) - width;
                    pSelected.X = p2.X;
                    p2.Y = (y * -2) + height;
                    pSelected.Y = p2.Y;
                break;

                case 3:
                    p3.X = (x * 2) - width;
                    pSelected.X = p3.X;
                    p3.Y = (y * -2) + height;
                    pSelected.Y = p3.Y;
                break;

                case 4:
                    p4.X = (x * 2) - width;
                    pSelected.X = p4.X;
                    p4.Y = (y * -2) + height;
                    pSelected.Y = p4.Y;
                break;

                default:
                    cout << "Ivalid point: " << selected << "\n";
                break;
            }

        glutPostRedisplay();
}

Point SplineIterator(Point a, Point b, float t)
{
    Point p;
    p.X = a.X + (b.X - a.X) * t;
    p.Y = a.Y + (b.Y - a.Y) * t;
    return p;
}

void DrawSpline()
{
    float incT = 1/ qtdPointsSpline;
    float t = 0;
    Point p1p2,p2p3,p3p4, p1p2p3, p2p3p4, p1p2p3p4, pontoInicial;

    // Define a Cor Amarela
    glColor3f(255.0, 255.0, 0.0);
    // Define expessura da linha
    glLineWidth(4.0f);

    // Aqui tem um problema, o T deve ser <= 1, mas nao entrava quando == 1, por isso coloquei < 1,001
    for(t=0; t < 1.0001; t = t + incT)
    {
        p1p2 = SplineIterator(p1,p2,t);
        p2p3 = SplineIterator(p2,p3,t);
        p3p4= SplineIterator(p3,p4,t);
        p1p2p3 = SplineIterator(p1p2,p2p3,t);
        p2p3p4 = SplineIterator(p2p3,p3p4,t);
        p1p2p3p4 = SplineIterator(p1p2p3,p2p3p4,t);

        //A primeira vez nao desenha, pois preciso definir o segundo ponto ainda
        if(t != 0)
        {
            glBegin(GL_LINES);
                glVertex2f(pontoInicial.X, pontoInicial.Y);
                glVertex2f(p1p2p3p4.X, p1p2p3p4.Y);
            glEnd();
        }

        pontoInicial.X = p1p2p3p4.X;
        pontoInicial.Y = p1p2p3p4.Y;
    }
}

void display()
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    gluOrtho2D(ortho2D_minX, ortho2D_maxX, ortho2D_minY, ortho2D_maxY);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Eixo X e Y.
    DrawXYAxes();

    // Define a cor Ciano
    glColor3f(0.0, 255.0, 255.0);

    // Expessura da Linha
    glLineWidth(4.0f);

    //Desenha as Linhas do poliedro
    glBegin(GL_LINE_STRIP);
        glVertex2f(p1.X, p1.Y);
        glVertex2f(p2.X, p2.Y);
        glVertex2f(p3.X, p3.Y);
        glVertex2f(p4.X, p4.Y);
    glEnd();

    //Rotina para desenhar Spline
    DrawSpline();

    //Define a Cor Vermelha
    glColor3f(255.0, 0.0, 0.0);
    //Define expessura do ponto
    glPointSize(7.0F);

    //Desenha o ponto na extremidade da Linha
     glBegin(GL_POINTS);
        glVertex2f(pSelected.X, pSelected.Y);
     glEnd();

    glutSwapBuffers();
}

void initialize()
{
    glDisable(GL_TEXTURE_2D);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisable(GL_LIGHTING);
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

    // Pontos Iniciais
    p1.X = -100;
    p1.Y = -100;

    p2.X = -100;
    p2.Y = 100;

    p3.X = 100;
    p3.Y = 100;

    p4.X = 100;
    p4.Y = -100;

    pSelected.X = p1.X;
    pSelected.Y = p1.Y;
}

void keyboard(unsigned char key, int mousePositionX, int mousePositionY)
{
    switch (key)
    {
        case KEY_ESCAPE:
            exit(0);
        break;

        case '1':
            pSelected.X = p1.X;
            pSelected.Y = p1.Y;
            selected = 1;
            glutPostRedisplay();

        break;

        case '2':
            pSelected.X = p2.X;
            pSelected.Y = p2.Y;
            selected = 2;
            glutPostRedisplay();
        break;

        case '3':
            pSelected.X = p3.X;
            pSelected.Y = p3.Y;
            selected = 3;
            glutPostRedisplay();
        break;

        case '4':
            pSelected.X = p4.X;
            pSelected.Y = p4.Y;
            selected = 4;
            glutPostRedisplay();
        break;

        case 'Q':
        case 'q':
            if(qtdPointsSpline > 1)
            {
                qtdPointsSpline = qtdPointsSpline - 1;
                glutPostRedisplay();
            }
        break;

        case 'W':
        case 'w':
            qtdPointsSpline = qtdPointsSpline + 1;
            glutPostRedisplay();
        break;

        default:
            cout << "Invalid key pressed: " << key << "\n";
        break;
    }
}

int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);

    //Posicao da Window
    glutInitWindowPosition(300, 250);

    //Tamananho da Window
    glutInitWindowSize(width, height);

    //Cria uma nova Window
    glutCreateWindow("N2 - Exercicio 5");
    //Display do desenho Inicial
    glutDisplayFunc(display);

    //Faz Tratamento das teclas e redesenha
    glutKeyboardFunc(keyboard);

    //Faz Tratamento do mouse
    glutMotionFunc(mouse);

    initialize();

    glutMainLoop();

    return 0;
}
<commit_msg>Adjust code.<commit_after>#ifdef WIN32
    #include <windows.h>
#endif

#include "base.h"
#include <iostream>

#include <stdio.h>

using namespace std;

GLint width     = 400,
      height    = 400;

GLfloat ortho2D_minX = -400.0f,
        ortho2D_maxX =  400.0f,
        ortho2D_minY = -400.0f,
        ortho2D_maxY =  400.0f;

GLfloat angle  = 100,
        radius = 100;

Point p1, p2, p3, p4, pSelected;

int selected        = 1,
    qtdPointsSpline = 10;

void mouse(int x, int y)
{
    switch (selected)
        {
            case 1:
                p1.X = (x * 2) - width;
                pSelected.X = p1.X;
                p1.Y = (y * -2) + height;
                pSelected.Y = p1.Y;
            break;

            case 2:
                p2.X = (x * 2) - width;
                pSelected.X = p2.X;
                p2.Y = (y * -2) + height;
                pSelected.Y = p2.Y;
            break;

            case 3:
                p3.X = (x * 2) - width;
                pSelected.X = p3.X;
                p3.Y = (y * -2) + height;
                pSelected.Y = p3.Y;
            break;

            case 4:
                p4.X = (x * 2) - width;
                pSelected.X = p4.X;
                p4.Y = (y * -2) + height;
                pSelected.Y = p4.Y;
            break;

            default:
                cout << "Invalid point: " << selected << "\n";
            break;
        }

    glutPostRedisplay();
}

Point SplineIterator(Point a, Point b, float t)
{
    Point p;
    p.X = a.X + (b.X - a.X) * t;
    p.Y = a.Y + (b.Y - a.Y) * t;
    return p;
}

void DrawSpline()
{
    float incT = 1.0f / qtdPointsSpline;
    float t;
    Point p1p2, p2p3, p3p4, p1p2p3, p2p3p4, p1p2p3p4, p0;

    glColor3f(1.0, 1.0, 0.0);
    glLineWidth(4.0f);

    // 1.00000 = Floating-Point Arithmetic Correction.
    for(t = 0; t <= 1.000001; t += incT)
    {
        p1p2     = SplineIterator(p1, p2, t);
        p2p3     = SplineIterator(p2, p3, t);
        p3p4     = SplineIterator(p3, p4, t);
        p1p2p3   = SplineIterator(p1p2, p2p3, t);
        p2p3p4   = SplineIterator(p2p3, p3p4, t);
        p1p2p3p4 = SplineIterator(p1p2p3, p2p3p4, t);

        // A primeira vez nao desenha, pois preciso definir o segundo ponto ainda.
        if(t != 0)
        {
            glBegin(GL_LINES);
                glVertex2f(p0.X, p0.Y);
                glVertex2f(p1p2p3p4.X, p1p2p3p4.Y);
            glEnd();
        }

        p0.X = p1p2p3p4.X;
        p0.Y = p1p2p3p4.Y;
    }
}

void display()
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    gluOrtho2D(ortho2D_minX, ortho2D_maxX, ortho2D_minY, ortho2D_maxY);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Eixo X e Y.
    DrawXYAxes();

    glColor3f(0.0, 1.0, 1.0);
    glLineWidth(4.0f);

    // Desenha as Linhas do poliedro.
    glBegin(GL_LINE_STRIP);
        glVertex2f(p1.X, p1.Y);
        glVertex2f(p2.X, p2.Y);
        glVertex2f(p3.X, p3.Y);
        glVertex2f(p4.X, p4.Y);
    glEnd();

    DrawSpline();

    glColor3f(1.0, 0.0, 0.0);
    glPointSize(7.0F);

    // Desenha o ponto na extremidade da linha.
     glBegin(GL_POINTS);
        glVertex2f(pSelected.X, pSelected.Y);
     glEnd();

    glutSwapBuffers();
}

void initialize()
{
    glDisable(GL_TEXTURE_2D);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisable(GL_LIGHTING);
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

    // Pontos Iniciais
    p1.X = -100;
    p1.Y = -100;

    p2.X = -100;
    p2.Y = 100;

    p3.X = 100;
    p3.Y = 100;

    p4.X = 100;
    p4.Y = -100;

    pSelected.X = p1.X;
    pSelected.Y = p1.Y;
}

void keyboard(unsigned char key, int mousePositionX, int mousePositionY)
{
    switch (key)
    {
        case KEY_ESCAPE:
            exit(0);
        break;

        case '1':
            pSelected.X = p1.X;
            pSelected.Y = p1.Y;
            selected = 1;
            glutPostRedisplay();

        break;

        case '2':
            pSelected.X = p2.X;
            pSelected.Y = p2.Y;
            selected = 2;
            glutPostRedisplay();
        break;

        case '3':
            pSelected.X = p3.X;
            pSelected.Y = p3.Y;
            selected = 3;
            glutPostRedisplay();
        break;

        case '4':
            pSelected.X = p4.X;
            pSelected.Y = p4.Y;
            selected = 4;
            glutPostRedisplay();
        break;

        case 'Q':
        case 'q':
            if(qtdPointsSpline > 1)
            {
                qtdPointsSpline -= 1;
                glutPostRedisplay();
            }
        break;

        case 'W':
        case 'w':
            qtdPointsSpline += 1;
            glutPostRedisplay();
        break;

        default:
            cout << "Invalid key pressed: " << key << "\n";
        break;
    }
}

int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);

    glutInitWindowPosition(300, 250);
    glutInitWindowSize(width, height);
    glutCreateWindow("N2 - Exercicio 5");

    glutDisplayFunc(display);
    glutKeyboardFunc(keyboard);
    glutMotionFunc(mouse);

    initialize();

    glutMainLoop();

    return 0;
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef  _WRTSWTBL_HXX
#define  _WRTSWTBL_HXX

#include <tools/solar.h>
#include <tools/color.hxx>
#include <svl/svarray.hxx>

#include <swdllapi.h>

class Color;
class SwTableBox;
class SwTableLine;
class SwTableLines;
class SwTable;
class SwHTMLTableLayout;
class SvxBrushItem;

namespace editeng { class SvxBorderLine; }

//---------------------------------------------------------------------------
//       Code aus dem HTML-Filter fuers schreiben von Tabellen
//---------------------------------------------------------------------------

#define COLFUZZY 20
#define ROWFUZZY 20
#define COL_DFLT_WIDTH ((2*COLFUZZY)+1)
#define ROW_DFLT_HEIGHT (2*ROWFUZZY)+1

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

class SwWriteTableCell
{
    const SwTableBox *pBox;     // SwTableBox der Zelle
    const SvxBrushItem *pBackground;    // geerbter Hintergrund einer Zeile

    long nHeight;               // fixe/Mindest-Hoehe der Zeile

    sal_uInt32 nWidthOpt;          // Breite aus Option;

    sal_uInt16 nRow;                // Start-Zeile
    sal_uInt16 nCol;                // Start-Spalte

    sal_uInt16 nRowSpan;            // ueberspannte Zeilen
    sal_uInt16 nColSpan;            // ueberspannte Spalten

    sal_Bool bPrcWidthOpt;

public:

    SwWriteTableCell(const SwTableBox *pB, sal_uInt16 nR, sal_uInt16 nC, sal_uInt16 nRSpan,
        sal_uInt16 nCSpan, long nHght, const SvxBrushItem *pBGround)
    : pBox( pB ), pBackground( pBGround ), nHeight( nHght ), nWidthOpt( 0 ),
    nRow( nR ), nCol( nC ), nRowSpan( nRSpan ), nColSpan( nCSpan ),
    bPrcWidthOpt( sal_False )
    {}

    const SwTableBox *GetBox() const { return pBox; }

    sal_uInt16 GetRow() const { return nRow; }
    sal_uInt16 GetCol() const { return nCol; }

    sal_uInt16 GetRowSpan() const { return nRowSpan; }
    sal_uInt16 GetColSpan() const { return nColSpan; }

    long GetHeight() const { return nHeight; }
    sal_Int16 GetVertOri() const;

    const SvxBrushItem *GetBackground() const { return pBackground; }

    void SetWidthOpt( sal_uInt16 nWidth, sal_Bool bPrc )
    {
        nWidthOpt = nWidth; bPrcWidthOpt = bPrc;
    }

    sal_uInt32 GetWidthOpt() const { return nWidthOpt; }
    sal_Bool HasPrcWidthOpt() const { return bPrcWidthOpt; }
};

typedef SwWriteTableCell *SwWriteTableCellPtr;
SV_DECL_PTRARR_DEL( SwWriteTableCells, SwWriteTableCellPtr, 5, 5 )

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

class SwWriteTableRow
{
    SwWriteTableCells aCells;       // Alle Zellen der Rows
    const SvxBrushItem *pBackground;// Hintergrund

    long nPos;                  // End-Position (twips) der Zeile
    sal_Bool mbUseLayoutHeights;

    // Forbidden and not implemented.
    SwWriteTableRow();

    SwWriteTableRow & operator= (const SwWriteTableRow &);

protected:
    // GCC >= 3.4 needs accessible T (const T&) to pass T as const T& argument.
    SwWriteTableRow( const SwWriteTableRow & );

public:

    sal_uInt16 nTopBorder;              // Dicke der oberen/unteren Umrandugen
    sal_uInt16 nBottomBorder;

    sal_Bool bTopBorder : 1;            // Welche Umrandungen sind da?
    sal_Bool bBottomBorder : 1;

    SwWriteTableRow( long nPos, sal_Bool bUseLayoutHeights );

    SwWriteTableCell *AddCell( const SwTableBox *pBox,
                                 sal_uInt16 nRow, sal_uInt16 nCol,
                                 sal_uInt16 nRowSpan, sal_uInt16 nColSpan,
                                 long nHeight,
                                 const SvxBrushItem *pBackground );

    void SetBackground( const SvxBrushItem *pBGround )
    {
        pBackground = pBGround;
    }
    const SvxBrushItem *GetBackground() const { return pBackground; }

    sal_Bool HasTopBorder() const                   { return bTopBorder; }
    sal_Bool HasBottomBorder() const                { return bBottomBorder; }

    long GetPos() const                         { return nPos; }
    const SwWriteTableCells& GetCells() const   { return aCells; }

    inline int operator==( const SwWriteTableRow& rRow ) const;
    inline int operator<( const SwWriteTableRow& rRow2 ) const;
};

inline int SwWriteTableRow::operator==( const SwWriteTableRow& rRow ) const
{
    // etwas Unschaerfe zulassen
    return (nPos >= rRow.nPos ?  nPos - rRow.nPos : rRow.nPos - nPos ) <=
        (mbUseLayoutHeights ? 0 : ROWFUZZY);
}

inline int SwWriteTableRow::operator<( const SwWriteTableRow& rRow ) const
{
    // Da wir hier nur die Wahrheits-Grade 0 und 1 kennen, lassen wir lieber
    // auch nicht zu, dass x==y und x<y gleichzeitig gilt ;-)
    return nPos < rRow.nPos - (mbUseLayoutHeights ? 0 : ROWFUZZY);
}

typedef SwWriteTableRow *SwWriteTableRowPtr;
SV_DECL_PTRARR_SORT_DEL( SwWriteTableRows, SwWriteTableRowPtr, 5, 5 )

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

class SwWriteTableCol
{
    sal_uInt32 nPos;                        // End Position der Spalte

    sal_uInt32 nWidthOpt;

    sal_Bool bRelWidthOpt : 1;
    sal_Bool bOutWidth : 1;                 // Spaltenbreite ausgeben?

public:
    sal_Bool bLeftBorder : 1;               // Welche Umrandungen sind da?
    sal_Bool bRightBorder : 1;

    SwWriteTableCol( sal_uInt32 nPosition );

    sal_uInt32 GetPos() const                       { return nPos; }

    void SetLeftBorder( sal_Bool bBorder )          { bLeftBorder = bBorder; }
    sal_Bool HasLeftBorder() const                  { return bLeftBorder; }

    void SetRightBorder( sal_Bool bBorder )         { bRightBorder = bBorder; }
    sal_Bool HasRightBorder() const                 { return bRightBorder; }

    void SetOutWidth( sal_Bool bSet )               { bOutWidth = bSet; }
    sal_Bool GetOutWidth() const                    { return bOutWidth; }

    inline int operator==( const SwWriteTableCol& rCol ) const;
    inline int operator<( const SwWriteTableCol& rCol ) const;

    void SetWidthOpt( sal_uInt32 nWidth, sal_Bool bRel )
    {
        nWidthOpt = nWidth; bRelWidthOpt = bRel;
    }
    sal_uInt32 GetWidthOpt() const                 { return nWidthOpt; }
    sal_Bool HasRelWidthOpt() const                 { return bRelWidthOpt; }
};

inline int SwWriteTableCol::operator==( const SwWriteTableCol& rCol ) const
{
    // etwas Unschaerfe zulassen
    return (nPos >= rCol.nPos ? nPos - rCol.nPos
                                     : rCol.nPos - nPos ) <= COLFUZZY;
}

inline int SwWriteTableCol::operator<( const SwWriteTableCol& rCol ) const
{
    // Da wir hier nur die Wahrheits-Grade 0 und 1 kennen, lassen wir lieber
    // auch nicht zu, dass x==y und x<y gleichzeitig gilt ;-)
    return nPos < rCol.nPos - COLFUZZY;
}

typedef SwWriteTableCol *SwWriteTableColPtr;
SV_DECL_PTRARR_SORT_DEL( SwWriteTableCols, SwWriteTableColPtr, 5, 5 )

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

class SW_DLLPUBLIC SwWriteTable
{
protected:
    SwWriteTableCols aCols; // alle Spalten
    SwWriteTableRows aRows; // alle Zellen

    sal_uInt32 nBorderColor;        // Umrandungsfarbe

    sal_uInt16 nCellSpacing;        // Dicke der inneren Umrandung
    sal_uInt16 nCellPadding;        // Absatnd Umrandung-Inhalt

    sal_uInt16 nBorder;             // Dicke der ausseren Umrandung
    sal_uInt16 nInnerBorder;        // Dicke der inneren Umrandung
    sal_uInt32 nBaseWidth;            // Bezugsgroesse fur Breiten SwFmtFrmSize

    sal_uInt16 nHeadEndRow;         // letzte Zeile des Tabellen-Kopfes

    sal_uInt16 nLeftSub;
    sal_uInt16 nRightSub;

    sal_uInt32 nTabWidth;              // Absolute/Relative Breite der Tabelle

    sal_Bool bRelWidths : 1;        // Breiten relativ ausgeben?
    sal_Bool bUseLayoutHeights : 1; // Layout zur Hoehenbestimmung nehmen?
#if OSL_DEBUG_LEVEL > 1
    sal_Bool bGetLineHeightCalled : 1;
#endif

    sal_Bool bColsOption : 1;
    sal_Bool bColTags : 1;
    sal_Bool bLayoutExport : 1;
    sal_Bool bCollectBorderWidth : 1;

    virtual sal_Bool ShouldExpandSub( const SwTableBox *pBox,
                                sal_Bool bExpandedBefore, sal_uInt16 nDepth ) const;

    void CollectTableRowsCols( long nStartRPos, sal_uInt32 nStartCPos,
                               long nParentLineHeight,
                               sal_uInt32 nParentLineWidth,
                               const SwTableLines& rLines,
                               sal_uInt16 nDepth );

    void FillTableRowsCols( long nStartRPos, sal_uInt16 nStartRow,
                            sal_uInt32 nStartCPos, sal_uInt16 nStartCol,
                            long nParentLineHeight,
                            sal_uInt32 nParentLineWidth,
                            const SwTableLines& rLines,
                            const SvxBrushItem* pLineBrush,
                            sal_uInt16 nDepth,
                            sal_uInt16 nNumOfHeaderRows );

    void MergeBorders( const editeng::SvxBorderLine* pBorderLine, sal_Bool bTable );

    sal_uInt16 MergeBoxBorders( const SwTableBox *pBox, sal_uInt16 nRow, sal_uInt16 nCol,
                            sal_uInt16 nRowSpan, sal_uInt16 nColSpan,
                            sal_uInt16 &rTopBorder, sal_uInt16 &rBottomBorder );

    sal_uInt32 GetBaseWidth() const { return nBaseWidth; }

    sal_Bool HasRelWidths() const { return bRelWidths; }

public:
    static sal_uInt32 GetBoxWidth( const SwTableBox *pBox );

    sal_uInt32 GetRawWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const;
    sal_uInt16 GetAbsWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const;
    sal_uInt16 GetRelWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const;
    sal_uInt16 GetPrcWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const;

    long GetAbsHeight( long nRawWidth, sal_uInt16 nRow, sal_uInt16 nRowSpan ) const;
protected:

    long GetLineHeight( const SwTableLine *pLine );
    long GetLineHeight( const SwTableBox *pBox ) const;
    const SvxBrushItem *GetLineBrush( const SwTableBox *pBox,
                                      SwWriteTableRow *pRow );

    sal_uInt16 GetLeftSpace( sal_uInt16 nCol ) const;
    sal_uInt16 GetRightSpace( sal_uInt16 nCol, sal_uInt16 nColSpan ) const;

public:
    SwWriteTable( const SwTableLines& rLines, long nWidth, sal_uInt32 nBWidth,
                    sal_Bool bRel, sal_uInt16 nMaxDepth = USHRT_MAX,
                    sal_uInt16 nLeftSub=0, sal_uInt16 nRightSub=0, sal_uInt32 nNumOfRowsToRepeat=0 );
    SwWriteTable( const SwHTMLTableLayout *pLayoutInfo );
    virtual ~SwWriteTable();

    const SwWriteTableCols& GetCols() const { return aCols; }
    const SwWriteTableRows& GetRows() const { return aRows; }
};

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>SW_DLLPUBLIC for SwWriteTable* classes<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef  _WRTSWTBL_HXX
#define  _WRTSWTBL_HXX

#include <tools/solar.h>
#include <tools/color.hxx>
#include <svl/svarray.hxx>

#include <swdllapi.h>

class Color;
class SwTableBox;
class SwTableLine;
class SwTableLines;
class SwTable;
class SwHTMLTableLayout;
class SvxBrushItem;

namespace editeng { class SvxBorderLine; }

//---------------------------------------------------------------------------
//       Code aus dem HTML-Filter fuers schreiben von Tabellen
//---------------------------------------------------------------------------

#define COLFUZZY 20
#define ROWFUZZY 20
#define COL_DFLT_WIDTH ((2*COLFUZZY)+1)
#define ROW_DFLT_HEIGHT (2*ROWFUZZY)+1

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

class SW_DLLPUBLIC SwWriteTableCell
{
    const SwTableBox *pBox;     // SwTableBox der Zelle
    const SvxBrushItem *pBackground;    // geerbter Hintergrund einer Zeile

    long nHeight;               // fixe/Mindest-Hoehe der Zeile

    sal_uInt32 nWidthOpt;          // Breite aus Option;

    sal_uInt16 nRow;                // Start-Zeile
    sal_uInt16 nCol;                // Start-Spalte

    sal_uInt16 nRowSpan;            // ueberspannte Zeilen
    sal_uInt16 nColSpan;            // ueberspannte Spalten

    sal_Bool bPrcWidthOpt;

public:

    SwWriteTableCell(const SwTableBox *pB, sal_uInt16 nR, sal_uInt16 nC, sal_uInt16 nRSpan,
        sal_uInt16 nCSpan, long nHght, const SvxBrushItem *pBGround)
    : pBox( pB ), pBackground( pBGround ), nHeight( nHght ), nWidthOpt( 0 ),
    nRow( nR ), nCol( nC ), nRowSpan( nRSpan ), nColSpan( nCSpan ),
    bPrcWidthOpt( sal_False )
    {}

    const SwTableBox *GetBox() const { return pBox; }

    sal_uInt16 GetRow() const { return nRow; }
    sal_uInt16 GetCol() const { return nCol; }

    sal_uInt16 GetRowSpan() const { return nRowSpan; }
    sal_uInt16 GetColSpan() const { return nColSpan; }

    long GetHeight() const { return nHeight; }
    sal_Int16 GetVertOri() const;

    const SvxBrushItem *GetBackground() const { return pBackground; }

    void SetWidthOpt( sal_uInt16 nWidth, sal_Bool bPrc )
    {
        nWidthOpt = nWidth; bPrcWidthOpt = bPrc;
    }

    sal_uInt32 GetWidthOpt() const { return nWidthOpt; }
    sal_Bool HasPrcWidthOpt() const { return bPrcWidthOpt; }
};

typedef SwWriteTableCell *SwWriteTableCellPtr;
SV_DECL_PTRARR_DEL( SwWriteTableCells, SwWriteTableCellPtr, 5, 5 )

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

class SW_DLLPUBLIC SwWriteTableRow
{
    SwWriteTableCells aCells;       // Alle Zellen der Rows
    const SvxBrushItem *pBackground;// Hintergrund

    long nPos;                  // End-Position (twips) der Zeile
    sal_Bool mbUseLayoutHeights;

    // Forbidden and not implemented.
    SwWriteTableRow();

    SwWriteTableRow & operator= (const SwWriteTableRow &);

protected:
    // GCC >= 3.4 needs accessible T (const T&) to pass T as const T& argument.
    SwWriteTableRow( const SwWriteTableRow & );

public:

    sal_uInt16 nTopBorder;              // Dicke der oberen/unteren Umrandugen
    sal_uInt16 nBottomBorder;

    sal_Bool bTopBorder : 1;            // Welche Umrandungen sind da?
    sal_Bool bBottomBorder : 1;

    SwWriteTableRow( long nPos, sal_Bool bUseLayoutHeights );

    SwWriteTableCell *AddCell( const SwTableBox *pBox,
                                 sal_uInt16 nRow, sal_uInt16 nCol,
                                 sal_uInt16 nRowSpan, sal_uInt16 nColSpan,
                                 long nHeight,
                                 const SvxBrushItem *pBackground );

    void SetBackground( const SvxBrushItem *pBGround )
    {
        pBackground = pBGround;
    }
    const SvxBrushItem *GetBackground() const { return pBackground; }

    sal_Bool HasTopBorder() const                   { return bTopBorder; }
    sal_Bool HasBottomBorder() const                { return bBottomBorder; }

    long GetPos() const                         { return nPos; }
    const SwWriteTableCells& GetCells() const   { return aCells; }

    inline int operator==( const SwWriteTableRow& rRow ) const;
    inline int operator<( const SwWriteTableRow& rRow2 ) const;
};

inline int SwWriteTableRow::operator==( const SwWriteTableRow& rRow ) const
{
    // etwas Unschaerfe zulassen
    return (nPos >= rRow.nPos ?  nPos - rRow.nPos : rRow.nPos - nPos ) <=
        (mbUseLayoutHeights ? 0 : ROWFUZZY);
}

inline int SwWriteTableRow::operator<( const SwWriteTableRow& rRow ) const
{
    // Da wir hier nur die Wahrheits-Grade 0 und 1 kennen, lassen wir lieber
    // auch nicht zu, dass x==y und x<y gleichzeitig gilt ;-)
    return nPos < rRow.nPos - (mbUseLayoutHeights ? 0 : ROWFUZZY);
}

typedef SwWriteTableRow *SwWriteTableRowPtr;
SV_DECL_PTRARR_SORT_DEL( SwWriteTableRows, SwWriteTableRowPtr, 5, 5 )

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

class SW_DLLPUBLIC SwWriteTableCol
{
    sal_uInt32 nPos;                        // End Position der Spalte

    sal_uInt32 nWidthOpt;

    sal_Bool bRelWidthOpt : 1;
    sal_Bool bOutWidth : 1;                 // Spaltenbreite ausgeben?

public:
    sal_Bool bLeftBorder : 1;               // Welche Umrandungen sind da?
    sal_Bool bRightBorder : 1;

    SwWriteTableCol( sal_uInt32 nPosition );

    sal_uInt32 GetPos() const                       { return nPos; }

    void SetLeftBorder( sal_Bool bBorder )          { bLeftBorder = bBorder; }
    sal_Bool HasLeftBorder() const                  { return bLeftBorder; }

    void SetRightBorder( sal_Bool bBorder )         { bRightBorder = bBorder; }
    sal_Bool HasRightBorder() const                 { return bRightBorder; }

    void SetOutWidth( sal_Bool bSet )               { bOutWidth = bSet; }
    sal_Bool GetOutWidth() const                    { return bOutWidth; }

    inline int operator==( const SwWriteTableCol& rCol ) const;
    inline int operator<( const SwWriteTableCol& rCol ) const;

    void SetWidthOpt( sal_uInt32 nWidth, sal_Bool bRel )
    {
        nWidthOpt = nWidth; bRelWidthOpt = bRel;
    }
    sal_uInt32 GetWidthOpt() const                 { return nWidthOpt; }
    sal_Bool HasRelWidthOpt() const                 { return bRelWidthOpt; }
};

inline int SwWriteTableCol::operator==( const SwWriteTableCol& rCol ) const
{
    // etwas Unschaerfe zulassen
    return (nPos >= rCol.nPos ? nPos - rCol.nPos
                                     : rCol.nPos - nPos ) <= COLFUZZY;
}

inline int SwWriteTableCol::operator<( const SwWriteTableCol& rCol ) const
{
    // Da wir hier nur die Wahrheits-Grade 0 und 1 kennen, lassen wir lieber
    // auch nicht zu, dass x==y und x<y gleichzeitig gilt ;-)
    return nPos < rCol.nPos - COLFUZZY;
}

typedef SwWriteTableCol *SwWriteTableColPtr;
SV_DECL_PTRARR_SORT_DEL( SwWriteTableCols, SwWriteTableColPtr, 5, 5 )

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

class SW_DLLPUBLIC SwWriteTable
{
protected:
    SwWriteTableCols aCols; // alle Spalten
    SwWriteTableRows aRows; // alle Zellen

    sal_uInt32 nBorderColor;        // Umrandungsfarbe

    sal_uInt16 nCellSpacing;        // Dicke der inneren Umrandung
    sal_uInt16 nCellPadding;        // Absatnd Umrandung-Inhalt

    sal_uInt16 nBorder;             // Dicke der ausseren Umrandung
    sal_uInt16 nInnerBorder;        // Dicke der inneren Umrandung
    sal_uInt32 nBaseWidth;            // Bezugsgroesse fur Breiten SwFmtFrmSize

    sal_uInt16 nHeadEndRow;         // letzte Zeile des Tabellen-Kopfes

    sal_uInt16 nLeftSub;
    sal_uInt16 nRightSub;

    sal_uInt32 nTabWidth;              // Absolute/Relative Breite der Tabelle

    sal_Bool bRelWidths : 1;        // Breiten relativ ausgeben?
    sal_Bool bUseLayoutHeights : 1; // Layout zur Hoehenbestimmung nehmen?
#if OSL_DEBUG_LEVEL > 1
    sal_Bool bGetLineHeightCalled : 1;
#endif

    sal_Bool bColsOption : 1;
    sal_Bool bColTags : 1;
    sal_Bool bLayoutExport : 1;
    sal_Bool bCollectBorderWidth : 1;

    virtual sal_Bool ShouldExpandSub( const SwTableBox *pBox,
                                sal_Bool bExpandedBefore, sal_uInt16 nDepth ) const;

    void CollectTableRowsCols( long nStartRPos, sal_uInt32 nStartCPos,
                               long nParentLineHeight,
                               sal_uInt32 nParentLineWidth,
                               const SwTableLines& rLines,
                               sal_uInt16 nDepth );

    void FillTableRowsCols( long nStartRPos, sal_uInt16 nStartRow,
                            sal_uInt32 nStartCPos, sal_uInt16 nStartCol,
                            long nParentLineHeight,
                            sal_uInt32 nParentLineWidth,
                            const SwTableLines& rLines,
                            const SvxBrushItem* pLineBrush,
                            sal_uInt16 nDepth,
                            sal_uInt16 nNumOfHeaderRows );

    void MergeBorders( const editeng::SvxBorderLine* pBorderLine, sal_Bool bTable );

    sal_uInt16 MergeBoxBorders( const SwTableBox *pBox, sal_uInt16 nRow, sal_uInt16 nCol,
                            sal_uInt16 nRowSpan, sal_uInt16 nColSpan,
                            sal_uInt16 &rTopBorder, sal_uInt16 &rBottomBorder );

    sal_uInt32 GetBaseWidth() const { return nBaseWidth; }

    sal_Bool HasRelWidths() const { return bRelWidths; }

public:
    static sal_uInt32 GetBoxWidth( const SwTableBox *pBox );

    sal_uInt32 GetRawWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const;
    sal_uInt16 GetAbsWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const;
    sal_uInt16 GetRelWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const;
    sal_uInt16 GetPrcWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const;

    long GetAbsHeight( long nRawWidth, sal_uInt16 nRow, sal_uInt16 nRowSpan ) const;
protected:

    long GetLineHeight( const SwTableLine *pLine );
    long GetLineHeight( const SwTableBox *pBox ) const;
    const SvxBrushItem *GetLineBrush( const SwTableBox *pBox,
                                      SwWriteTableRow *pRow );

    sal_uInt16 GetLeftSpace( sal_uInt16 nCol ) const;
    sal_uInt16 GetRightSpace( sal_uInt16 nCol, sal_uInt16 nColSpan ) const;

public:
    SwWriteTable( const SwTableLines& rLines, long nWidth, sal_uInt32 nBWidth,
                    sal_Bool bRel, sal_uInt16 nMaxDepth = USHRT_MAX,
                    sal_uInt16 nLeftSub=0, sal_uInt16 nRightSub=0, sal_uInt32 nNumOfRowsToRepeat=0 );
    SwWriteTable( const SwHTMLTableLayout *pLayoutInfo );
    virtual ~SwWriteTable();

    const SwWriteTableCols& GetCols() const { return aCols; }
    const SwWriteTableRows& GetRows() const { return aRows; }
};

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>// Copyright (c) 2009 Roman Neuhauser
// Distributed under the MIT license (see LICENSE file)
// vim: sw=4 sts=4 et fdm=marker cms=\ //\ %s

#include "php_iniphile.hpp"
#include "iniphile.hpp"

zend_class_entry *iniphile_ce;
zend_object_handlers iniphile_object_handlers;

struct phpini
// {{{
{
    zend_object std;
    iniphile_bridge *impl;
}; // }}}

#define PHPTHIS() \
    static_cast<phpini *>( \
        zend_object_store_get_object(getThis() TSRMLS_CC) \
    )

void
iniphile_free_storage(void *object TSRMLS_DC) // {{{
{
    phpini *obj = static_cast<phpini *>(object);
    delete obj->impl;

    zend_hash_destroy(obj->std.properties);
    FREE_HASHTABLE(obj->std.properties);

    efree(obj);
} // }}}

static
void
init(zend_object *zob, zend_class_entry *type TSRMLS_DC) // {{{
{
    zob->ce = type;

    ALLOC_HASHTABLE(zob->properties);
    zend_hash_init(
        zob->properties
      , 0
      , 0
      , ZVAL_PTR_DTOR
      , 0
    );

    zval *tmp;

    zend_hash_copy(
        zob->properties
      , &(zob->ce)->default_properties
      , reinterpret_cast<copy_ctor_func_t>(zval_add_ref)
      , static_cast<void *>(&tmp)
      , sizeof(zval *)
    );

} // }}}

zend_object_value
iniphile_create_handler(zend_class_entry *type TSRMLS_DC) // {{{
{
    phpini *obj = static_cast<phpini *>(
        emalloc(sizeof(phpini))
    );
    memset(obj, 0, sizeof(phpini));

    zend_object *zob(&obj->std);

    init(zob, type TSRMLS_CC);
    zend_object_value retval;

    retval.handle = zend_objects_store_put(
        obj
      , 0
      , iniphile_free_storage
      , 0 TSRMLS_CC
    );
    retval.handlers = &iniphile_object_handlers;

    return retval;
} // }}}

PHP_METHOD(iniphile, __construct) // {{{
{
    char *path;
    int pathlen;

    if (FAILURE == zend_parse_parameters(
        ZEND_NUM_ARGS() TSRMLS_CC
      , "s"
      , &path
      , &pathlen
    )) {
        return;
    }
    phpini *obj = PHPTHIS();
    obj->impl = new iniphile_bridge(path);
} // }}}

PHP_METHOD(iniphile, is_open) // {{{
{
    phpini *obj = PHPTHIS();
    if (0 == obj->impl) {
        RETURN_NULL();
    }
    RETURN_BOOL(obj->impl->is_open());
} // }}}
PHP_METHOD(iniphile, path) // {{{
{
    phpini *obj = PHPTHIS();
    if (0 == obj->impl) {
        RETURN_NULL();
    }
    RETURN_STRING(estrdup(obj->impl->path().c_str()), 0);
} // }}}
PHP_METHOD(iniphile, get_strings) // {{{
{
    phpini *obj = PHPTHIS();
    if (0 == obj->impl) {
        RETURN_NULL();
    }
    char *path;
    int path_len;
    zval *arr;
    if (FAILURE == zend_parse_parameters(
        ZEND_NUM_ARGS() TSRMLS_CC
      , "sa"
      , &path
      , &path_len
      , &arr
    )) {
        RETURN_NULL();
    }
    typedef std::vector<std::string> Strings;
    zval **elm;
    HashPosition i;
    HashTable *hash = Z_ARRVAL_P(arr);
    Strings dv(zend_hash_num_elements(hash));
    for (
        zend_hash_internal_pointer_reset_ex(hash, &i);
        SUCCESS == zend_hash_get_current_data_ex(hash, (void**) &elm, &i);
        zend_hash_move_forward_ex(hash, &i)
    ) {
        dv.push_back(Z_STRVAL_PP(elm));
    }
    Strings rv(obj->impl->get(path, dv));
    array_init(return_value);
    for (int i = 0; i < rv.size(); ++i) {
        add_next_index_string(return_value, estrdup(rv[i].c_str()), 0);
    }
} // }}}
PHP_METHOD(iniphile, get_string) // {{{
{
    phpini *obj = PHPTHIS();
    if (0 == obj->impl) {
        RETURN_NULL();
    }
    char *path, *dflt;
    int path_len, dflt_len;
    if (FAILURE == zend_parse_parameters(
        ZEND_NUM_ARGS() TSRMLS_CC
      , "ss"
      , &path
      , &path_len
      , &dflt
      , &dflt_len
    )) {
        RETURN_NULL();
    }
    RETURN_STRING(estrdup(obj->impl->get(path, std::string(dflt)).c_str()), 0);
} // }}}
PHP_METHOD(iniphile, get_bool) // {{{
{
    phpini *obj = PHPTHIS();
    if (0 == obj->impl) {
        RETURN_NULL();
    }
    char *path;
    int path_len;
    zend_bool dflt;
    if (FAILURE == zend_parse_parameters(
        ZEND_NUM_ARGS() TSRMLS_CC
      , "sb"
      , &path
      , &path_len
      , &dflt
    )) {
        RETURN_NULL();
    }
    RETURN_BOOL(obj->impl->get(path, !!dflt));
} // }}}
PHP_METHOD(iniphile, get_long) // {{{
{
    phpini *obj = PHPTHIS();
    if (0 == obj->impl) {
        RETURN_NULL();
    }
    char *path;
    int path_len;
    long dflt;
    if (FAILURE == zend_parse_parameters(
        ZEND_NUM_ARGS() TSRMLS_CC
      , "sl"
      , &path
      , &path_len
      , &dflt
    )) {
        RETURN_NULL();
    }
    RETURN_LONG(obj->impl->get(path, dflt));
} // }}}
PHP_METHOD(iniphile, get_double) // {{{
{
    phpini *obj = PHPTHIS();
    if (0 == obj->impl) {
        RETURN_NULL();
    }
    char *path;
    int path_len;
    double dflt;
    if (FAILURE == zend_parse_parameters(
        ZEND_NUM_ARGS() TSRMLS_CC
      , "sd"
      , &path
      , &path_len
      , &dflt
    )) {
        RETURN_NULL();
    }
    RETURN_DOUBLE(obj->impl->get(path, dflt));
} // }}}

function_entry iniphile_methods[] = // {{{
{
    PHP_ME(iniphile, __construct, 0, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
    PHP_ME(iniphile, is_open, 0, ZEND_ACC_PUBLIC)
    PHP_ME(iniphile, path, 0, ZEND_ACC_PUBLIC)
    PHP_ME(iniphile, get_strings, 0, ZEND_ACC_PUBLIC)
    PHP_ME(iniphile, get_string, 0, ZEND_ACC_PUBLIC)
    PHP_ME(iniphile, get_bool, 0, ZEND_ACC_PUBLIC)
    PHP_ME(iniphile, get_long, 0, ZEND_ACC_PUBLIC)
    PHP_ME(iniphile, get_double, 0, ZEND_ACC_PUBLIC)
    {0, 0, 0}
}; // }}}

PHP_MINIT_FUNCTION(iniphile) // {{{
{
    zend_class_entry ce;
    INIT_CLASS_ENTRY(ce, "iniphile", iniphile_methods);
    iniphile_ce = zend_register_internal_class(&ce TSRMLS_CC);
    iniphile_ce->create_object = &iniphile_create_handler;
    memcpy(
        &iniphile_object_handlers
      , zend_get_std_object_handlers()
      , sizeof(zend_object_handlers)
    );
    iniphile_object_handlers.clone_obj = 0;

    return SUCCESS;
} // }}}

zend_module_entry iniphile_module_entry = // {{{
{
    STANDARD_MODULE_HEADER,
    PHP_INIPHILE_EXTNAME,
    0, // functions
    PHP_MINIT(iniphile),
    0, // MSHUTDOWN
    0, // RINIT
    0, // RSHUTDOWN
    0, // MINFO
    PHP_INIPHILE_EXTVER,
    STANDARD_MODULE_PROPERTIES
}; // }}}

#ifdef COMPILE_DL_INIPHILE
extern "C" {
ZEND_GET_MODULE(iniphile)
}
#endif
<commit_msg>remove superfluous checks from PHP_METHODs<commit_after>// Copyright (c) 2009 Roman Neuhauser
// Distributed under the MIT license (see LICENSE file)
// vim: sw=4 sts=4 et fdm=marker cms=\ //\ %s

#include "php_iniphile.hpp"
#include "iniphile.hpp"

zend_class_entry *iniphile_ce;
zend_object_handlers iniphile_object_handlers;

struct phpini
// {{{
{
    zend_object std;
    iniphile_bridge *impl;
}; // }}}

#define PHPTHIS() \
    static_cast<phpini *>( \
        zend_object_store_get_object(getThis() TSRMLS_CC) \
    )

void
iniphile_free_storage(void *object TSRMLS_DC) // {{{
{
    phpini *obj = static_cast<phpini *>(object);
    delete obj->impl;

    zend_hash_destroy(obj->std.properties);
    FREE_HASHTABLE(obj->std.properties);

    efree(obj);
} // }}}

static
void
init(zend_object *zob, zend_class_entry *type TSRMLS_DC) // {{{
{
    zob->ce = type;

    ALLOC_HASHTABLE(zob->properties);
    zend_hash_init(
        zob->properties
      , 0
      , 0
      , ZVAL_PTR_DTOR
      , 0
    );

    zval *tmp;

    zend_hash_copy(
        zob->properties
      , &(zob->ce)->default_properties
      , reinterpret_cast<copy_ctor_func_t>(zval_add_ref)
      , static_cast<void *>(&tmp)
      , sizeof(zval *)
    );

} // }}}

zend_object_value
iniphile_create_handler(zend_class_entry *type TSRMLS_DC) // {{{
{
    phpini *obj = static_cast<phpini *>(
        emalloc(sizeof(phpini))
    );
    memset(obj, 0, sizeof(phpini));

    zend_object *zob(&obj->std);

    init(zob, type TSRMLS_CC);
    zend_object_value retval;

    retval.handle = zend_objects_store_put(
        obj
      , 0
      , iniphile_free_storage
      , 0 TSRMLS_CC
    );
    retval.handlers = &iniphile_object_handlers;

    return retval;
} // }}}

PHP_METHOD(iniphile, __construct) // {{{
{
    char *path;
    int pathlen;

    if (FAILURE == zend_parse_parameters(
        ZEND_NUM_ARGS() TSRMLS_CC
      , "s"
      , &path
      , &pathlen
    )) {
        return;
    }
    phpini *obj = PHPTHIS();
    obj->impl = new iniphile_bridge(path);
} // }}}

PHP_METHOD(iniphile, is_open) // {{{
{
    phpini *obj = PHPTHIS();
    RETURN_BOOL(obj->impl->is_open());
} // }}}
PHP_METHOD(iniphile, path) // {{{
{
    phpini *obj = PHPTHIS();
    RETURN_STRING(estrdup(obj->impl->path().c_str()), 0);
} // }}}
PHP_METHOD(iniphile, get_strings) // {{{
{
    phpini *obj = PHPTHIS();
    char *path;
    int path_len;
    zval *arr;
    if (FAILURE == zend_parse_parameters(
        ZEND_NUM_ARGS() TSRMLS_CC
      , "sa"
      , &path
      , &path_len
      , &arr
    )) {
        RETURN_NULL();
    }
    typedef std::vector<std::string> Strings;
    zval **elm;
    HashPosition i;
    HashTable *hash = Z_ARRVAL_P(arr);
    Strings dv(zend_hash_num_elements(hash));
    for (
        zend_hash_internal_pointer_reset_ex(hash, &i);
        SUCCESS == zend_hash_get_current_data_ex(hash, (void**) &elm, &i);
        zend_hash_move_forward_ex(hash, &i)
    ) {
        dv.push_back(Z_STRVAL_PP(elm));
    }
    Strings rv(obj->impl->get(path, dv));
    array_init(return_value);
    for (int i = 0; i < rv.size(); ++i) {
        add_next_index_string(return_value, estrdup(rv[i].c_str()), 0);
    }
} // }}}
PHP_METHOD(iniphile, get_string) // {{{
{
    phpini *obj = PHPTHIS();
    char *path, *dflt;
    int path_len, dflt_len;
    if (FAILURE == zend_parse_parameters(
        ZEND_NUM_ARGS() TSRMLS_CC
      , "ss"
      , &path
      , &path_len
      , &dflt
      , &dflt_len
    )) {
        RETURN_NULL();
    }
    RETURN_STRING(estrdup(obj->impl->get(path, std::string(dflt)).c_str()), 0);
} // }}}
PHP_METHOD(iniphile, get_bool) // {{{
{
    phpini *obj = PHPTHIS();
    char *path;
    int path_len;
    zend_bool dflt;
    if (FAILURE == zend_parse_parameters(
        ZEND_NUM_ARGS() TSRMLS_CC
      , "sb"
      , &path
      , &path_len
      , &dflt
    )) {
        RETURN_NULL();
    }
    RETURN_BOOL(obj->impl->get(path, !!dflt));
} // }}}
PHP_METHOD(iniphile, get_long) // {{{
{
    phpini *obj = PHPTHIS();
    char *path;
    int path_len;
    long dflt;
    if (FAILURE == zend_parse_parameters(
        ZEND_NUM_ARGS() TSRMLS_CC
      , "sl"
      , &path
      , &path_len
      , &dflt
    )) {
        RETURN_NULL();
    }
    RETURN_LONG(obj->impl->get(path, dflt));
} // }}}
PHP_METHOD(iniphile, get_double) // {{{
{
    phpini *obj = PHPTHIS();
    char *path;
    int path_len;
    double dflt;
    if (FAILURE == zend_parse_parameters(
        ZEND_NUM_ARGS() TSRMLS_CC
      , "sd"
      , &path
      , &path_len
      , &dflt
    )) {
        RETURN_NULL();
    }
    RETURN_DOUBLE(obj->impl->get(path, dflt));
} // }}}

function_entry iniphile_methods[] = // {{{
{
    PHP_ME(iniphile, __construct, 0, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
    PHP_ME(iniphile, is_open, 0, ZEND_ACC_PUBLIC)
    PHP_ME(iniphile, path, 0, ZEND_ACC_PUBLIC)
    PHP_ME(iniphile, get_strings, 0, ZEND_ACC_PUBLIC)
    PHP_ME(iniphile, get_string, 0, ZEND_ACC_PUBLIC)
    PHP_ME(iniphile, get_bool, 0, ZEND_ACC_PUBLIC)
    PHP_ME(iniphile, get_long, 0, ZEND_ACC_PUBLIC)
    PHP_ME(iniphile, get_double, 0, ZEND_ACC_PUBLIC)
    {0, 0, 0}
}; // }}}

PHP_MINIT_FUNCTION(iniphile) // {{{
{
    zend_class_entry ce;
    INIT_CLASS_ENTRY(ce, "iniphile", iniphile_methods);
    iniphile_ce = zend_register_internal_class(&ce TSRMLS_CC);
    iniphile_ce->create_object = &iniphile_create_handler;
    memcpy(
        &iniphile_object_handlers
      , zend_get_std_object_handlers()
      , sizeof(zend_object_handlers)
    );
    iniphile_object_handlers.clone_obj = 0;

    return SUCCESS;
} // }}}

zend_module_entry iniphile_module_entry = // {{{
{
    STANDARD_MODULE_HEADER,
    PHP_INIPHILE_EXTNAME,
    0, // functions
    PHP_MINIT(iniphile),
    0, // MSHUTDOWN
    0, // RINIT
    0, // RSHUTDOWN
    0, // MINFO
    PHP_INIPHILE_EXTVER,
    STANDARD_MODULE_PROPERTIES
}; // }}}

#ifdef COMPILE_DL_INIPHILE
extern "C" {
ZEND_GET_MODULE(iniphile)
}
#endif
<|endoftext|>