netsurf/amiga/theme.c
Vincent Sanders 67ded2a02a This moves message loading out of netsurf_init into each frontend
The translated message loading is dependant on configuration of
resource location in each frontend, additionally they should have the
ability to deal with errors in this loading in a implementation
specific manner.

This also extends the message loading API to be capable of loading
from an inline memory buffer instead of from a file.
2015-06-21 23:27:22 +01:00

511 lines
12 KiB
C

/*
* Copyright 2010 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 "amiga/os3support.h"
#include <string.h>
#include <proto/clicktab.h>
#include <proto/datatypes.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/icon.h>
#include <proto/intuition.h>
#include <gadgets/clicktab.h>
#include <gadgets/space.h>
#ifdef __amigaos4__
#include <graphics/blitattr.h>
#endif
#include <intuition/pointerclass.h>
#include <workbench/icon.h>
#include "utils/messages.h"
#include "utils/nsoption.h"
#include "utils/utils.h"
#include "desktop/searchweb.h"
#include "desktop/mouse.h"
#include "desktop/gui_window.h"
#include "amiga/gui.h"
#include "amiga/drag.h"
#include "amiga/bitmap.h"
#include "amiga/schedule.h"
#include "amiga/theme.h"
struct BitMap *throbber = NULL;
struct bitmap *throbber_nsbm = NULL;
int throbber_frames, throbber_update_interval;
static Object *mouseptrobj[AMI_LASTPOINTER+1];
static struct BitMap *mouseptrbm[AMI_LASTPOINTER+1];
const char *ptrs[AMI_LASTPOINTER+1] = {
"ptr_default",
"ptr_point",
"ptr_caret",
"ptr_menu",
"ptr_up",
"ptr_down",
"ptr_left",
"ptr_right",
"ptr_rightup",
"ptr_leftdown",
"ptr_leftup",
"ptr_rightdown",
"ptr_cross",
"ptr_move",
"ptr_wait",
"ptr_help",
"ptr_nodrop",
"ptr_notallowed",
"ptr_progress",
"ptr_blank",
"ptr_drag"};
const char *ptrs32[AMI_LASTPOINTER+1] = {
"ptr32_default",
"ptr32_point",
"ptr32_caret",
"ptr32_menu",
"ptr32_up",
"ptr32_down",
"ptr32_left",
"ptr32_right",
"ptr32_rightup",
"ptr32_leftdown",
"ptr32_leftup",
"ptr32_rightdown",
"ptr32_cross",
"ptr32_move",
"ptr32_wait",
"ptr32_help",
"ptr32_nodrop",
"ptr32_notallowed",
"ptr32_progress",
"ptr32_blank",
"ptr32_drag"};
#ifdef __amigaos4__
/* Mapping from NetSurf to AmigaOS mouse pointers */
int osmouseptr[AMI_LASTPOINTER+1] = {
POINTERTYPE_NORMAL,
POINTERTYPE_LINK,
POINTERTYPE_TEXT,
POINTERTYPE_CONTEXTMENU,
POINTERTYPE_NORTHRESIZE,
POINTERTYPE_SOUTHRESIZE,
POINTERTYPE_WESTRESIZE,
POINTERTYPE_EASTRESIZE,
POINTERTYPE_NORTHEASTRESIZE,
POINTERTYPE_SOUTHWESTRESIZE,
POINTERTYPE_NORTHWESTRESIZE,
POINTERTYPE_SOUTHEASTRESIZE,
POINTERTYPE_CROSS,
POINTERTYPE_HAND,
POINTERTYPE_BUSY,
POINTERTYPE_HELP,
POINTERTYPE_NODROP,
POINTERTYPE_NOTALLOWED,
POINTERTYPE_PROGRESS,
POINTERTYPE_NONE,
POINTERTYPE_DRAGANDDROP};
#endif
void ami_theme_init(void)
{
char themefile[1024];
BPTR lock = 0;
strcpy(themefile,nsoption_charp(theme));
AddPart(themefile,"Theme",100);
lock = Lock(themefile,ACCESS_READ);
if(!lock)
{
warn_user("ThemeApplyErr",nsoption_charp(theme));
strcpy(themefile,"PROGDIR:Resources/Themes/Default/Theme");
nsoption_set_charp(theme, (char *)strdup("PROGDIR:Resources/Themes/Default"));
}
else
{
UnLock(lock);
}
lock = Lock(themefile,ACCESS_READ);
if(lock)
{
UnLock(lock);
messages_add_from_file(themefile);
}
}
void ami_theme_throbber_setup(void)
{
char throbberfile[1024];
struct bitmap *bm;
ami_get_theme_filename(throbberfile,"theme_throbber",false);
throbber_frames=atoi(messages_get("theme_throbber_frames"));
throbber_update_interval = atoi(messages_get("theme_throbber_delay"));
if(throbber_update_interval == 0) throbber_update_interval = 250;
bm = ami_bitmap_from_datatype(throbberfile);
throbber = ami_bitmap_get_native(bm, bm->width, bm->height, NULL);
throbber_width = bm->width / throbber_frames;
throbber_height = bm->height;
throbber_nsbm = bm;
}
void ami_theme_throbber_free(void)
{
amiga_bitmap_destroy(throbber_nsbm);
throbber = NULL;
}
void ami_get_theme_filename(char *filename, const char *themestring, bool protocol)
{
if(protocol)
strcpy(filename,"file:///");
else
strcpy(filename,"");
if(messages_get(themestring)[0] == '*')
{
strncat(filename,messages_get(themestring)+1,100);
}
else
{
strcat(filename, nsoption_charp(theme));
AddPart(filename, messages_get(themestring), 100);
}
}
void gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape)
{
ami_set_pointer(g->shared, shape, true);
}
void ami_set_pointer(struct gui_window_2 *gwin, gui_pointer_shape shape, bool update)
{
if(gwin->mouse_pointer == shape) return;
ami_update_pointer(gwin->win, shape);
if(update == true) gwin->mouse_pointer = shape;
}
/* reset the mouse pointer back to what NetSurf last set it as */
void ami_reset_pointer(struct gui_window_2 *gwin)
{
ami_update_pointer(gwin->win, gwin->mouse_pointer);
}
void ami_update_pointer(struct Window *win, gui_pointer_shape shape)
{
if(drag_save_data) return;
if(LIB_IS_AT_LEAST((struct Library *)IntuitionBase, 53, 42)) {
#ifdef __amigaos4__
BOOL ptr_delay = FALSE;
if(shape == GUI_POINTER_WAIT) ptr_delay = TRUE;
SetWindowPointer(win,
WA_PointerType, osmouseptr[shape],
WA_PointerDelay, ptr_delay,
TAG_DONE);
#endif
} else {
if(nsoption_bool(os_mouse_pointers))
{
switch(shape)
{
case GUI_POINTER_DEFAULT:
SetWindowPointer(win, TAG_DONE);
break;
case GUI_POINTER_WAIT:
SetWindowPointer(win,
WA_BusyPointer, TRUE,
WA_PointerDelay, TRUE,
TAG_DONE);
break;
default:
if(mouseptrobj[shape]) {
SetWindowPointer(win, WA_Pointer, mouseptrobj[shape], TAG_DONE);
} else {
SetWindowPointer(win, TAG_DONE);
}
break;
}
}
else
{
if(mouseptrobj[shape])
{
SetWindowPointer(win, WA_Pointer, mouseptrobj[shape], TAG_DONE);
}
else
{
if(shape == GUI_POINTER_WAIT)
{
SetWindowPointer(win,
WA_BusyPointer, TRUE,
WA_PointerDelay, TRUE,
TAG_DONE);
}
else
{
SetWindowPointer(win, TAG_DONE);
}
}
}
}
}
void ami_init_mouse_pointers(void)
{
if(LIB_IS_AT_LEAST((struct Library *)IntuitionBase, 53, 42)) return;
int i;
struct RastPort mouseptr;
struct DiskObject *dobj;
uint32 format = IDFMT_BITMAPPED;
int32 mousexpt=0,mouseypt=0;
InitRastPort(&mouseptr);
for(i=0; i<=AMI_LASTPOINTER; i++) {
BPTR ptrfile;
mouseptrbm[i] = NULL;
mouseptrobj[i] = NULL;
char ptrfname[1024];
#ifdef __amigaos4__
if(nsoption_bool(truecolour_mouse_pointers)) {
ami_get_theme_filename((char *)&ptrfname,ptrs32[i], false);
if((dobj = GetIconTags(ptrfname,ICONGETA_UseFriendBitMap,TRUE,TAG_DONE))) {
if(IconControl(dobj, ICONCTRLA_GetImageDataFormat, &format, TAG_DONE)) {
if(IDFMT_DIRECTMAPPED == format) {
int32 width = 0, height = 0;
uint8* data = 0;
IconControl(dobj,
ICONCTRLA_GetWidth, &width,
ICONCTRLA_GetHeight, &height,
ICONCTRLA_GetImageData1, &data,
TAG_DONE);
if ((width > 0) && (width <= 64) && (height > 0) && (height <= 64) && data) {
STRPTR tooltype;
if((tooltype = FindToolType(dobj->do_ToolTypes, "XOFFSET")))
mousexpt = atoi(tooltype);
if((tooltype = FindToolType(dobj->do_ToolTypes, "YOFFSET")))
mouseypt = atoi(tooltype);
if ((mousexpt < 0) || (mousexpt >= width))
mousexpt = 0;
if ((mouseypt < 0) || (mouseypt >= height))
mouseypt = 0;
static uint8 dummyPlane[64 * 64 / 8];
static struct BitMap dummyBitMap = { 64 / 8, 64, 0, 2, 0, { dummyPlane, dummyPlane, 0, 0, 0, 0, 0, 0 }, };
mouseptrobj[i] = NewObject(NULL, "pointerclass",
POINTERA_BitMap, &dummyBitMap,
POINTERA_XOffset, -mousexpt,
POINTERA_YOffset, -mouseypt,
POINTERA_WordWidth, (width + 15) / 16,
POINTERA_XResolution, POINTERXRESN_SCREENRES,
POINTERA_YResolution, POINTERYRESN_SCREENRESASPECT,
POINTERA_ImageData, data,
POINTERA_Width, width,
POINTERA_Height, height,
TAG_DONE);
}
}
}
}
}
#endif
if(!mouseptrobj[i])
{
ami_get_theme_filename(ptrfname,ptrs[i], false);
if((ptrfile = Open(ptrfname,MODE_OLDFILE)))
{
int mx,my;
UBYTE *pprefsbuf = AllocVecTagList(1061, NULL);
Read(ptrfile,pprefsbuf,1061);
mouseptrbm[i]=AllocVecTagList(sizeof(struct BitMap), NULL);
InitBitMap(mouseptrbm[i],2,32,32);
mouseptrbm[i]->Planes[0] = AllocRaster(32,32);
mouseptrbm[i]->Planes[1] = AllocRaster(32,32);
mouseptr.BitMap = mouseptrbm[i];
for(my=0;my<32;my++)
{
for(mx=0;mx<32;mx++)
{
SetAPen(&mouseptr,pprefsbuf[(my*(33))+mx]-'0');
WritePixel(&mouseptr,mx,my);
}
}
mousexpt = ((pprefsbuf[1056]-'0')*10)+(pprefsbuf[1057]-'0');
mouseypt = ((pprefsbuf[1059]-'0')*10)+(pprefsbuf[1060]-'0');
mouseptrobj[i] = NewObject(NULL,"pointerclass",
POINTERA_BitMap,mouseptrbm[i],
POINTERA_WordWidth,2,
POINTERA_XOffset,-mousexpt,
POINTERA_YOffset,-mouseypt,
POINTERA_XResolution,POINTERXRESN_SCREENRES,
POINTERA_YResolution,POINTERYRESN_SCREENRESASPECT,
TAG_DONE);
FreeVec(pprefsbuf);
Close(ptrfile);
}
}
} // for
}
void ami_mouse_pointers_free(void)
{
if(LIB_IS_AT_LEAST((struct Library *)IntuitionBase, 53, 42)) return;
int i;
for(i=0;i<=AMI_LASTPOINTER;i++)
{
if(mouseptrbm[i])
{
FreeRaster(mouseptrbm[i]->Planes[0],32,32);
FreeRaster(mouseptrbm[i]->Planes[1],32,32);
FreeVec(mouseptrbm[i]);
}
}
}
void gui_window_start_throbber(struct gui_window *g)
{
if(!g) return;
if(nsoption_bool(kiosk_mode)) return;
#ifdef __amigaos4__
if(g->tab_node && (g->shared->tabs > 1))
{
SetClickTabNodeAttrs(g->tab_node, TNA_Flagged, TRUE, TAG_DONE);
RefreshGadgets((APTR)g->shared->objects[GID_TABS],
g->shared->win, NULL);
}
#endif
g->throbbing = true;
if(g->shared->throbber_frame == 0) g->shared->throbber_frame = 1;
ami_throbber_redraw_schedule(throbber_update_interval, g);
}
void gui_window_stop_throbber(struct gui_window *g)
{
struct IBox *bbox;
if(!g) return;
if(nsoption_bool(kiosk_mode)) return;
#ifdef __amigaos4__
if(g->tab_node && (g->shared->tabs > 1))
{
SetClickTabNodeAttrs(g->tab_node, TNA_Flagged, FALSE, TAG_DONE);
RefreshGadgets((APTR)g->shared->objects[GID_TABS],
g->shared->win, NULL);
}
#endif
if(g == g->shared->gw) {
if(ami_gui_get_space_box(g->shared->objects[GID_THROBBER], &bbox) != NSERROR_OK) {
warn_user("NoMemory", "");
return;
}
BltBitMapRastPort(throbber, 0, 0, g->shared->win->RPort, bbox->Left,
bbox->Top, throbber_width, throbber_height, 0x0C0);
ami_gui_free_space_box(bbox);
}
g->throbbing = false;
ami_throbber_redraw_schedule(-1, g);
}
static void ami_throbber_update(void *p)
{
struct gui_window *g = (struct gui_window *)p;
struct IBox *bbox;
int frame = 0;
if(!g) return;
if(!g->shared->objects[GID_THROBBER]) return;
if(g->throbbing == true) {
frame = g->shared->throbber_frame;
g->shared->throbber_frame++;
if(g->shared->throbber_frame > (throbber_frames-1))
g->shared->throbber_frame=1;
}
if(g->shared->gw == g) {
if(ami_gui_get_space_box(g->shared->objects[GID_THROBBER], &bbox) != NSERROR_OK) {
warn_user("NoMemory", "");
return;
}
#ifdef __amigaos4__
BltBitMapTags(BLITA_SrcX, throbber_width * frame,
BLITA_SrcY, 0,
BLITA_DestX, bbox->Left,
BLITA_DestY, bbox->Top,
BLITA_Width, throbber_width,
BLITA_Height, throbber_height,
BLITA_Source, throbber,
BLITA_Dest, g->shared->win->RPort,
BLITA_SrcType, BLITT_BITMAP,
BLITA_DestType, BLITT_RASTPORT,
// BLITA_UseSrcAlpha, TRUE,
TAG_DONE);
#else
BltBitMapRastPort(throbber, throbber_width * frame, 0, g->shared->win->RPort,
bbox->Left, bbox->Top, throbber_width, throbber_height, 0xC0);
#endif
ami_gui_free_space_box(bbox);
}
if(frame > 0) ami_throbber_redraw_schedule(throbber_update_interval, g);
}
void ami_throbber_redraw_schedule(int t, struct gui_window *g)
{
ami_schedule(t, ami_throbber_update, g);
}