netsurf/amiga/clipboard.c
Chris Young 004aee8281 Amiga: Add "cut" option; make cut/copy/paste menus context sensitive; allow dragging
selections within NetSurf window to text fields (does not work across windows).

todo: switching tabs will reset cut/copy/paste menus to initial state; cut option is
putting something on the clipboard which causes a crash when pasting it back

svn path=/trunk/netsurf/; revision=10660
2010-07-24 16:39:37 +00:00

295 lines
5.9 KiB
C
Executable File

/*
* Copyright 2008,2009 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* 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"
#include "utils/utf8.h"
#include "desktop/selection.h"
#include "amiga/iff_cset.h"
#include "amiga/options.h"
#include "amiga/gui.h"
#include "amiga/utf8.h"
#include "amiga/bitmap.h"
#include "amiga/iff_dr2d.h"
#include "amiga/menu.h"
#include <proto/iffparse.h>
#include <proto/intuition.h>
#include <proto/exec.h>
#include <proto/datatypes.h>
#include <proto/diskfont.h>
#include <diskfont/diskfonttag.h>
#include <datatypes/textclass.h>
#include <datatypes/pictureclass.h>
struct IFFHandle *iffh = NULL;
void ami_clipboard_init(void)
{
if(iffh = AllocIFF())
{
if(iffh->iff_Stream = (ULONG)OpenClipboard(0))
{
InitIFFasClip(iffh);
}
}
}
void ami_clipboard_free(void)
{
if(iffh->iff_Stream) CloseClipboard((struct ClipboardHandle *)iffh->iff_Stream);
if(iffh) FreeIFF(iffh);
}
void gui_start_selection(struct gui_window *g)
{
if(!g) return;
if(!g->shared->win) return;
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;
OffMenu(g->shared->win, AMI_MENU_CLEAR);
OffMenu(g->shared->win, AMI_MENU_CUT);
OffMenu(g->shared->win, AMI_MENU_COPY);
}
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;
STRPTR readbuf = AllocVec(1024,MEMF_PRIVATE | MEMF_CLEAR);
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
{
utf8_from_enc(readbuf,
ObtainCharsetInfo(DFCS_NUMBER, cset.CodeSet, DFCS_MIMENAME),
rlen, &clip);
}
browser_window_paste_text(g->shared->bw,clip,rlen,true);
}
if(rlen < 0) error = rlen;
}
}
CloseIFF(iffh);
}
bool gui_empty_clipboard(void)
{
return true;
}
bool gui_add_to_clipboard(const char *text, size_t length, bool space)
{
char *buffer;
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)
{
if(!gui_add_to_clipboard(whitespace_text,whitespace_length, false)) return false;
}
if(text)
{
if (!gui_add_to_clipboard(text, length, box->space)) return false;
}
PopChunk(iffh);
}
else
{
PopChunk(iffh);
return false;
}
return true;
}
bool gui_copy_to_clipboard(struct selection *s)
{
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);
}
}
if (s->defined && selection_traverse(s, ami_clipboard_copy, NULL))
{
gui_commit_clipboard();
return true;
}
}
else
{
PopChunk(iffh);
}
CloseIFF(iffh);
}
return false;
}
bool ami_easy_clipboard(char *text)
{
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);
}
}
if(!(PushChunk(iffh,0,ID_CHRS,IFFSIZE_UNKNOWN)))
{
if(gui_add_to_clipboard(text,strlen(text),false))
{
PopChunk(iffh);
gui_commit_clipboard();
return true;
}
}
else
{
PopChunk(iffh);
}
}
else
{
PopChunk(iffh);
}
CloseIFF(iffh);
}
return false;
}
bool ami_easy_clipboard_bitmap(struct bitmap *bitmap)
{
Object *dto = NULL;
if(dto = ami_datatype_object_from_bitmap(bitmap))
{
DoDTMethod(dto,NULL,NULL,DTM_COPY,NULL);
DisposeDTObject(dto);
}
}
#ifdef WITH_NS_SVG
bool ami_easy_clipboard_svg(struct hlcache_handle *c)
{
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;
if(!(OpenIFF(iffh,IFFF_WRITE)))
{
ami_svg_to_dr2d(iffh, source_data, source_size, content_get_url(c));
CloseIFF(iffh);
}
return true;
}
#endif