+ Added support to paste/copy text from/to Windows clipboard.

+ Added support to process Ctrl+C / Ctrl+V / Ctrl+P keys in all entry fields.
+ Fixed a bug where file names for new sprites are lower-case always (in Windows).
This commit is contained in:
David Capello 2009-08-09 21:24:32 +00:00
parent f283a862d0
commit 8b8f13edf9
28 changed files with 342 additions and 183 deletions

View File

@ -1,3 +1,13 @@
2009-08-09 David A. Capello <davidcapello@gmail.com>
* src/dialogs/filesel.cpp (ase_file_selector): Fixed a bug where
new sprites where saved with lower case file names in Windows.
* src/jinete/jentry.cpp (entry_msg_proc): Process Windows
shortcuts to cut/paste (Ctrl+X, Ctrl+C, Ctrl+V).
* src/jinete/jclipboard.cpp: Added support for Windows clipboard.
2009-08-04 David A. Capello <davidcapello@gmail.com>
* Version 0.7 released.

View File

@ -2,6 +2,15 @@
NEWS
===================================
0.7.1
-----
+ Added support to paste/copy text from/to Windows clipboard.
+ Added support to process Ctrl+C / Ctrl+V / Ctrl+P keys in all
entry fields.
+ Fixed a bug where file names for new sprites are lower-case always
(in Windows).
0.7
---

View File

@ -24,7 +24,7 @@
/* general information */
#define PACKAGE "ASE"
#define VERSION "0.7"
#define VERSION "0.7.1"
#define WEBSITE "http://www.aseprite.org/"
#define COPYRIGHT "Copyright (C) 2001-2009 David Capello"

View File

@ -6,8 +6,6 @@
ASE = aseprite$(EXE)
COMMON_SOURCES = \
src/ase/context.cpp \
src/ase/ui_context.cpp \
src/commands/cmd_about.cpp \
src/commands/cmd_advanced_mode.cpp \
src/commands/cmd_background_from_layer.cpp \
@ -235,7 +233,9 @@ COMMON_OBJS = $(addprefix $(OBJ_DIR)/, \
$(notdir $(basename $(COMMON_SOURCES)))))
ASE_SOURCES = \
src/context.cpp \
src/main.cpp \
src/ui_context.cpp \
src/undoable.cpp \
$(COMMON_SOURCES)

View File

@ -21,7 +21,7 @@
#include <allegro.h>
#include "jinete/jinete.h"
#include "ase/ui_context.h"
#include "ui_context.h"
#include "commands/commands.h"
#include "core/app.h"
#include "modules/sprites.h"

View File

@ -22,7 +22,7 @@
#include "jinete/jinete.h"
#include "ase/ui_context.h"
#include "ui_context.h"
#include "commands/commands.h"
#include "core/app.h"
#include "core/cfg.h"

View File

@ -20,7 +20,7 @@
#include "jinete/jinete.h"
#include "ase/ui_context.h"
#include "ui_context.h"
#include "commands/commands.h"
#include "core/app.h"
#include "modules/sprites.h"

View File

@ -24,7 +24,7 @@
#include "jinete/jinete.h"
#include "ase/ui_context.h"
#include "ui_context.h"
#include "commands/commands.h"
#include "console/console.h"
#include "core/app.h"

View File

@ -23,7 +23,7 @@
#include "jinete/jinete.h"
#include "ase/ui_context.h"
#include "ui_context.h"
#include "commands/commands.h"
#include "console/console.h"
#include "core/app.h"

View File

@ -24,7 +24,7 @@
#include "jinete/jinete.h"
#include "ase/ui_context.h"
#include "ui_context.h"
#include "commands/commands.h"
#include "core/app.h"
#include "modules/sprites.h"

View File

@ -21,7 +21,7 @@
#include <cassert>
#include <algorithm>
#include "ase/context.h"
#include "context.h"
#include "raster/sprite.h"
Context::Context()

View File

@ -31,7 +31,7 @@
#include "jinete/jintern.h"
#include "ase_exception.h"
#include "ase/ui_context.h"
#include "ui_context.h"
#include "commands/commands.h"
#include "console/console.h"
#include "core/app.h"

View File

@ -243,8 +243,9 @@ again:
// check if the user specified in "fn" a item of "fileview"
const FileItemList& children = fileview_get_filelist(fileview);
jstring fn2 = fn;
#ifdef ALLEGRO_WINDOWS
fn.tolower();
fn2.tolower();
#endif
for (FileItemList::const_iterator
@ -255,7 +256,7 @@ again:
#ifdef ALLEGRO_WINDOWS
child_name.tolower();
#endif
if (child_name == fn) {
if (child_name == fn2) {
enter_folder = *it;
buf = fileitem_get_filename(enter_folder);
break;

View File

@ -31,19 +31,65 @@
#include "config.h"
#ifdef ALLEGRO_WINDOWS
#include <allegro.h>
#include <winalleg.h>
#endif
#include "jinete/jbase.h"
static char *clipboard_text = NULL;
const char *jclipboard_get_text()
{
return clipboard_text;
}
void jclipboard_set_text(const char *text)
static void lowlevel_set_clipboard_text(const char *text)
{
if (clipboard_text)
jfree(clipboard_text);
clipboard_text = text ? jstrdup(text) : NULL;
}
const char* jclipboard_get_text()
{
#ifdef ALLEGRO_WINDOWS
if (IsClipboardFormatAvailable(CF_TEXT)) {
if (OpenClipboard(win_get_window())) {
HGLOBAL hglobal = GetClipboardData(CF_TEXT);
if (hglobal != NULL) {
LPSTR lpstr = static_cast<LPSTR>(GlobalLock(hglobal));
if (lpstr != NULL) {
lowlevel_set_clipboard_text(lpstr);
GlobalUnlock(hglobal);
}
}
CloseClipboard();
}
}
#endif
return clipboard_text;
}
void jclipboard_set_text(const char *text)
{
lowlevel_set_clipboard_text(text);
#ifdef ALLEGRO_WINDOWS
if (IsClipboardFormatAvailable(CF_TEXT)) {
if (OpenClipboard(win_get_window())) {
EmptyClipboard();
if (clipboard_text) {
int len = ustrlen(clipboard_text);
HGLOBAL hglobal = GlobalAlloc(GMEM_MOVEABLE, sizeof(char)*(len+1));
LPSTR lpstr = static_cast<LPSTR>(GlobalLock(hglobal));
memcpy(lpstr, clipboard_text, len);
GlobalUnlock(hglobal);
SetClipboardData(CF_TEXT, hglobal);
}
CloseClipboard();
}
}
#endif
}

View File

@ -29,12 +29,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef JINETE_CLIPBRD_H
#define JINETE_CLIPBRD_H
#ifndef ASE_JINETE_JCLIPBOARD_H
#define ASE_JINETE_JCLIPBOARD_H
#include "jinete/jbase.h"
const char* jclipboard_get_text();
void jclipboard_set_text(const char* text);
#endif /* JINETE_CLIPBRD_H */
#endif // ASE_JINETE_JCLIPBOARD_H

View File

@ -42,11 +42,30 @@
#include "jinete/jmessage.h"
#include "jinete/jrect.h"
#include "jinete/jsystem.h"
#include "jinete/jstring.h"
#include "jinete/jtheme.h"
#include "jinete/jwidget.h"
#define CHARACTER_LENGTH(f, c) ((f)->vtable->char_length((f), (c)))
namespace EntryCmd {
enum Type {
NoOp,
InsertChar,
ForwardChar,
ForwardWord,
BackwardChar,
BackwardWord,
BeginningOfLine,
EndOfLine,
DeleteForward,
DeleteBackward,
Cut,
Copy,
Paste,
};
}
typedef struct Entry
{
int maxsize;
@ -66,6 +85,7 @@ static void entry_request_size(JWidget widget, int *w, int *h);
static int entry_get_cursor_from_mouse(JWidget widget, JMessage msg);
static void entry_execute_cmd(JWidget widget, EntryCmd::Type cmd, int ascii, bool shift_pressed);
static void entry_forward_word(JWidget widget);
static void entry_backward_word(JWidget widget);
@ -273,175 +293,75 @@ static bool entry_msg_proc(JWidget widget, JMessage msg)
case JM_KEYPRESSED:
if (jwidget_has_focus(widget) && !jentry_is_readonly(widget)) {
std::string text = widget->text();
int c, selbeg, selend;
jtheme_entry_info(widget, NULL, NULL, NULL, &selbeg, &selend);
// Command to execute
EntryCmd::Type cmd = EntryCmd::NoOp;
switch (msg->key.scancode) {
case KEY_LEFT:
/* selection */
if (msg->any.shifts & KB_SHIFT_FLAG) {
if (entry->select < 0)
entry->select = entry->cursor;
}
else
entry->select = -1;
/* backward word */
if (msg->any.shifts & KB_CTRL_FLAG)
entry_backward_word(widget);
/* backward char */
else if (entry->cursor > 0)
entry->cursor--;
cmd = EntryCmd::BackwardWord;
else
cmd = EntryCmd::BackwardChar;
break;
case KEY_RIGHT:
/* selection */
if (msg->any.shifts & KB_SHIFT_FLAG) {
if (entry->select < 0)
entry->select = entry->cursor;
}
else
entry->select = -1;
/* forward word */
if (msg->any.shifts & KB_CTRL_FLAG)
entry_forward_word(widget);
/* forward char */
else if (entry->cursor < text.size())
entry->cursor++;
cmd = EntryCmd::ForwardWord;
else
cmd = EntryCmd::ForwardChar;
break;
case KEY_HOME:
/* selection */
if (msg->any.shifts & KB_SHIFT_FLAG) {
if (entry->select < 0)
entry->select = entry->cursor;
}
else
entry->select = -1;
entry->cursor = 0;
cmd = EntryCmd::BeginningOfLine;
break;
case KEY_END:
/* selection */
if (msg->any.shifts & KB_SHIFT_FLAG) {
if (entry->select < 0)
entry->select = entry->cursor;
}
else
entry->select = -1;
entry->cursor = text.size();
cmd = EntryCmd::EndOfLine;
break;
case KEY_DEL:
// delete the entire selection
if (selbeg >= 0) {
// *cut* text!
if (msg->any.shifts & KB_SHIFT_FLAG) {
char buf[1024];
ustrcpy(buf, empty_string);
for (c=selbeg; c<=selend; c++)
uinsert(buf, ustrlen(buf), text[c]);
jclipboard_set_text(buf);
}
// remove text
text.erase(selbeg, selend-selbeg+1);
entry->cursor = selbeg;
}
/* delete the next character */
else {
if (entry->cursor < text.size())
text.erase(entry->cursor, 1);
}
entry->select = -1;
if (msg->any.shifts & KB_SHIFT_FLAG)
cmd = EntryCmd::Cut;
else
cmd = EntryCmd::DeleteForward;
break;
case KEY_INSERT:
/* *paste* text */
if (msg->any.shifts & KB_SHIFT_FLAG) {
const char *clipboard;
if ((clipboard = jclipboard_get_text())) {
/* delete the entire selection */
if (selbeg >= 0) {
text.erase(selbeg, selend-selbeg+1);
entry->cursor = selbeg;
entry->select = -1;
}
/* paste text */
for (c=0; c<ustrlen(clipboard); c++)
if (text.size() < entry->maxsize)
text.insert(entry->cursor+c, 1, ugetat(clipboard, c));
else
break;
jentry_set_cursor_pos(widget, entry->cursor+c);
}
}
/* *copy* text */
else if ((selbeg >= 0) && (msg->any.shifts & KB_CTRL_FLAG)) {
char buf[1024];
ustrcpy(buf, empty_string);
for (c=selbeg; c<=selend; c++)
uinsert(buf, ustrlen(buf), text[c]);
jclipboard_set_text(buf);
}
if (msg->any.shifts & KB_SHIFT_FLAG)
cmd = EntryCmd::Paste;
else if (msg->any.shifts & KB_CTRL_FLAG)
cmd = EntryCmd::Copy;
break;
case KEY_BACKSPACE:
/* delete the entire selection */
if (selbeg >= 0) {
text.erase(selbeg, selend-selbeg+1);
entry->cursor = selbeg;
}
/* delete the previous character */
else {
if (entry->cursor > 0)
text.erase(--entry->cursor, 1);
}
entry->select = -1;
cmd = EntryCmd::DeleteBackward;
break;
default:
if (msg->key.ascii >= 32) {
/* delete the entire selection */
if (selbeg >= 0) {
text.erase(selbeg, selend-selbeg+1);
entry->cursor = selbeg;
cmd = EntryCmd::InsertChar;
}
else {
// map common Windows shortcuts for Cut/Copy/Paste
if ((msg->any.shifts & (KB_CTRL_FLAG | KB_SHIFT_FLAG | KB_ALT_FLAG)) == KB_CTRL_FLAG) {
switch (msg->key.scancode) {
case KEY_X: cmd = EntryCmd::Cut; break;
case KEY_C: cmd = EntryCmd::Copy; break;
case KEY_V: cmd = EntryCmd::Paste; break;
}
}
}
/* put the character */
if (text.size() < entry->maxsize)
text.insert(entry->cursor++, 1, msg->key.ascii);
entry->select = -1;
break;
}
else
if (cmd == EntryCmd::NoOp)
return false;
}
if (text != widget->text()) {
widget->text(text.c_str());
jwidget_emit_signal(widget, JI_SIGNAL_ENTRY_CHANGE);
}
jentry_set_cursor_pos(widget, entry->cursor);
widget->dirty();
return TRUE;
entry_execute_cmd(widget, cmd,
msg->key.ascii,
(msg->any.shifts & KB_SHIFT_FLAG) ? true: false);
return true;
}
break;
@ -587,6 +507,177 @@ static int entry_get_cursor_from_mouse(JWidget widget, JMessage msg)
return cursor;
}
static void entry_execute_cmd(JWidget widget, EntryCmd::Type cmd,
int ascii, bool shift_pressed)
{
Entry* entry = reinterpret_cast<Entry*>(jwidget_get_data(widget, JI_ENTRY));
std::string text = widget->text();
int c, selbeg, selend;
jtheme_entry_info(widget, NULL, NULL, NULL, &selbeg, &selend);
switch (cmd) {
case EntryCmd::InsertChar:
// delete the entire selection
if (selbeg >= 0) {
text.erase(selbeg, selend-selbeg+1);
entry->cursor = selbeg;
}
// put the character
if (text.size() < entry->maxsize)
text.insert(entry->cursor++, 1, ascii);
entry->select = -1;
break;
case EntryCmd::BackwardChar:
case EntryCmd::BackwardWord:
// selection
if (shift_pressed) {
if (entry->select < 0)
entry->select = entry->cursor;
}
else
entry->select = -1;
// backward word
if (cmd == EntryCmd::BackwardWord) {
entry_backward_word(widget);
}
// backward char
else if (entry->cursor > 0) {
entry->cursor--;
}
break;
case EntryCmd::ForwardChar:
case EntryCmd::ForwardWord:
// selection
if (shift_pressed) {
if (entry->select < 0)
entry->select = entry->cursor;
}
else
entry->select = -1;
// forward word
if (cmd == EntryCmd::ForwardWord) {
entry_forward_word(widget);
}
// forward char
else if (entry->cursor < text.size()) {
entry->cursor++;
}
break;
case EntryCmd::BeginningOfLine:
// selection
if (shift_pressed) {
if (entry->select < 0)
entry->select = entry->cursor;
}
else
entry->select = -1;
entry->cursor = 0;
break;
case EntryCmd::EndOfLine:
// selection
if (shift_pressed) {
if (entry->select < 0)
entry->select = entry->cursor;
}
else
entry->select = -1;
entry->cursor = text.size();
break;
case EntryCmd::DeleteForward:
case EntryCmd::Cut:
// delete the entire selection
if (selbeg >= 0) {
// *cut* text!
if (cmd == EntryCmd::Cut) {
jstring buf = text.substr(selbeg, selend - selbeg + 1);
jclipboard_set_text(buf.c_str());
}
// remove text
text.erase(selbeg, selend-selbeg+1);
entry->cursor = selbeg;
}
// delete the next character
else {
if (entry->cursor < text.size())
text.erase(entry->cursor, 1);
}
entry->select = -1;
break;
case EntryCmd::Paste: {
const char *clipboard;
if ((clipboard = jclipboard_get_text())) {
// delete the entire selection
if (selbeg >= 0) {
text.erase(selbeg, selend-selbeg+1);
entry->cursor = selbeg;
entry->select = -1;
}
// paste text
for (c=0; c<ustrlen(clipboard); c++)
if (text.size() < entry->maxsize)
text.insert(entry->cursor+c, 1, ugetat(clipboard, c));
else
break;
jentry_set_cursor_pos(widget, entry->cursor+c);
}
break;
}
case EntryCmd::Copy:
if (selbeg >= 0) {
jstring buf = text.substr(selbeg, selend - selbeg + 1);
jclipboard_set_text(buf.c_str());
}
break;
case EntryCmd::DeleteBackward:
// delete the entire selection
if (selbeg >= 0) {
text.erase(selbeg, selend-selbeg+1);
entry->cursor = selbeg;
}
// delete the previous character
else {
if (entry->cursor > 0)
text.erase(--entry->cursor, 1);
}
entry->select = -1;
break;
}
if (text != widget->text()) {
widget->text(text.c_str());
jwidget_emit_signal(widget, JI_SIGNAL_ENTRY_CHANGE);
}
jentry_set_cursor_pos(widget, entry->cursor);
widget->dirty();
}
#define IS_WORD_CHAR(ch) \
(!((!ch) || (uisspace(ch)) || \
((ch) == '/') || ((ch) == OTHER_PATH_SEPARATOR)))

View File

@ -32,6 +32,8 @@
#include "config.h"
#include "jinete/jbase.h"
#include "jinete/jtheme.h"
#include "jinete/jclipboard.h"
#ifdef MEMLEAK
void _jmemleak_init();
@ -68,6 +70,12 @@ Jinete::Jinete()
Jinete::~Jinete()
{
// finish theme
ji_set_theme(NULL);
// destroy clipboard
jclipboard_set_text(NULL);
// shutdown system
_ji_theme_exit();
_ji_widgets_exit();

View File

@ -221,12 +221,6 @@ void jmanager_free(JWidget widget)
/* no more cursor */
jmouse_set_cursor(JI_CURSOR_NULL);
/* finish theme */
ji_set_theme(NULL);
/* destroy clipboard */
jclipboard_set_text(NULL);
/* destroy this widget */
jwidget_free(widget);

View File

@ -29,8 +29,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef JINETE_STRING_H
#define JINETE_STRING_H
#ifndef ASE_JINETE_STRING_H
#define ASE_JINETE_STRING_H
#include <string>
@ -126,4 +126,4 @@ inline jstring operator+(const char* _s1, const jstring& _s2)
return _res;
}
#endif /* JINETE_STRING_H */
#endif // ASE_JINETE_STRING_H

View File

@ -21,7 +21,7 @@
#include "jinete/jinete.h"
#include "sprite_wrappers.h"
#include "ase/ui_context.h"
#include "ui_context.h"
#include "core/app.h"
#include "modules/editors.h"
#include "modules/gui.h"

View File

@ -32,7 +32,7 @@
#include "jinete/jinete.h"
#include "jinete/jintern.h"
#include "ase/ui_context.h"
#include "ui_context.h"
#include "commands/commands.h"
#include "console/console.h"
#include "core/app.h"

View File

@ -22,7 +22,7 @@
#include "jinete/jlist.h"
#include "ase/ui_context.h"
#include "ui_context.h"
#include "effect/effect.h"
#include "modules/sprites.h"
#include "raster/cel.h"

View File

@ -16,13 +16,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef SPRITE_WRAPPERS_H
#define SPRITE_WRAPPERS_H
#ifndef ASE_SPRITE_WRAPPERS_H
#define ASE_SPRITE_WRAPPERS_H
#include <list>
#include <exception>
#include "ase_exception.h"
#include "ase/ui_context.h"
#include "ui_context.h"
#include "raster/sprite.h"
class Context;
@ -245,4 +245,4 @@ public:
};
#endif // SPRITE_WRAPPERS_H
#endif // ASE_SPRITE_WRAPPERS_H

View File

@ -21,7 +21,7 @@
#include <cassert>
#include <allegro/file.h>
#include "ase/ui_context.h"
#include "ui_context.h"
#include "core/app.h"
#include "modules/editors.h"
#include "raster/sprite.h"

View File

@ -19,7 +19,7 @@
#ifndef ASE_UI_CONTEXT_H
#define ASE_UI_CONTEXT_H
#include "ase/context.h"
#include "context.h"
class UIContext : public Context
{

View File

@ -16,8 +16,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef UNDOABLE_H
#define UNDOABLE_H
#ifndef ASE_UNDOABLE_H
#define ASE_UNDOABLE_H
class Cel;
class Layer;
@ -103,4 +103,4 @@ public:
};
#endif // UNDOABLE_H
#endif // ASE_UNDOABLE_H

View File

@ -26,7 +26,7 @@
#include "jinete/jinete.h"
#include "ase/ui_context.h"
#include "ui_context.h"
#include "commands/commands.h"
#include "core/app.h"
#include "core/cfg.h"