2008-10-26 02:22:34 +03:00
|
|
|
/*
|
2010-07-25 00:18:56 +04:00
|
|
|
* Copyright 2008-2010 Chris Young <chris@unsatisfactorysoftware.co.uk>
|
2008-10-26 02:22:34 +03:00
|
|
|
*
|
|
|
|
* This file is part of NetSurf, http://www.netsurf-browser.org/
|
|
|
|
*
|
|
|
|
* NetSurf 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; version 2 of the License.
|
|
|
|
*
|
|
|
|
* NetSurf 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, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "desktop/gui.h"
|
2010-07-24 20:39:37 +04:00
|
|
|
#include "utils/utf8.h"
|
|
|
|
#include "desktop/selection.h"
|
2010-07-24 23:57:27 +04:00
|
|
|
#include "desktop/textinput.h"
|
2010-07-24 20:39:37 +04:00
|
|
|
|
2008-10-26 02:22:34 +03:00
|
|
|
#include "amiga/iff_cset.h"
|
|
|
|
#include "amiga/options.h"
|
|
|
|
#include "amiga/gui.h"
|
|
|
|
#include "amiga/utf8.h"
|
2009-05-16 21:04:28 +04:00
|
|
|
#include "amiga/bitmap.h"
|
2009-05-19 11:23:56 +04:00
|
|
|
#include "amiga/iff_dr2d.h"
|
2010-07-24 20:39:37 +04:00
|
|
|
#include "amiga/menu.h"
|
2010-10-30 15:20:53 +04:00
|
|
|
#include "amiga/drag.h"
|
2010-07-24 20:39:37 +04:00
|
|
|
|
|
|
|
#include <proto/iffparse.h>
|
|
|
|
#include <proto/intuition.h>
|
|
|
|
#include <proto/exec.h>
|
|
|
|
#include <proto/datatypes.h>
|
2010-05-04 00:49:15 +04:00
|
|
|
#include <proto/diskfont.h>
|
2010-07-24 20:39:37 +04:00
|
|
|
|
2010-05-04 00:49:15 +04:00
|
|
|
#include <diskfont/diskfonttag.h>
|
2010-07-24 20:39:37 +04:00
|
|
|
#include <datatypes/textclass.h>
|
|
|
|
#include <datatypes/pictureclass.h>
|
2008-10-26 02:22:34 +03:00
|
|
|
|
|
|
|
struct IFFHandle *iffh = NULL;
|
|
|
|
|
2010-07-24 23:57:27 +04:00
|
|
|
bool ami_add_to_clipboard(const char *text, size_t length, bool space);
|
|
|
|
|
2010-10-24 22:07:11 +04:00
|
|
|
struct IFFHandle *ami_clipboard_init_internal(int unit)
|
2008-10-26 02:22:34 +03:00
|
|
|
{
|
2010-10-24 22:07:11 +04:00
|
|
|
struct IFFHandle *iffhandle = NULL;
|
|
|
|
|
|
|
|
if(iffhandle = AllocIFF())
|
2008-10-26 02:22:34 +03:00
|
|
|
{
|
2010-10-24 22:07:11 +04:00
|
|
|
if(iffhandle->iff_Stream = (ULONG)OpenClipboard(unit))
|
2008-10-26 02:22:34 +03:00
|
|
|
{
|
2010-10-24 22:07:11 +04:00
|
|
|
InitIFFasClip(iffhandle);
|
2008-10-26 02:22:34 +03:00
|
|
|
}
|
|
|
|
}
|
2010-10-24 22:07:11 +04:00
|
|
|
|
|
|
|
return iffhandle;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ami_clipboard_init(void)
|
|
|
|
{
|
|
|
|
iffh = ami_clipboard_init_internal(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ami_clipboard_free_internal(struct IFFHandle *iffhandle)
|
|
|
|
{
|
|
|
|
if(iffhandle->iff_Stream) CloseClipboard((struct ClipboardHandle *)iffhandle->iff_Stream);
|
|
|
|
if(iffhandle) FreeIFF(iffhandle);
|
2008-10-26 02:22:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void ami_clipboard_free(void)
|
|
|
|
{
|
2010-10-24 22:07:11 +04:00
|
|
|
ami_clipboard_free_internal(iffh);
|
2008-10-26 02:22:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void gui_start_selection(struct gui_window *g)
|
|
|
|
{
|
2010-07-24 20:39:37 +04:00
|
|
|
if(!g) return;
|
|
|
|
if(!g->shared->win) return;
|
2010-09-28 22:03:03 +04:00
|
|
|
if(g->shared->bw->browser_window_type != BROWSER_WINDOW_NORMAL) return;
|
|
|
|
if(option_kiosk_mode == true) return;
|
2010-07-24 20:39:37 +04:00
|
|
|
|
|
|
|
OnMenu(g->shared->win, AMI_MENU_CLEAR);
|
|
|
|
OnMenu(g->shared->win, AMI_MENU_COPY);
|
|
|
|
|
|
|
|
if(selection_read_only(g->shared->bw->sel) == false)
|
|
|
|
OnMenu(g->shared->win, AMI_MENU_CUT);
|
|
|
|
}
|
|
|
|
|
|
|
|
void gui_clear_selection(struct gui_window *g)
|
|
|
|
{
|
|
|
|
if(!g) return;
|
|
|
|
if(!g->shared->win) return;
|
2010-09-28 22:03:03 +04:00
|
|
|
if(g->shared->bw->browser_window_type != BROWSER_WINDOW_NORMAL) return;
|
|
|
|
if(option_kiosk_mode == true) return;
|
2010-07-24 20:39:37 +04:00
|
|
|
|
|
|
|
OffMenu(g->shared->win, AMI_MENU_CLEAR);
|
|
|
|
OffMenu(g->shared->win, AMI_MENU_CUT);
|
|
|
|
OffMenu(g->shared->win, AMI_MENU_COPY);
|
2008-10-26 02:22:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void gui_paste_from_clipboard(struct gui_window *g, int x, int y)
|
|
|
|
{
|
|
|
|
/* This and the other clipboard code is heavily based on the RKRM examples */
|
|
|
|
struct ContextNode *cn;
|
|
|
|
ULONG rlen=0,error;
|
|
|
|
struct CSet cset;
|
|
|
|
char *clip;
|
2008-11-02 03:21:49 +03:00
|
|
|
STRPTR readbuf = AllocVec(1024,MEMF_PRIVATE | MEMF_CLEAR);
|
2008-10-26 02:22:34 +03:00
|
|
|
|
|
|
|
cset.CodeSet = 0;
|
|
|
|
|
|
|
|
if(OpenIFF(iffh,IFFF_READ)) return;
|
|
|
|
if(StopChunk(iffh,ID_FTXT,ID_CHRS)) return;
|
|
|
|
if(StopChunk(iffh,ID_FTXT,ID_CSET)) return;
|
|
|
|
|
|
|
|
while(1)
|
|
|
|
{
|
|
|
|
error = ParseIFF(iffh,IFFPARSE_SCAN);
|
|
|
|
if(error == IFFERR_EOC) continue;
|
|
|
|
else if(error) break;
|
|
|
|
|
|
|
|
cn = CurrentChunk(iffh);
|
|
|
|
|
|
|
|
if((cn)&&(cn->cn_Type == ID_FTXT)&&(cn->cn_ID == ID_CSET))
|
|
|
|
{
|
|
|
|
rlen = ReadChunkBytes(iffh,&cset,24);
|
|
|
|
}
|
|
|
|
|
|
|
|
if((cn)&&(cn->cn_Type == ID_FTXT)&&(cn->cn_ID == ID_CHRS))
|
|
|
|
{
|
|
|
|
while((rlen = ReadChunkBytes(iffh,readbuf,1024)) > 0)
|
|
|
|
{
|
|
|
|
if(cset.CodeSet == 0)
|
|
|
|
{
|
|
|
|
utf8_from_local_encoding(readbuf,rlen,&clip);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-05-04 00:49:15 +04:00
|
|
|
utf8_from_enc(readbuf,
|
|
|
|
ObtainCharsetInfo(DFCS_NUMBER, cset.CodeSet, DFCS_MIMENAME),
|
|
|
|
rlen, &clip);
|
2008-10-26 02:22:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
browser_window_paste_text(g->shared->bw,clip,rlen,true);
|
|
|
|
}
|
|
|
|
if(rlen < 0) error = rlen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CloseIFF(iffh);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool gui_empty_clipboard(void)
|
|
|
|
{
|
2010-07-24 23:57:27 +04:00
|
|
|
/* Put a half-completed FTXT on the clipboard and leave it open for more additions */
|
|
|
|
|
|
|
|
struct CSet cset = {0};
|
|
|
|
|
|
|
|
if(!(OpenIFF(iffh,IFFF_WRITE)))
|
|
|
|
{
|
|
|
|
if(!(PushChunk(iffh,ID_FTXT,ID_FORM,IFFSIZE_UNKNOWN)))
|
|
|
|
{
|
|
|
|
if(option_utf8_clipboard)
|
|
|
|
{
|
|
|
|
if(!(PushChunk(iffh,0,ID_CSET,24)))
|
|
|
|
{
|
|
|
|
cset.CodeSet = 106; // UTF-8
|
|
|
|
WriteChunkBytes(iffh,&cset,24);
|
|
|
|
PopChunk(iffh);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PopChunk(iffh);
|
2010-07-25 00:18:56 +04:00
|
|
|
return false;
|
2010-07-24 23:57:27 +04:00
|
|
|
}
|
2010-07-25 00:18:56 +04:00
|
|
|
return true;
|
2010-07-24 23:57:27 +04:00
|
|
|
}
|
2010-07-25 00:18:56 +04:00
|
|
|
return false;
|
2008-10-26 02:22:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool gui_add_to_clipboard(const char *text, size_t length, bool space)
|
2010-07-24 23:57:27 +04:00
|
|
|
{
|
|
|
|
/* This might crash or at least not work if gui_empty_clipboard isn't called first,
|
|
|
|
and gui_commit_clipboard after.
|
|
|
|
These only seem to be called from desktop/textinput.c in this specific order, if they
|
|
|
|
are added elsewhere this might need a rewrite. */
|
|
|
|
|
|
|
|
if(!(PushChunk(iffh,0,ID_CHRS,IFFSIZE_UNKNOWN)))
|
|
|
|
{
|
|
|
|
if(text)
|
|
|
|
{
|
2010-12-20 22:06:57 +03:00
|
|
|
if(!ami_add_to_clipboard(text, length, space)) return false;
|
2010-07-24 23:57:27 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
PopChunk(iffh);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PopChunk(iffh);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ami_add_to_clipboard(const char *text, size_t length, bool space)
|
2008-10-26 02:22:34 +03:00
|
|
|
{
|
|
|
|
char *buffer;
|
2010-07-24 23:57:27 +04:00
|
|
|
|
2008-10-26 02:22:34 +03:00
|
|
|
if(option_utf8_clipboard)
|
|
|
|
{
|
|
|
|
WriteChunkBytes(iffh,text,length);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
utf8_to_local_encoding(text,length,&buffer);
|
|
|
|
if(buffer) WriteChunkBytes(iffh,buffer,strlen(buffer));
|
|
|
|
ami_utf8_free(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(space) WriteChunkBytes(iffh," ",1);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool gui_commit_clipboard(void)
|
|
|
|
{
|
|
|
|
if(iffh) CloseIFF(iffh);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ami_clipboard_copy(const char *text, size_t length, struct box *box,
|
|
|
|
void *handle, const char *whitespace_text,size_t whitespace_length)
|
|
|
|
{
|
|
|
|
if(!(PushChunk(iffh,0,ID_CHRS,IFFSIZE_UNKNOWN)))
|
|
|
|
{
|
|
|
|
if (whitespace_text)
|
|
|
|
{
|
2010-07-24 23:57:27 +04:00
|
|
|
if(!ami_add_to_clipboard(whitespace_text,whitespace_length, false)) return false;
|
2008-10-26 02:22:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if(text)
|
|
|
|
{
|
2010-07-24 23:57:27 +04:00
|
|
|
if (!ami_add_to_clipboard(text, length, box->space)) return false;
|
2008-10-26 02:22:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
PopChunk(iffh);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PopChunk(iffh);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool gui_copy_to_clipboard(struct selection *s)
|
|
|
|
{
|
2010-07-25 00:18:56 +04:00
|
|
|
if(!gui_empty_clipboard()) return false;
|
2008-10-26 02:22:34 +03:00
|
|
|
|
2010-07-25 00:18:56 +04:00
|
|
|
if (s->defined && selection_traverse(s, ami_clipboard_copy, NULL))
|
2008-10-26 02:22:34 +03:00
|
|
|
{
|
2010-07-25 00:18:56 +04:00
|
|
|
gui_commit_clipboard();
|
|
|
|
return true;
|
2008-10-26 02:22:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-07-24 23:57:27 +04:00
|
|
|
void ami_drag_selection(struct selection *s)
|
|
|
|
{
|
|
|
|
struct box *text_box;
|
2010-07-28 01:41:21 +04:00
|
|
|
ULONG x;
|
|
|
|
ULONG y;
|
2010-10-24 22:07:11 +04:00
|
|
|
struct IFFHandle *old_iffh = iffh;
|
2010-07-28 01:41:21 +04:00
|
|
|
struct gui_window_2 *gwin = ami_window_at_pointer();
|
2010-07-24 23:57:27 +04:00
|
|
|
|
2010-07-28 01:41:21 +04:00
|
|
|
if(!gwin)
|
|
|
|
{
|
|
|
|
DisplayBeep(scrn);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
x = gwin->win->MouseX;
|
|
|
|
y = gwin->win->MouseY;
|
|
|
|
|
|
|
|
if(text_box = ami_text_box_at_point(gwin, &x, &y))
|
2010-07-24 23:57:27 +04:00
|
|
|
{
|
2010-10-24 22:07:11 +04:00
|
|
|
iffh = ami_clipboard_init_internal(1);
|
|
|
|
|
2010-07-24 23:57:27 +04:00
|
|
|
if(gui_copy_to_clipboard(s))
|
|
|
|
{
|
2010-07-28 01:41:21 +04:00
|
|
|
browser_window_mouse_click(gwin->bw, BROWSER_MOUSE_PRESS_1, x, y);
|
|
|
|
browser_window_key_press(gwin->bw, KEY_PASTE);
|
2010-07-24 23:57:27 +04:00
|
|
|
}
|
2010-10-24 22:07:11 +04:00
|
|
|
|
|
|
|
ami_clipboard_free_internal(iffh);
|
|
|
|
iffh = old_iffh;
|
2010-07-24 23:57:27 +04:00
|
|
|
}
|
2010-07-28 01:41:21 +04:00
|
|
|
else
|
|
|
|
{
|
|
|
|
DisplayBeep(scrn);
|
|
|
|
}
|
2010-07-24 23:57:27 +04:00
|
|
|
}
|
|
|
|
|
2008-10-26 02:22:34 +03:00
|
|
|
bool ami_easy_clipboard(char *text)
|
|
|
|
{
|
2010-07-25 00:18:56 +04:00
|
|
|
if(!gui_empty_clipboard()) return false;
|
|
|
|
if(!gui_add_to_clipboard(text,strlen(text),false)) return false;
|
|
|
|
if(!gui_commit_clipboard()) return false;
|
2008-10-26 02:22:34 +03:00
|
|
|
|
2010-07-25 00:18:56 +04:00
|
|
|
return true;
|
2008-10-26 02:22:34 +03:00
|
|
|
}
|
2009-05-16 18:50:30 +04:00
|
|
|
|
2009-05-16 21:04:28 +04:00
|
|
|
bool ami_easy_clipboard_bitmap(struct bitmap *bitmap)
|
2009-05-16 18:50:30 +04:00
|
|
|
{
|
2009-05-16 21:04:28 +04:00
|
|
|
Object *dto = NULL;
|
2009-05-16 18:50:30 +04:00
|
|
|
|
2009-05-16 21:04:28 +04:00
|
|
|
if(dto = ami_datatype_object_from_bitmap(bitmap))
|
2009-05-16 18:50:30 +04:00
|
|
|
{
|
2009-05-16 21:04:28 +04:00
|
|
|
DoDTMethod(dto,NULL,NULL,DTM_COPY,NULL);
|
|
|
|
DisposeDTObject(dto);
|
2009-05-16 18:50:30 +04:00
|
|
|
}
|
|
|
|
}
|
2009-05-19 11:23:56 +04:00
|
|
|
|
2009-05-19 11:30:00 +04:00
|
|
|
#ifdef WITH_NS_SVG
|
2010-03-28 19:51:05 +04:00
|
|
|
bool ami_easy_clipboard_svg(struct hlcache_handle *c)
|
2009-05-19 11:23:56 +04:00
|
|
|
{
|
2010-03-28 19:51:05 +04:00
|
|
|
char *source_data;
|
|
|
|
ULONG source_size;
|
|
|
|
|
|
|
|
if(content_get_type(c) != CONTENT_SVG) return false;
|
|
|
|
if((source_data = content_get_source_data(c, &source_size)) == NULL) return false;
|
2009-05-19 11:23:56 +04:00
|
|
|
|
|
|
|
if(!(OpenIFF(iffh,IFFF_WRITE)))
|
|
|
|
{
|
2010-03-28 19:51:05 +04:00
|
|
|
ami_svg_to_dr2d(iffh, source_data, source_size, content_get_url(c));
|
2009-05-19 11:23:56 +04:00
|
|
|
CloseIFF(iffh);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2009-05-19 11:30:00 +04:00
|
|
|
#endif
|