Olav SørensenUpdate ft2_mouse.cbfaa5bd3 years agoHistory
918 lines · 21.6 KB · C
RawDownload
// for finding memory leaks in debug mode with Visual Studio#if defined _DEBUG && defined _MSC_VER#include <crtdbg.h>#endif #include <stdio.h>#include <stdbool.h>#include "ft2_header.h"#include "ft2_gui.h"#include "ft2_video.h"#include "scopes/ft2_scopes.h"#include "ft2_help.h"#include "ft2_sample_ed.h"#include "ft2_inst_ed.h"#include "ft2_pattern_ed.h"#include "ft2_mouse.h"#include "ft2_config.h"#include "ft2_diskop.h"#include "ft2_audioselector.h"#include "ft2_midi.h"#include "ft2_bmp.h"#include "ft2_structs.h" #define NUM_CURSORS 6 mouse_t mouse; // globalized static bool mouseBusyGfxBackwards;static int16_t mouseShape;static int32_t mouseModeGfxOffs, mouseBusyGfxFrame;static SDL_Cursor *cursors[NUM_CURSORS]; static bool setSystemCursor(SDL_Cursor *cur){	if (config.specialFlags2 & USE_OS_MOUSE_POINTER)	{		SDL_SetCursor(SDL_GetDefaultCursor());		return true;	} 	if (cur == NULL)	{		SDL_SetCursor(SDL_GetDefaultCursor());		return false;	} 	SDL_SetCursor(cur);	return true;} void freeMouseCursors(void){	SDL_SetCursor(SDL_GetDefaultCursor());	for (int32_t i = 0; i < NUM_CURSORS; i++)	{		if (cursors[i] != NULL)		{			SDL_FreeCursor(cursors[i]);			cursors[i] = NULL;		}	}} bool createMouseCursors(void) // creates scaled SDL surfaces for current mouse pointer shape{	freeMouseCursors(); 	const uint8_t *cursorsSrc = bmp.mouseCursors;	switch (config.mouseType)	{		case MOUSE_IDLE_SHAPE_NICE: cursorsSrc += 0 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;		case MOUSE_IDLE_SHAPE_UGLY: cursorsSrc += 1 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;		case MOUSE_IDLE_SHAPE_AWFUL: cursorsSrc += 2 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;		case MOUSE_IDLE_SHAPE_USABLE: cursorsSrc += 3 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;		default: break;	} 	for (int32_t i = 0; i < NUM_CURSORS; i++)	{		int32_t scaleFactor = video.yScale;		if (scaleFactor > 8) // just in case			scaleFactor = 8; 		SDL_Surface *surface = SDL_CreateRGBSurface(0, MOUSE_CURSOR_W*scaleFactor, MOUSE_CURSOR_H*scaleFactor, 32, 0, 0, 0, 0);		if (surface == NULL)		{			freeMouseCursors(); 			if (config.specialFlags2 & USE_OS_MOUSE_POINTER)			{				SDL_ShowCursor(SDL_TRUE);			}			else			{				// enable software mouse				config.specialFlags2 &= ~HARDWARE_MOUSE;				SDL_ShowCursor(SDL_FALSE);			} 			return false;		} 		const uint32_t colorkey = SDL_MapRGB(surface->format, 0x00, 0xFF, 0x00); // colorkey		const uint32_t fg = SDL_MapRGB(surface->format, 0xFF, 0xFF, 0xFF); // foreground		const uint32_t border = SDL_MapRGB(surface->format, 0x00, 0x00, 0x00); // border 		SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);		SDL_SetColorKey(surface, SDL_TRUE, colorkey);		SDL_SetSurfaceRLE(surface, SDL_TRUE); 		const uint8_t *srcPixels8;		if (i == 3) // text edit cursor			srcPixels8 = &bmp.mouseCursors[12 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H)];		else if (i == 4) // mouse busy (wall clock)			srcPixels8 = &bmp.mouseCursorBusyClock[2 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H)]; // pick a good still-frame		else if (i == 5) // mouse busy (hourglass)			srcPixels8 = &bmp.mouseCursorBusyGlass[2 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H)]; // pick a good still-frame		else // normal idle cursor + disk op. "delete/rename" cursors			srcPixels8 = &cursorsSrc[i * (4 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H))]; 		SDL_LockSurface(surface); 		uint32_t *dstPixels32 = (uint32_t *)surface->pixels;		for (int32_t k = 0; k < surface->w*surface->h; k++) // fill surface with colorkey pixels			dstPixels32[k] = colorkey; 		// blit upscaled cursor to surface		for (int32_t y = 0; y < MOUSE_CURSOR_H; y++)		{			uint32_t *outX = &dstPixels32[(y * scaleFactor) * surface->w];			for (int32_t yScale = 0; yScale < scaleFactor; yScale++)			{				const uint8_t *srcPtr = &srcPixels8[y * MOUSE_CURSOR_W];				for (int32_t x = 0; x < MOUSE_CURSOR_W; x++)				{					const uint8_t srcPix = srcPtr[x];					if (srcPix != PAL_TRANSPR)					{						uint32_t pixel = colorkey;						if (srcPix == PAL_MOUSEPT)							pixel = fg;						else if (srcPix == PAL_BCKGRND)							pixel = border; 						for (int32_t xScale = 0; xScale < scaleFactor; xScale++)							outX[xScale] = pixel;					} 					outX += scaleFactor;				}			}		}		SDL_UnlockSurface(surface); 		uint32_t hotX = 0;		uint32_t hotY = 0; 		if (i == 3) // text edit cursor bias		{			hotX = 2 * video.xScale;			hotY = 6 * video.yScale;		} 		cursors[i] = SDL_CreateColorCursor(surface, hotX, hotY);		if (cursors[i] == NULL)		{			SDL_FreeSurface(surface);			freeMouseCursors(); 			if (config.specialFlags2 & USE_OS_MOUSE_POINTER)			{				SDL_ShowCursor(SDL_TRUE);			}			else			{				// enable software mouse				config.specialFlags2 &= ~HARDWARE_MOUSE;				SDL_ShowCursor(SDL_FALSE);			} 			return false;		} 		SDL_FreeSurface(surface);	} 	if (config.specialFlags2 & HARDWARE_MOUSE)	{		     if (mouse.mode == MOUSE_MODE_NORMAL) setSystemCursor(cursors[0]);		else if (mouse.mode == MOUSE_MODE_DELETE) setSystemCursor(cursors[1]);		else if (mouse.mode == MOUSE_MODE_RENAME) setSystemCursor(cursors[2]); 		SDL_ShowCursor(SDL_TRUE);	}	else	{		SDL_ShowCursor(SDL_FALSE);	} 	return true;} void setMousePosToCenter(void){	if (video.fullscreen)	{		mouse.setPosX = video.displayW >> 1;		mouse.setPosY = video.displayH >> 1;	}	else	{		mouse.setPosX = video.renderW >> 1;		mouse.setPosY = video.renderH >> 1;	} 	mouse.setPosFlag = true;} void animateBusyMouse(void){	if (config.mouseAnimType == MOUSE_BUSY_SHAPE_CLOCK)	{		if (config.specialFlags2 & HARDWARE_MOUSE)		{			setSystemCursor(cursors[4]);			return;		} 		if ((editor.framesPassed % 7) == 6)		{			if (mouseBusyGfxBackwards)			{				if (--mouseBusyGfxFrame <= 0)				{					mouseBusyGfxFrame = 0;					mouseBusyGfxBackwards = false;				}			}			else			{				if (++mouseBusyGfxFrame >= MOUSE_CLOCK_ANI_FRAMES-1)				{					mouseBusyGfxFrame = MOUSE_CLOCK_ANI_FRAMES - 1;					mouseBusyGfxBackwards = true;				}			} 			changeSpriteData(SPRITE_MOUSE_POINTER,				&bmp.mouseCursorBusyClock[(mouseBusyGfxFrame % MOUSE_CLOCK_ANI_FRAMES) * (MOUSE_CURSOR_W * MOUSE_CURSOR_H)]);		}	}	else	{		if (config.specialFlags2 & HARDWARE_MOUSE)		{			setSystemCursor(cursors[5]);			return;		} 		if ((editor.framesPassed % 5) == 4)		{			mouseBusyGfxFrame = (mouseBusyGfxFrame + 1) % MOUSE_GLASS_ANI_FRAMES; 			changeSpriteData(SPRITE_MOUSE_POINTER,				&bmp.mouseCursorBusyGlass[mouseBusyGfxFrame * (MOUSE_CURSOR_W * MOUSE_CURSOR_H)]);		}	}} void setMouseShape(int16_t shape){	const uint8_t *gfxPtr; 	if (editor.busy)	{		if (config.mouseAnimType == MOUSE_BUSY_SHAPE_CLOCK)			gfxPtr = &bmp.mouseCursorBusyClock[(mouseBusyGfxFrame % MOUSE_GLASS_ANI_FRAMES) * (MOUSE_CURSOR_W * MOUSE_CURSOR_H)];		else			gfxPtr = &bmp.mouseCursorBusyGlass[(mouseBusyGfxFrame % MOUSE_CLOCK_ANI_FRAMES) * (MOUSE_CURSOR_W * MOUSE_CURSOR_H)];	}	else	{		gfxPtr = &bmp.mouseCursors[mouseModeGfxOffs];		switch (shape)		{			case MOUSE_IDLE_SHAPE_NICE:   gfxPtr +=  0 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;			case MOUSE_IDLE_SHAPE_UGLY:   gfxPtr +=  1 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;			case MOUSE_IDLE_SHAPE_AWFUL:  gfxPtr +=  2 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;			case MOUSE_IDLE_SHAPE_USABLE: gfxPtr +=  3 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;			case MOUSE_IDLE_TEXT_EDIT:    gfxPtr += 12 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); break;			default: return;		}	} 	mouseShape = shape;	changeSpriteData(SPRITE_MOUSE_POINTER, gfxPtr); 	if (config.specialFlags2 & HARDWARE_MOUSE)	{		     if (mouse.mode == MOUSE_MODE_NORMAL) setSystemCursor(cursors[0]);		else if (mouse.mode == MOUSE_MODE_DELETE) setSystemCursor(cursors[1]);		else if (mouse.mode == MOUSE_MODE_RENAME) setSystemCursor(cursors[2]);	}} static void setTextEditMouse(void){	setMouseShape(MOUSE_IDLE_TEXT_EDIT);	mouse.xBias = -2;	mouse.yBias = -6; 	if (config.specialFlags2 & HARDWARE_MOUSE)		setSystemCursor(cursors[3]);} static void clearTextEditMouse(void){	setMouseShape(config.mouseType);	mouse.xBias = 0;	mouse.yBias = 0; 	if (config.specialFlags2 & HARDWARE_MOUSE)		setSystemCursor(cursors[0]);} static void changeCursorIfOverTextBoxes(void){	int32_t i; 	mouse.mouseOverTextBox = false;	if (editor.busy || mouse.mode != MOUSE_MODE_NORMAL)		return; 	const int32_t mx = mouse.x;	const int32_t my = mouse.y; 	textBox_t *t = textBoxes;	for (i = 0; i < NUM_TEXTBOXES; i++, t++)	{		if (ui.sysReqShown && i != 0) // Sys. Req can only have one (special) text box			continue; 		if (!t->visible)			continue; 		if (!t->changeMouseCursor && (!editor.editTextFlag || i != mouse.lastEditBox))			continue; // some kludge of sorts 		if (my >= t->y && my < t->y+t->h && mx >= t->x && mx < t->x+t->w)		{			mouse.mouseOverTextBox = true; 			if (mouseShape != MOUSE_IDLE_TEXT_EDIT)				setTextEditMouse(); 			return;		}	} 	// we're not inside a text edit box, set back mouse cursor	if (i == NUM_TEXTBOXES && mouseShape == MOUSE_IDLE_TEXT_EDIT)		clearTextEditMouse();} void setMouseMode(uint8_t mode){	switch (mode)	{		case MOUSE_MODE_NORMAL: { mouse.mode = mode; mouseModeGfxOffs = 0 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); } break;		case MOUSE_MODE_DELETE: { mouse.mode = mode; mouseModeGfxOffs = 4 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); } break;		case MOUSE_MODE_RENAME: { mouse.mode = mode; mouseModeGfxOffs = 8 * (MOUSE_CURSOR_W * MOUSE_CURSOR_H); } break; 		default: return;	} 	setMouseShape(config.mouseType);} void resetMouseBusyAnimation(void){	mouseBusyGfxBackwards = false;	mouseBusyGfxFrame = 0;} void setMouseBusy(bool busy) // can be called from other threads{	if (busy)	{		ui.setMouseIdle = false;		ui.setMouseBusy = true;	}	else	{		ui.setMouseBusy = false;		ui.setMouseIdle = true;	}} void mouseAnimOn(void){	ui.setMouseBusy = false;	ui.setMouseIdle = false; 	editor.busy = true;	setMouseShape(config.mouseAnimType);} void mouseAnimOff(void){	ui.setMouseBusy = false;	ui.setMouseIdle = false; 	editor.busy = false;	setMouseShape(config.mouseType);} static void mouseWheelDecRow(void){	if (songPlaying)		return; 	int16_t row = editor.row - 1;	if (row < 0)		row = patternNumRows[editor.editPattern] - 1; 	setPos(-1, row, true);} static void mouseWheelIncRow(void){	if (songPlaying)		return; 	int16_t row = editor.row + 1;	if (row >= patternNumRows[editor.editPattern])		row = 0; 	setPos(-1, row, true);} void mouseWheelHandler(bool directionUp){	if (ui.sysReqShown || editor.editTextFlag)		return; 	if (ui.extended)	{		if (mouse.y <= 52)		{			     if (mouse.x <= 111) directionUp ? decSongPos() : incSongPos();			else if (mouse.x >= 386) directionUp ?  decCurIns() :  incCurIns();		}		else		{			directionUp ? mouseWheelDecRow() : mouseWheelIncRow();		} 		return;	} 	if (mouse.y < 173)	{		// top screens 		if (ui.helpScreenShown)		{			// help screen 			if (directionUp)			{				helpScrollUp();				helpScrollUp();			}			else			{				helpScrollDown();				helpScrollDown();			}		}		else if (ui.diskOpShown)		{			// disk op - 3x speed			if (mouse.x <= 355)			{				if (directionUp)				{					pbDiskOpListUp();					pbDiskOpListUp();					pbDiskOpListUp();				}				else				{					pbDiskOpListDown();					pbDiskOpListDown();					pbDiskOpListDown();				}			}		}		else if (ui.configScreenShown)		{

Lines 1–500 of 918.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t