503 lines · 9.7 KB · C
RawDownload
// for finding memory leaks in debug mode with Visual Studio#if defined _DEBUG && defined _MSC_VER#include <crtdbg.h>#endif #include <stdint.h>#include <stdio.h>#include "ft2_header.h"#include "ft2_gui.h"#include "ft2_help.h"#include "ft2_video.h"#include "ft2_pattern_ed.h"#include "ft2_bmp.h"#include "ft2_structs.h"#include "helpdata/ft2_help_data.h" typedef struct{	bool bigFont, noLine;	uint8_t color;	int16_t xPos;	char text[100];} helpRec; #define HELP_LINES 15#define MAX_HELP_LINES 768#define HELP_SIZE sizeof (helpRec)#define MAX_SUBJ 10#define HELP_COLUMN 135#define HELP_WIDTH (596 - HELP_COLUMN) static uint8_t fHlp_Num;static int16_t textLine, fHlp_Line, subjLen[MAX_SUBJ];static int32_t helpBufferPos;static helpRec *subjPtrArr[MAX_SUBJ]; static void addText(helpRec *t, int16_t xPos, uint8_t color, char *text){	if (*text == '\0')		return; 	t->xPos = xPos;	t->color = color;	t->bigFont = false;	t->noLine = false;	strcpy(t->text, text);	*text = '\0'; // empty old string 	textLine++;} static bool getLine(char *output){	if (helpBufferPos >= (int32_t)sizeof (helpData))	{		*output = '\0';		return false;	} 	const uint8_t strLen = helpData[helpBufferPos++];	memcpy(output, &helpData[helpBufferPos], strLen);	output[strLen] = '\0'; 	helpBufferPos += strLen; 	return true;} static int16_t controlCodeToNum(const char *controlCode){	return (((controlCode[0]-'0')%10)*100) + (((controlCode[1]-'0')%10)*10) + ((controlCode[2]-'0')%10);} static char *ltrim(char *s){	if (*s == '\0')		return (s); 	while (*s == ' ') s++; 	return s;} static char *rtrim(char *s){	if (*s == '\0')		return (s); 	int32_t i = (int32_t)strlen(s) - 1;	while (i >= 0)	{		if (s[i] != ' ')		{			s[i+1] = '\0';			break;		} 		i--;	} 	return s;} static void readHelp(void) // this is a bit messy...{	char text[256], text2[256], *s, *sEnd, *s3;	int16_t a, b, i, k; 	helpRec *tempText = (helpRec *)malloc(HELP_SIZE * MAX_HELP_LINES);	if (tempText == NULL)	{		okBox(0, "System message", "Not enough memory!");		return;	}		text[0] = '\0';	text2[0] = '\0'; 	char *s2 = text2; 	helpBufferPos = 0;	for (int16_t subj = 0; subj < MAX_SUBJ; subj++)	{		textLine = 0;		int16_t currColumn = 0;		uint8_t currColor = PAL_FORGRND; 		getLine(text); s = text;		while (strncmp(s, "END", 3) != 0)		{			if (*s == ';')			{				if (!getLine(text))					break; 				s = text;				continue;			} 			if (*(uint16_t *)s == 0x4C40) // @L - "big font"			{				addText(&tempText[textLine], currColumn, currColor, s2);				s += 2; 				if (*(uint16_t *)s == 0x5840) // @X - "change X position"				{					currColumn = controlCodeToNum(&s[2]);					s += 5;				} 				if (*(uint16_t *)s == 0x4340) // @C - "change color				{					currColor = (uint8_t)controlCodeToNum(&s[2]);					currColor = (currColor < 2) ? PAL_FORGRND : PAL_BUTTONS;					s += 5;				} 				helpRec *t = &tempText[textLine];				t->xPos = currColumn;				t->color = currColor;				t->bigFont = true;				t->noLine = false;				strcpy(t->text, s);				textLine++; 				t = &tempText[textLine];				t->noLine = true;				textLine++;			}			else			{				if (*s == '>')				{					addText(&tempText[textLine], currColumn, currColor, s2);					s++;				} 				if (*(uint16_t *)s == 0x5840) // @X - "set X position (relative to help X start)"				{					currColumn = controlCodeToNum(&s[2]);					s += 5;				} 				if (*(uint16_t *)s == 0x4340) // @C - "change color"				{					currColor = (uint8_t)controlCodeToNum(&s[2]);					currColor = (currColor < 2) ? PAL_FORGRND : PAL_BUTTONS;					s += 5;				} 				s = ltrim(rtrim(s));				if (*s == '\0')				{					addText(&tempText[textLine], currColumn, currColor, s2);					strcpy(s2, " ");					addText(&tempText[textLine], currColumn, currColor, s2);				} 				int16_t sLen = (int16_t)strlen(s); 				sEnd = &s[sLen];				while (s < sEnd)				{					if (sLen < 0)						sLen = 0; 					i = 0;					while (s[i] != ' ' && i < sLen) i++;					i++; 					if (*(uint16_t *)s == 0x5440) // @T - "set absolute X position (in the middle of text)"					{						k = controlCodeToNum(&s[2]);						s += 5; sLen -= 5; 						s3 = &s2[strlen(s2)];						while (textWidth(s2) + charWidth(' ') + 1 < k-currColumn)						{							s3[0] = ' ';							s3[1] = '\0';							s3++;						} 						b = textWidth(s2) + 1;						if (b < k-currColumn)						{							s3 = &s2[strlen(s2)];							for (a = 0; a < k-b-currColumn; a++)								s3[a] = 127; // one-pixel spacer glyph							s3[a] = '\0';						}					} 					if (textWidth(s2)+textNWidth(s,i)+2 > HELP_WIDTH-currColumn)						addText(&tempText[textLine], currColumn, currColor, s2); 					strncat(s2, s, i); 					s += i; sLen -= i;					if ((*s == '\0') || (s >= sEnd))						strcat(s2, " ");				}			} 			if (textLine >= MAX_HELP_LINES || !getLine(text))				break; 			s = text;		} 		subjPtrArr[subj] = (helpRec *)malloc(HELP_SIZE * textLine);		if (subjPtrArr[subj] == NULL)		{			okBox(0, "System message", "Not enough memory!");			break;		} 		memcpy(subjPtrArr[subj], tempText, HELP_SIZE * textLine);		subjLen[subj] = textLine;	} 	free(tempText);} static void bigTextOutHalf(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, bool lowerHalf, const char *textPtr){	assert(textPtr != NULL); 	uint16_t currX = xPos;	while (true)	{		const char chr = *textPtr++ & 0x7F;		if (chr == '\0')			break; 		if (chr != ' ')		{			const uint8_t *srcPtr = &bmp.font2[chr * FONT2_CHAR_W];			if (!lowerHalf)				srcPtr += (FONT2_CHAR_H / 2) * FONT2_WIDTH; 			uint32_t *dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + currX];			const uint32_t pixVal = video.palette[paletteIndex]; 			for (uint32_t y = 0; y < FONT2_CHAR_H/2; y++)			{				for (uint32_t x = 0; x < FONT2_CHAR_W; x++)				{					if (srcPtr[x])						dstPtr[x] = pixVal;				} 				srcPtr += FONT2_WIDTH;				dstPtr += SCREEN_W;			}		} 		currX += charWidth16(chr);	}} static void writeHelp(void){	helpRec *ptr = subjPtrArr[fHlp_Num];	if (ptr == NULL)		return; 	for (int16_t i = 0; i < HELP_LINES; i++)	{		const int16_t k = i + fHlp_Line;		if (k >= subjLen[fHlp_Num])			break; 		clearRect(HELP_COLUMN, 5 + (i * 11), HELP_WIDTH, 11); 		if (ptr[k].noLine)		{			if (i == 0)				bigTextOutHalf(HELP_COLUMN + ptr[k-1].xPos, 5 + (i * 11), PAL_FORGRND, false, ptr[k-1].text);		}		else		{			if (ptr[k].bigFont)			{				if (i == HELP_LINES-1)				{					bigTextOutHalf(HELP_COLUMN + ptr[k].xPos, 5 + (i * 11), PAL_FORGRND, true, ptr[k].text);					return;				}				else				{					clearRect(HELP_COLUMN, 5 + ((i + 1) * 11), HELP_WIDTH, 11);					bigTextOut(HELP_COLUMN + ptr[k].xPos, 5 + (i * 11), PAL_FORGRND, ptr[k].text);					i++;				}			}			else			{				textOut(HELP_COLUMN + ptr[k].xPos, 5 + (i * 11), ptr[k].color, ptr[k].text);			}		}	}} void helpScrollUp(void){	if (fHlp_Line > 0)	{		scrollBarScrollUp(SB_HELP_SCROLL, 1);		writeHelp();	}} void helpScrollDown(void){	if (fHlp_Line < subjLen[fHlp_Num]-1)	{		scrollBarScrollDown(SB_HELP_SCROLL, 1);		writeHelp();	}} void helpScrollSetPos(uint32_t pos){	if (fHlp_Line != (int16_t)pos)	{		fHlp_Line = (int16_t)pos;		writeHelp();	}} void showHelpScreen(void){	uint16_t tmpID; 	if (ui.extended)		exitPatternEditorExtended(); 	hideTopScreen();	ui.helpScreenShown = true; 	drawFramework(0,   0, 128, 173, FRAMEWORK_TYPE1);	drawFramework(128, 0, 504, 173, FRAMEWORK_TYPE1);	drawFramework(130, 2, 479, 169, FRAMEWORK_TYPE2); 	showPushButton(PB_HELP_EXIT);	showPushButton(PB_HELP_SCROLL_UP);	showPushButton(PB_HELP_SCROLL_DOWN); 	uncheckRadioButtonGroup(RB_GROUP_HELP);	switch (fHlp_Num)	{		default:		case 0: tmpID = RB_HELP_FEATURES;       break;		case 1: tmpID = RB_HELP_EFFECTS;        break;		case 2: tmpID = RB_HELP_KEYBINDINGS;       break;		case 3: tmpID = RB_HELP_HOW_TO_USE_FT2; break;		case 4: tmpID = RB_HELP_FAQ;            break;		case 5: tmpID = RB_HELP_KNOWN_BUGS;     break;	}	radioButtons[tmpID].state = RADIOBUTTON_CHECKED; 	showRadioButtonGroup(RB_GROUP_HELP); 	showScrollBar(SB_HELP_SCROLL); 	textOutShadow(4,   4, PAL_FORGRND, PAL_DSKTOP2, "Subjects:");	textOutShadow(21, 19, PAL_FORGRND, PAL_DSKTOP2, "Features");	textOutShadow(21, 35, PAL_FORGRND, PAL_DSKTOP2, "Effects");	textOutShadow(21, 51, PAL_FORGRND, PAL_DSKTOP2, "Keybindings");	textOutShadow(21, 67, PAL_FORGRND, PAL_DSKTOP2, "How to use FT2");	textOutShadow(21, 83, PAL_FORGRND, PAL_DSKTOP2, "Problems/FAQ");	textOutShadow(21, 99, PAL_FORGRND, PAL_DSKTOP2, "Known bugs"); 	writeHelp();} void hideHelpScreen(void){	hidePushButton(PB_HELP_EXIT);	hidePushButton(PB_HELP_SCROLL_UP);	hidePushButton(PB_HELP_SCROLL_DOWN); 	hideRadioButtonGroup(RB_GROUP_HELP);	hideScrollBar(SB_HELP_SCROLL); 	ui.helpScreenShown = false;} void exitHelpScreen(void){	hideHelpScreen();	showTopScreen(true);} static void setHelpSubject(uint8_t Nr){	fHlp_Num = Nr;	fHlp_Line = 0; 	setScrollBarEnd(SB_HELP_SCROLL, subjLen[fHlp_Num]);	setScrollBarPos(SB_HELP_SCROLL, 0, false);} void rbHelpFeatures(void){	checkRadioButton(RB_HELP_FEATURES);	setHelpSubject(0);	writeHelp();} void rbHelpEffects(void){	checkRadioButton(RB_HELP_EFFECTS);	setHelpSubject(1);	writeHelp();} void rbHelpKeybindings(void){	checkRadioButton(RB_HELP_KEYBINDINGS);	setHelpSubject(2);	writeHelp();} void rbHelpHowToUseFT2(void){	checkRadioButton(RB_HELP_HOW_TO_USE_FT2);	setHelpSubject(3);	writeHelp();} void rbHelpFAQ(void){	checkRadioButton(RB_HELP_FAQ);	setHelpSubject(4);	writeHelp();} void rbHelpKnownBugs(void){	checkRadioButton(RB_HELP_KNOWN_BUGS);	setHelpSubject(5);	writeHelp();} void initFTHelp(void){	readHelp();	setHelpSubject(0);} void windUpFTHelp(void){	for (int16_t i = 0; i < MAX_SUBJ; i++)	{		if (subjPtrArr[i] != NULL)		{			free(subjPtrArr[i]);			subjPtrArr[i] = NULL;

Lines 1–500 of 503.

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