123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511 |
- /* GCSx
- ** CLIPBOARD.CPP
- **
- ** Our internal clipboard, with cross-platform clipboard reading/writing
- ** added transparently as code becomes available
- */
- /*****************************************************************************
- ** Copyright (C) 2003-2006 Janson
- **
- ** This program is free software; you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation; either version 2 of the License, or
- ** (at your option) any later version.
- **
- ** This program 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 General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program; if not, write to the Free Software
- ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
- #include "SDL_syswm.h"
- #include "all.h"
- // Current internal clipboard
- ClipboardType clipType = CLIPBOARD_NONE;
- string* clipString = NULL;
- SDL_Surface* clipImage = NULL;
- Uint8* clipColors = NULL;
- int clipColorCount = 0;
- // (tile layer clipboard)
- int clipLayerCount = 0;
- int clipLayerWidth = 0;
- int clipLayerHeight = 0;
- Uint32** clipLayerData = NULL;
- Uint32** clipLayerExt = NULL;
- Uint32** clipLayerFx = NULL;
- const void** clipLayerTileSet = NULL;
- // (spawn clipboard)
- int clipSpawnCount = 0;
- int clipSpawnCountLayers = 0;
- SpawnEdit** clipSpawnData = NULL;
- int* clipSpawnLayers = NULL;
- ClipboardType typeInClipboard() { start_func
- return clipType;
- }
- int canConvertClipboard(ClipboardType type) { start_func
- // Text type
- #ifdef WIN32
- // WINDOWS CLIPBOARD
- if ((type == CLIPBOARD_TEXT_LINE) || (type == CLIPBOARD_TEXT_MULTI)) {
- if ((IsClipboardFormatAvailable(CF_TEXT)) || (IsClipboardFormatAvailable(CF_OEMTEXT))) return 1;
- return 0;
- }
- #else
- if ((type == CLIPBOARD_TEXT_LINE) && (clipType == CLIPBOARD_TEXT_MULTI)) return 1;
- if ((type == CLIPBOARD_TEXT_MULTI) && (clipType == CLIPBOARD_TEXT_LINE)) return 1;
- #endif
- // Other types
- if (type == clipType) return 1;
- return 0;
- }
- void clipboardClear() { start_func
- clipType = CLIPBOARD_NONE;
- delete clipString;
- clipString = NULL;
- delete[] clipColors;
- clipColors = NULL;
- clipColorCount = 0;
- if (clipImage) {
- SDL_FreeSurface(clipImage);
- clipImage = NULL;
- }
- if (clipLayerCount) {
- for (int pos = 0; pos < clipLayerCount; ++pos) {
- delete[] clipLayerData[pos];
- delete[] clipLayerExt[pos];
- delete[] clipLayerFx[pos];
- }
- delete[] clipLayerData;
- delete[] clipLayerExt;
- delete[] clipLayerFx;
- delete[] clipLayerTileSet;
- clipLayerData = NULL;
- clipLayerExt = NULL;
- clipLayerFx = NULL;
- clipLayerTileSet = NULL;
- clipLayerCount = 0;
- }
- if (clipSpawnCount) {
- for (int pos = 0; pos < clipSpawnCount; ++pos) {
- delete clipSpawnData[pos];
- }
- delete[] clipSpawnData;
- delete[] clipSpawnLayers;
- clipSpawnData = NULL;
- clipSpawnLayers = NULL;
- clipSpawnCount = 0;
- clipSpawnCountLayers = 0;
- }
- }
- void clipboardClearTileset(const void* tileset) { start_func
- if (clipType == CLIPBOARD_LAYER) {
- for (int pos = 0; pos < clipLayerCount; ++pos) {
- if (clipLayerTileSet[pos] == tileset) clipLayerTileSet[pos] = NULL;
- }
- }
- // @TODO: Spawns
- }
- void clipboardCopy(const string& text) { start_func
- // (clear any other types)
- clipboardClear();
- #ifdef WIN32
- // WINDOWS CLIPBOARD
- SDL_SysWMinfo wmInfo;
- SDL_VERSION(&wmInfo.version);
- SDL_GetWMInfo(&wmInfo);
- if (OpenClipboard(wmInfo.window)) {
- // Add \r before every \n
- string data = text;
- string::size_type pos = 0;
- while ((pos = data.find('\n', pos)) != string::npos) {
- data.insert(pos, 1, '\r');
- pos += 2;
- }
-
- EmptyClipboard();
- HGLOBAL hClipboardData;
- hClipboardData = GlobalAlloc(GMEM_DDESHARE, data.size() + 1);
- char* pchData = (char*)GlobalLock(hClipboardData);
- strcpy(pchData, data.c_str());
- GlobalUnlock(hClipboardData);
- SetClipboardData(CF_TEXT, hClipboardData);
- CloseClipboard();
- }
- #else
- // Store string
- delete clipString;
- clipString = NULL;
- clipString = new string(text);
-
- // Multiline?
- if (clipString->find_first_of('\n', 0) == string::npos) clipType = CLIPBOARD_TEXT_MULTI;
- else clipType = CLIPBOARD_TEXT_LINE;
- #endif
- }
- void clipboardCopy(SDL_Surface* surface, int x, int y, int width, int height) { start_func
- assert(surface);
- assert(width > 0);
- assert(height > 0);
- // (clear any other types)
- clipboardClear();
- // Attempt to allocate surface
- clipImage = createSurface32(width, height);
-
- // Blit
- blit(x, y, surface, 0, 0, clipImage, width, height);
- clipType = CLIPBOARD_IMAGE;
- }
- void clipboardCopy(const Uint8* colors, int count) { start_func
- assert(count);
- assert(colors);
-
- // (clear any other types)
- clipboardClear();
- // Attempt to allocate memory
- clipColors = new Uint8[count * 4];
-
- // Copy
- memcpy(clipColors, colors, count * 4);
- clipType = CLIPBOARD_RGBA;
- clipColorCount = count;
- }
- void clipboardCopy(const vector<SpawnEdit const*>& spawns, const vector<int>& layers) { start_func
- assert(!spawns.empty());
- assert(!layers.empty());
- assert(spawns.size() == layers.size());
-
- // (clear any other types)
- clipboardClear();
-
- // Prepare memory
- clipSpawnCount = spawns.size();
- clipSpawnData = new SpawnEdit*[clipSpawnCount];
- clipSpawnLayers = new int[clipSpawnCount];
-
- // Loop through twice- first to determine range of layers and x/y positions
- int baseX = 0;
- int baseY = 0;
- set<int> layersUsed;
- vector<SpawnEdit const*>::const_iterator sPos = spawns.begin();
- vector<SpawnEdit const*>::const_iterator sEnd = spawns.end();
- vector<int>::const_iterator lPos = layers.begin();
- vector<int>::const_iterator lEnd = layers.end();
- for (; sPos != sEnd; ++sPos, ++lPos) {
- if (sPos == spawns.begin()) {
- baseX = (*sPos)->getX();
- baseY = (*sPos)->getY();
- }
- else {
- if ((*sPos)->getX() < baseX) baseX = (*sPos)->getX();
- if ((*sPos)->getY() < baseY) baseY = (*sPos)->getY();
- }
- layersUsed.insert(*lPos);
- }
-
- // Prepare for normalization of layer numbers to be zero-based
- map<int, int> layerMap;
- int layerNormalized = 0;
- for (set<int>::iterator pos = layersUsed.begin(); pos != layersUsed.end(); ++pos) {
- layerMap[*pos] = layerNormalized++;
- }
- clipSpawnCountLayers = layerNormalized;
-
- // Second loop, to copy to clipboard as normalized data
- sPos = spawns.begin();
- lPos = layers.begin();
- for (int pos = 0; sPos != sEnd; ++pos, ++sPos, ++lPos) {
- SpawnEdit* newSpawn = new SpawnEdit(*sPos, NULL);
- // Normalize position
- newSpawn->setPos(newSpawn->getX() - baseX, newSpawn->getY() - baseY, 1);
- clipSpawnData[pos] = newSpawn;
- // Normalize layer
- clipSpawnLayers[pos] = layerMap[*lPos];
- }
-
- clipType = CLIPBOARD_SPAWN;
- }
- void clipboardCopy(int numLayers, const void* const* tileset, const Uint32* const* data, const Uint32* const* dataExt, const Uint32* const* dataFx, int x, int y, int width, int height, int pitch) { start_func
- assert(numLayers);
- assert(data);
- assert(width);
- assert(height);
- assert(pitch);
-
- // (clear any other types)
- clipboardClear();
- // Attempt to allocate arrays
- clipLayerData = new Uint32*[numLayers];
- clipLayerExt = new Uint32*[numLayers];
- clipLayerFx = new Uint32*[numLayers];
- clipLayerTileSet = new const void*[numLayers];
-
- // Fill arrays with NULL
- for (int pos = 0; pos < numLayers; ++pos) {
- assert(data[pos]);
- clipLayerData[pos] = NULL;
- clipLayerExt[pos] = NULL;
- clipLayerFx[pos] = NULL;
- clipLayerTileSet[pos] = NULL;
- }
-
- // Copy each layer
- for (int pos = 0; pos < numLayers; ++pos) {
- // Tileset
- if (tileset) clipLayerTileSet[pos] = tileset[pos];
-
- // Allocate data space and copy
- clipLayerData[pos] = new Uint32[width * height];
- matrixCopy(data[pos] + x + y * pitch, clipLayerData[pos], width * 4, height, pitch * 4, width * 4);
- // If applicable, allocate ext space and copy
- if ((dataExt) && (dataExt[pos])) {
- clipLayerExt[pos] = new Uint32[width * height];
- matrixCopy(dataExt[pos] + x + y * pitch, clipLayerExt[pos], width * 4, height, pitch * 4, width * 4);
- }
- // If applicable, allocate fx space and copy
- if ((dataFx) && (dataFx[pos])) {
- clipLayerFx[pos] = new Uint32[width * height];
- matrixCopy(dataFx[pos] + x + y * pitch, clipLayerFx[pos], width * 4, height, pitch * 4, width * 4);
- }
- }
-
- // Store layer stats
- clipLayerCount = numLayers;
- clipLayerWidth = width;
- clipLayerHeight = height;
- clipType = CLIPBOARD_LAYER;
- }
- void clipboardPasteTextLine(string& paste) { start_func
- #ifdef WIN32
- // WINDOWS CLIPBOARD
- SDL_SysWMinfo wmInfo;
- SDL_VERSION(&wmInfo.version);
- SDL_GetWMInfo(&wmInfo);
- if (OpenClipboard(wmInfo.window)) {
- if ((IsClipboardFormatAvailable(CF_TEXT)) || (IsClipboardFormatAvailable(CF_OEMTEXT))) {
- HANDLE hClipboardData = GetClipboardData(CF_TEXT);
- char *pchData = (char*)GlobalLock(hClipboardData);
- string data = pchData;
- GlobalUnlock(hClipboardData);
- CloseClipboard();
- // (cut at first \n or \r)
- string::size_type pos = data.find_first_of("\r\n", 0);
- if (pos == string::npos) paste = data;
- else paste = data.substr(0, pos);
- }
- else paste = blankString;
- }
- else paste = blankString;
- #else
- if (clipType == CLIPBOARD_TEXT_LINE) {
- assert(clipString);
- paste = *clipString;
- }
- else if (clipType == CLIPBOARD_TEXT_MULTI) {
- assert(clipString);
- // (cut at first \n)
- string::size_type pos = clipString->find_first_of('\n', 0);
- if (pos == string::npos) paste = *clipString;
- else paste = clipString->substr(0, pos);
- }
- else paste = blankString;
- #endif
- }
- void clipboardPasteTextMulti(string& paste) { start_func
- #ifdef WIN32
- // WINDOWS CLIPBOARD
- SDL_SysWMinfo wmInfo;
- SDL_VERSION(&wmInfo.version);
- SDL_GetWMInfo(&wmInfo);
- if (OpenClipboard(wmInfo.window)) {
- if ((IsClipboardFormatAvailable(CF_TEXT)) || (IsClipboardFormatAvailable(CF_OEMTEXT))) {
- HANDLE hClipboardData = GetClipboardData(CF_TEXT);
- char *pchData = (char*)GlobalLock(hClipboardData);
- string data = pchData;
- GlobalUnlock(hClipboardData);
- CloseClipboard();
- // (remove all \r)
- string::size_type pos = 0;
- while ((pos = data.find('\r', pos)) != string::npos) {
- data.erase(pos, 1);
- }
- paste = data;
- }
- else paste = blankString;
- }
- else paste = blankString;
- #else
- if ((clipType == CLIPBOARD_TEXT_LINE) || (clipType == CLIPBOARD_TEXT_MULTI)) {
- assert(clipString);
- paste = *clipString;
- }
- else paste = blankString;
- #endif
- }
- void clipboardPasteImageSize(int* width, int* height) { start_func
- assert(width);
- assert(height);
-
- if (clipType == CLIPBOARD_IMAGE) {
- assert(clipImage);
-
- *width = clipImage->w;
- *height = clipImage->h;
- }
- else {
- *width = 0;
- *height = 0;
- }
- }
- void clipboardPasteImage(SDL_Surface* dest, int x, int y) { start_func
- assert(dest);
-
- if (clipType == CLIPBOARD_IMAGE) {
- blit(0, 0, clipImage, x, y, dest, clipImage->w, clipImage->h);
- }
- }
- int clipboardPasteColor(Uint8* dest, int count) { start_func
- assert(dest);
-
- if (clipType == CLIPBOARD_RGBA) {
- if (count > clipColorCount) count = clipColorCount;
- memcpy(dest, clipColors, count * 4);
- return count;
- }
- return 0;
- }
- void clipboardPasteLayerInfo(int* numLayers, int* width, int* height) { start_func
- assert(numLayers);
- assert(width);
- assert(height);
-
- if (clipType == CLIPBOARD_LAYER) {
- *numLayers = clipLayerCount;
- *width = clipLayerWidth;
- *height = clipLayerHeight;
- }
- else {
- *numLayers = 0;
- *width = 0;
- *height = 0;
- }
- }
- void clipboardPasteLayerInfoDetails(int layer, const void** tileset, int* hasExt, int* hasFx) { start_func
- assert(tileset);
- assert(hasFx);
-
- if (clipType == CLIPBOARD_LAYER) {
- assert(layer >= 0);
- assert(layer < clipLayerCount);
-
- *tileset = clipLayerTileSet[layer];
- *hasExt = clipLayerExt[layer] ? 1 : 0;
- *hasFx = clipLayerFx[layer] ? 1 : 0;
- }
- else {
- *tileset = NULL;
- *hasExt = 0;
- *hasFx = 0;
- }
- }
- void clipboardPasteLayer(int layer, Uint32* data, Uint32* dataExt, Uint32* dataFx, int x, int y, int width, int height, int pitch, Uint32 defaultData, Uint32 defaultExt, Uint32 defaultFx) { start_func
- assert(data);
- assert(pitch);
- assert(width);
- assert(height);
-
- if (clipType == CLIPBOARD_LAYER) {
- assert(layer >= 0);
- assert(layer < clipLayerCount);
-
- // First, main data
- matrixCopy(clipLayerData[layer], data + x + y * pitch, min(width, clipLayerWidth) * 4, min(height, clipLayerHeight), clipLayerWidth * 4, pitch * 4);
- // Next, ext?
- if (dataExt) {
- // Copy or fill?
- if (clipLayerExt[layer]) {
- matrixCopy(clipLayerExt[layer], dataExt + x + y * pitch, min(width, clipLayerWidth) * 4, min(height, clipLayerHeight), clipLayerWidth * 4, pitch * 4);
- }
- else {
- for (int row = min(height, clipLayerHeight); row > 0; --row) {
- memSet32(dataExt + x + (y + row) * pitch, defaultExt, min(width, clipLayerWidth));
- }
- }
- }
- // Next, fx?
- if (dataFx) {
- // Copy or fill?
- if (clipLayerFx[layer]) {
- matrixCopy(clipLayerFx[layer], dataFx + x + y * pitch, min(width, clipLayerWidth) * 4, min(height, clipLayerHeight), clipLayerWidth * 4, pitch * 4);
- }
- else {
- for (int row = min(height, clipLayerHeight); row > 0; --row) {
- memSet32(dataFx + x + (y + row) * pitch, defaultFx, min(width, clipLayerWidth));
- }
- }
- }
- }
- }
- void clipboardPasteSpawnInfo(int* numSpawns, int* numLayers) { start_func
- assert(numSpawns);
- assert(numLayers);
-
- if (clipType == CLIPBOARD_SPAWN) {
- *numSpawns = clipSpawnCount;
- *numLayers = clipSpawnCountLayers;
- }
- else {
- *numSpawns = 0;
- *numLayers = 0;
- }
- }
- void clipboardPasteSpawn(int spawnNum, SpawnEdit* newSpawn, int* layerNum, int baseX, int baseY) { start_func
- assert(clipType == CLIPBOARD_SPAWN);
- assert(newSpawn);
- assert(layerNum);
- assert(spawnNum >= 0);
- assert(spawnNum < clipSpawnCount);
-
- *layerNum = clipSpawnLayers[spawnNum];
- newSpawn->setPos(clipSpawnData[spawnNum]->getX() + baseX, clipSpawnData[spawnNum]->getY() + baseY);
- newSpawn->setName(clipSpawnData[spawnNum]->getName());
- newSpawn->setScript(clipSpawnData[spawnNum]->getScript());
- newSpawn->setSprite(clipSpawnData[spawnNum]->getAnimgroup(), clipSpawnData[spawnNum]->getTileset(),
- clipSpawnData[spawnNum]->getSubid());
- }
|