Beispiel #1
0
static void SaveExtensionConfig(ProjectStateContext *ctx, bool isUndo, struct project_config_extension_t *reg)
{
	char line[SNM_MAX_CHUNK_LINE_LENGTH] = "";
	if (ctx && g_prjActions.Get()->GetLength())
		if (_snprintfStrict(line, sizeof(line), "S&M_PROJACTION %s", g_prjActions.Get()->Get()) > 0)
			ctx->AddLine("%s", line);
}
Beispiel #2
0
void UndoEditCursor(COMMAND_T*)
{
	int iPrev = *g_editCursorStackPos.Get() - 1;
	if (iPrev < 0)
		iPrev = SWS_EDITCURSOR_STACK_SIZE - 1;
	if (g_editCursorStack.Get()->Get()[iPrev] != -DBL_MAX)
	{
		*g_editCursorStackPos.Get() = iPrev;
		SetEditCurPos(g_editCursorStack.Get()->Get()[iPrev], true, true);
	}
}
Beispiel #3
0
void RedoEditCursor(COMMAND_T*)
{
	int iNext = *g_editCursorStackPos.Get() + 1;
	if (iNext >= SWS_EDITCURSOR_STACK_SIZE)
		iNext = 0;
	if (g_editCursorStack.Get()->Get()[iNext] != -DBL_MAX)
	{
		*g_editCursorStackPos.Get() = iNext;
		SetEditCurPos(g_editCursorStack.Get()->Get()[iNext], true, true);
	}
}
Beispiel #4
0
void RestoreActiveTakes(COMMAND_T*)
{
	for (int i = 1; i <= GetNumTracks(); i++)
	{
		MediaTrack* tr = CSurf_TrackFromID(i, false);
		if (*(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL))
			// Find the saved track
			for (int j = 0; j < g_activeTakeTracks.Get()->GetSize(); j++)
				if (TrackMatchesGuid(tr, &g_activeTakeTracks.Get()->Get(j)->m_guid))
					g_activeTakeTracks.Get()->Get(j)->Restore(tr);
	}
	UpdateArrange();
}
Beispiel #5
0
// per-project action timer armed via ProcessExtensionLine()
void ProjectStartupActionTimer()
{
	plugin_register("-timer",(void*)ProjectStartupActionTimer);
	if (int cmdId = NamedCommandLookup(g_prjActions.Get()->Get()))
	{
		Main_OnCommand(cmdId, 0);
#ifdef _SNM_DEBUG
		OutputDebugString("ProjectStartupActionTimer() - Performed project startup action '");
		OutputDebugString(g_prjActions.Get()->Get());
		OutputDebugString("'\n");
#endif
	}
}
Beispiel #6
0
void ShowStartupActions(COMMAND_T* _ct)
{
	WDL_FastString msg(__LOCALIZE("No project startup action is defined","sws_startup_action"));
	if (int cmdId = SNM_NamedCommandLookup(g_prjActions.Get()->Get()))
		msg.SetFormatted(512, __LOCALIZE_VERFMT("'%s' is defined as project startup action", "sws_startup_action"), kbd_getTextFromCmd(cmdId, NULL));

	char prjFn[SNM_MAX_PATH] = "";
	EnumProjects(-1, prjFn, sizeof(prjFn));
	if (*prjFn)
	{
		msg.Append("\r\n");
		msg.AppendFormatted(SNM_MAX_PATH, __LOCALIZE_VERFMT("for %s", "sws_startup_action"), prjFn);
	}
	msg.Append(".");
	msg.Append("\r\n\r\n");

	if (int cmdId = SNM_NamedCommandLookup(g_globalAction.Get()))
	{
		msg.AppendFormatted(512, __LOCALIZE_VERFMT("'%s' is defined as global startup action", "sws_startup_action"), kbd_getTextFromCmd(cmdId, NULL));
	}
	else
	{
		msg.Append(__LOCALIZE("No global startup action is defined","sws_startup_action"));
	}
	msg.Append(".");

	MessageBox(GetMainHwnd(), msg.Get(), SWS_CMD_SHORTNAME(_ct), MB_OK);
}
Beispiel #7
0
void ClearProjectStartupAction(COMMAND_T* _ct)
{
	if (PromptClearProjectStartupAction(true)==IDYES) {
		g_prjActions.Get()->Set("");
		Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_MISCCFG, -1);
	}
}
Beispiel #8
0
void DelRelatedProject(COMMAND_T*)
{
	if (!g_relatedProjects.Get()->GetSize())
		MessageBox(g_hwndParent, __LOCALIZE("No related projects to delete","sws_mbox"), __LOCALIZE("SWS Delete Related Project","sws_mbox"), MB_OK);
	else
		DialogBox(g_hInst, MAKEINTRESOURCE(IDD_LOAD) ,g_hwndParent, doDeleteDialog);
}
Beispiel #9
0
static bool ProcessExtensionLine(const char *line, ProjectStateContext *ctx, bool isUndo, struct project_config_extension_t *reg)
{
	LineParser lp(false);
	if (lp.parse(line) || lp.getnumtokens() < 1)
		return false;

	if (!strcmp(lp.gettoken_str(0), "S&M_PROJACTION"))
	{
		g_prjActions.Get()->Set(lp.gettoken_str(1));

		if (!isUndo && g_prjActions.Get()->GetLength() && IsActiveProjectInLoadSave())
			plugin_register("timer",(void*)ProjectStartupActionTimer);
		return true;
	}
	return false;
}
Beispiel #10
0
static void menuhook(const char* menustr, HMENU hMenu, int flag)
{
	if (flag == 1)
	{
		// Delete all related project entries and regenerate
		int iFirstPos;

		hMenu = FindMenuItem(hMenu, g_projMgrCmdTable[g_iORPCmdIndex].accel.accel.cmd, &iFirstPos);

		if (hMenu)
		{
			int iSlot = 0;
			int iPos;
			while (true)
			{
				int iCmd = GetLoadCommandID(iSlot, false);
				if (iCmd)
				{
					if (FindMenuItem(hMenu, iCmd, &iPos))
						DeleteMenu(hMenu, iPos, MF_BYPOSITION);
					else
						break;
				}
				else
					break;
				iSlot++;
			}

			if (!g_relatedProjects.Get()->GetSize())
			{
				MENUITEMINFO mi={sizeof(MENUITEMINFO),};
				mi.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID;
				mi.fType = MFT_STRING;
				mi.fState = MFS_GRAYED;
				mi.dwTypeData = (char *)__localizeFunc(g_projMgrCmdTable[g_iORPCmdIndex].menuText,"sws_menu",0);
				mi.wID = g_projMgrCmdTable[g_iORPCmdIndex].accel.accel.cmd;
				InsertMenuItem(hMenu, iFirstPos, true, &mi);
			}
			else
			{
				for (int i = 0; i < g_relatedProjects.Get()->GetSize(); i++)
					AddToMenu(hMenu, g_relatedProjects.Get()->Get(i)->Get(), GetLoadCommandID(i, true), iFirstPos++, true, MFS_UNCHECKED);
			}
		}
	}
}
Beispiel #11
0
//*****************************************************
// Global Functions
void SaveActiveTakes(COMMAND_T*)
{
	for (int i = 1; i <= GetNumTracks(); i++)
	{
		MediaTrack* tr = CSurf_TrackFromID(i, false);
		if (*(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL))
		{
			// Delete if exists
			for (int j = 0; j < g_activeTakeTracks.Get()->GetSize(); j++)
				if (TrackMatchesGuid(tr, &g_activeTakeTracks.Get()->Get(j)->m_guid))
				{
					g_activeTakeTracks.Get()->Delete(j--, true);
					break;
				}
			g_activeTakeTracks.Get()->Add(new ActiveTakeTrack(tr));
		}
	}
}
Beispiel #12
0
static bool ProcessExtensionLine(const char *line, ProjectStateContext *ctx, bool isUndo, struct project_config_extension_t *reg)
{
	LineParser lp(false);
	if (lp.parse(line) || lp.getnumtokens() < 1)
		return false;

	if (!strcmp(lp.gettoken_str(0), "S&M_PROJACTION"))
	{
		g_prjActions.Get()->Set(lp.gettoken_str(1));

		// by default, a registered timer is not armed when 
		// loading projects, only when launching REAPER, so...
		if (!isUndo && g_prjActions.Get()->GetLength() && IsActiveProjectInLoadSave())
			plugin_register("timer",(void*)OnTriggerActionTimer);
		return true;
	}
	return false;
}
Beispiel #13
0
void OpenRelatedProject(COMMAND_T* pCmd)
{
	if ((int)pCmd->user == g_relatedProjects.Get()->GetSize())
		// Give the user the chance to add a related project if they selected the first open spot
		if (MessageBox(g_hwndParent, __LOCALIZE("No related project found. Add one now?","sws_mbox"), __LOCALIZE("SWS Open Related Project","sws_mbox"), MB_YESNO) == IDYES)
			AddRelatedProject();

	if ((int)pCmd->user >= g_relatedProjects.Get()->GetSize())
		return;

	WDL_String* pStr = g_relatedProjects.Get()->Get((int)pCmd->user);
	ReaProject* pProj;
	// See if it's already opened
	char cOpenedProj[256];
	int i = 0;
	while ((pProj = EnumProjects(i++, cOpenedProj, 256)))
	{
		if (_stricmp(cOpenedProj, pStr->Get()) == 0)
		{
			SelectProjectInstance(pProj);
			return;
		}
	}

	// Nope, open in new tab
	// Save "prompt on new project" variable
	int iNewProjOpts;
	int sztmp;
	int* pNewProjOpts = (int*)get_config_var("newprojdo", &sztmp);
	iNewProjOpts = *pNewProjOpts;
	*pNewProjOpts = 0;
	pProj = EnumProjects(-1, NULL, 0);
	Main_OnCommand(41929, 0); // New project tab (ignore default template)
	Main_openProject(pStr->Get());
	EnumProjects(-1, cOpenedProj, 256);
	if (_stricmp(pStr->Get(), cOpenedProj))
	{
		Main_OnCommand(40860, 0); // 40860 = Close current project tab
		SelectProjectInstance(pProj);
		g_relatedProjects.Get()->Delete((int)pCmd->user, true);
	}
	*pNewProjOpts = iNewProjOpts;
}
Beispiel #14
0
void OnTriggerActionTimer()
{
	// unregister timer (called once)
	plugin_register("-timer",(void*)OnTriggerActionTimer);

	if (int cmdId = NamedCommandLookup(g_prjActions.Get()->Get()))
	{
		// specific case for "load theme" actions (~1s delay)
		if (strstr(g_prjActions.Get()->Get(), "S&M_LOAD_THEME"))
			ScheduledJob::Schedule(new StartupProjectActionJob(cmdId));

		// standard case, faster
		else
			Main_OnCommand(cmdId, 0);
#ifdef _SNM_DEBUG
		OutputDebugString("OnTriggerActionTimer() - Performed startup action '");
		OutputDebugString(g_prjActions.Get()->Get());
		OutputDebugString("'\n");
#endif
	}
}
Beispiel #15
0
void RestoreLastSelItemTrack(COMMAND_T* ct)
{
	PreventUIRefresh(1);
	for (int i = 1; i <= GetNumTracks(); i++)
	{
		MediaTrack* tr = CSurf_TrackFromID(i, false);
		if (*(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL))
		{
			GUID* g = (GUID*)GetSetMediaTrackInfo(tr, "GUID", NULL);
			for (int j = 0; j < g_selItemsTrack.Get()->GetSize(); j++)
				if (GuidsEqual(g, &g_selItemsTrack.Get()->Get(j)->m_guid))
				{
					g_selItemsTrack.Get()->Get(j)->PreviousSelection(tr);
					break;
				}
		}
	}
	PreventUIRefresh(-1);
	Undo_OnStateChangeEx(SWS_CMD_SHORTNAME(ct), UNDO_STATE_ITEMS, -1);
	UpdateArrange();
}
Beispiel #16
0
static INT_PTR WINAPI doDeleteDialog(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	if (INT_PTR r = SNM_HookThemeColorsMessage(hwndDlg, uMsg, wParam, lParam))
		return r;

	switch (uMsg)
	{
		case WM_INITDIALOG:
		{
			HWND list = GetDlgItem(hwndDlg, IDC_COMBO);
			WDL_UTF8_HookComboBox(list);
			for (int i = 0; i < g_relatedProjects.Get()->GetSize(); i++)
				SendMessage(list, CB_ADDSTRING, 0, (LPARAM)g_relatedProjects.Get()->Get(i)->Get());
            SendMessage(list, CB_SETCURSEL, 0, 0);
			SetWindowText(hwndDlg, __LOCALIZE("SWS Delete Related Project","sws_mbox"));
			RestoreWindowPos(hwndDlg, DELWINDOW_POS_KEY);
			return 0;
		}
		case WM_COMMAND:
			switch(LOWORD(wParam))
			{
				case IDOK:
				{
					HWND list = GetDlgItem(hwndDlg, IDC_COMBO);
					int iList = (int)SendMessage(list, CB_GETCURSEL, 0, 0);
					if (iList >= 0 && iList < g_relatedProjects.Get()->GetSize())
						g_relatedProjects.Get()->Delete(iList, true);
					Undo_OnStateChangeEx(__LOCALIZE("Delete related project","sws_undo"), UNDO_STATE_MISCCFG, -1);
				}
				// Fall through to cancel to save/end
				case IDCANCEL:
					SaveWindowPos(hwndDlg, DELWINDOW_POS_KEY);
					EndDialog(hwndDlg, 0);
					break;
			}
			break;
	}
	return 0;
}
Beispiel #17
0
static bool ProcessExtensionLine(const char *line, ProjectStateContext *ctx, bool isUndo, struct project_config_extension_t *reg)
{
	LineParser lp(false);
	if (lp.parse(line) || lp.getnumtokens() < 1)
		return false;
	if (strcmp(lp.gettoken_str(0), "RELATEDPROJECT") != 0)
		return false; // only look for RELATEDPROJECT lines

	if (lp.getnumtokens() == 2)
	{
		g_relatedProjects.Get()->Add(new WDL_String(lp.gettoken_str(1)));
	}
	return true;
}
Beispiel #18
0
int PromptClearProjectStartupAction(bool _clear)
{
	int r=0, cmdId=SNM_NamedCommandLookup(g_prjActions.Get()->Get());
	if (cmdId)
	{
		WDL_FastString msg;
		msg.AppendFormatted(256,
			_clear ?
				__LOCALIZE_VERFMT("Are you sure you want to clear the current startup action: '%s'?","sws_mbox") :
				__LOCALIZE_VERFMT("Are you sure you want to replace the current startup action: '%s'?","sws_mbox"),
			kbd_getTextFromCmd(cmdId, NULL));
		r = MessageBox(GetMainHwnd(), msg.Get(), __LOCALIZE("S&M - Confirmation","sws_mbox"), MB_YESNO);
	}
	return r;
}
Beispiel #19
0
void RestoreSelTrackSelItems(int iSlot)
{
	PreventUIRefresh(1);
	for (int i = 1; i <= GetNumTracks(); i++)
	{
		MediaTrack* tr = CSurf_TrackFromID(i, false);
		if (*(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL))
		{
			GUID* g = (GUID*)GetSetMediaTrackInfo(tr, "GUID", NULL);
			for (int j = 0; j < g_selItemsTrack.Get()->GetSize(); j++)
				if (GuidsEqual(g, &g_selItemsTrack.Get()->Get(j)->m_guid))
				{
					g_selItemsTrack.Get()->Get(j)->Restore(tr, iSlot);
					break;
				}
		}
	}
	PreventUIRefresh(-1);

	char cUndoText[256];
	sprintf(cUndoText, __LOCALIZE_VERFMT("Restore selected track(s) selected item(s), slot %d","sws_undo"), iSlot+1);
	Undo_OnStateChangeEx(cUndoText, UNDO_STATE_ITEMS, -1);
	UpdateArrange();
}
Beispiel #20
0
void SetProjectStartupAction(COMMAND_T* _ct)
{
	if (PromptClearProjectStartupAction(false) == IDNO)
		return;

	char idstr[SNM_MAX_ACTION_CUSTID_LEN];
	lstrcpyn(idstr, __LOCALIZE("Paste command ID or identifier string here","sws_mbox"), sizeof(idstr));
	if (PromptUserForString(GetMainHwnd(), SWS_CMD_SHORTNAME(_ct), idstr, sizeof(idstr), true))
	{
		WDL_FastString msg;
		if (int cmdId = SNM_NamedCommandLookup(idstr))
		{
			// more checks: http://forum.cockos.com/showpost.php?p=1252206&postcount=1618
			if (int tstNum = CheckSwsMacroScriptNumCustomId(idstr))
			{
				msg.SetFormatted(256, __LOCALIZE_VERFMT("%s failed: unreliable command ID '%s'!","sws_DLG_161"), SWS_CMD_SHORTNAME(_ct), idstr);
				msg.Append("\n");

				// localization note: msgs shared with the CA editor
				if (tstNum==-1)
					msg.Append(__LOCALIZE("For SWS/S&M actions, you must use identifier strings (e.g. _SWS_ABOUT), not command IDs (e.g. 47145).\nTip: to copy such identifiers, right-click the action in the Actions window > Copy selected action cmdID/identifier string.","sws_mbox"));
				else if (tstNum==-2)
					msg.Append(__LOCALIZE("For macros/scripts, you must use identifier strings (e.g. _f506bc780a0ab34b8fdedb67ed5d3649), not command IDs (e.g. 47145).\nTip: to copy such identifiers, right-click the macro/script in the Actions window > Copy selected action cmdID/identifier string.","sws_mbox"));
				MessageBox(GetMainHwnd(), msg.Get(), __LOCALIZE("S&M - Error","sws_DLG_161"), MB_OK);
			}
			else
			{
				g_prjActions.Get()->Set(idstr);
				Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_MISCCFG, -1);

				msg.SetFormatted(256, __LOCALIZE_VERFMT("'%s' is defined as project startup action","sws_mbox"), kbd_getTextFromCmd(cmdId, NULL));
				char prjFn[SNM_MAX_PATH] = "";
				EnumProjects(-1, prjFn, sizeof(prjFn));
				if (*prjFn) {
					msg.Append("\n");
					msg.AppendFormatted(SNM_MAX_PATH, __LOCALIZE_VERFMT("for %s","sws_mbox"), prjFn);
				}
				msg.Append(".");
				MessageBox(GetMainHwnd(), msg.Get(), SWS_CMD_SHORTNAME(_ct), MB_OK);
			}
		}
		else
		{
			msg.SetFormatted(256, __LOCALIZE_VERFMT("%s failed: command ID or identifier string '%s' not found in the 'Main' section of the action list!","sws_DLG_161"), SWS_CMD_SHORTNAME(_ct), idstr);
			MessageBox(GetMainHwnd(), msg.Get(), __LOCALIZE("S&M - Error","sws_DLG_161"), MB_OK);
		}
	}
}
Beispiel #21
0
void ClearStartupAction(COMMAND_T* _ct)
{
	int type=(int)_ct->user;
  
	if (PromptClearStartupAction(type, true)==IDYES)
	{
		if (!type)
		{
			g_prjActions.Get()->Set("");
			Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_MISCCFG, -1);
		}
		else
		{
			g_globalAction.Set("");
			WritePrivateProfileString("Misc", "GlobalStartupAction", NULL, g_SNM_IniFn.Get()); 
		}
	}
}
Beispiel #22
0
void AddRelatedProject(COMMAND_T* = NULL)
{
	char cPath[256];
	GetProjectPath(cPath, 256);

	char* filename = BrowseForFiles(__LOCALIZE("Select related projects","sws_mbox"), cPath, NULL, false, "Reaper Project (*.RPP)\0*.RPP");
	char* pBuf = filename;
	if (pBuf)
	{
		while(filename[0])
		{
			g_relatedProjects.Get()->Add(new WDL_String(filename));
			filename += strlen(filename) +1;
		}

		free(pBuf);
		Undo_OnStateChangeEx(__LOCALIZE("Add related projects","sws_mbox"), UNDO_STATE_MISCCFG, -1);
	}
}
Beispiel #23
0
int PromptClearStartupAction(int _type, bool _clear)
{
	int r=0, cmdId=SNM_NamedCommandLookup(_type ? g_globalAction.Get() : g_prjActions.Get()->Get());
	if (cmdId)
	{
		WDL_FastString msg;
		if (!_type)
		{
			msg.AppendFormatted(512, _clear ?
                          __LOCALIZE_VERFMT("Are you sure you want to clear the project startup action: '%s'?","sws_startup_action") :
                          __LOCALIZE_VERFMT("Are you sure you want to replace the project startup action: '%s'?","sws_startup_action"),
                          kbd_getTextFromCmd(cmdId, NULL));
		}
		else
		{
			msg.AppendFormatted(512, _clear ?
                          __LOCALIZE_VERFMT("Are you sure you want to clear the global startup action: '%s'?","sws_startup_action") :
                          __LOCALIZE_VERFMT("Are you sure you want to replace the global startup action: '%s'?","sws_startup_action"),
                          kbd_getTextFromCmd(cmdId, NULL));
		}
		r = MessageBox(GetMainHwnd(), msg.Get(), __LOCALIZE("S&M - Confirmation","sws_mbox"), MB_YESNO);
	}
	return r;
}
Beispiel #24
0
//*****************************************************
// Global functions
void SaveSelTrackSelItems(int iSlot)
{
	for (int i = 1; i <= GetNumTracks(); i++)
	{
		MediaTrack* tr = CSurf_TrackFromID(i, false);
		if (*(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL))
		{
			GUID* g = (GUID*)GetSetMediaTrackInfo(tr, "GUID", NULL);
			int j;
			for (j = 0; j < g_selItemsTrack.Get()->GetSize(); j++)
				if (GuidsEqual(g, &g_selItemsTrack.Get()->Get(j)->m_guid))
				{
					g_selItemsTrack.Get()->Get(j)->Save(tr, iSlot);
					break;
				}
			if (j == g_selItemsTrack.Get()->GetSize())
			{
				g_selItemsTrack.Get()->Add(new SelItemsTrack(tr));
				g_selItemsTrack.Get()->Get(g_selItemsTrack.Get()->GetSize()-1)->Save(tr, iSlot);
			}
		}
	}
}
Beispiel #25
0
static void BeginLoadProjectState(bool isUndo, struct project_config_extension_t *reg) {
	g_prjActions.Cleanup();
	g_prjActions.Get()->Set("");
}
Beispiel #26
0
void RestoreSelItems(COMMAND_T* ct)
{
	g_selItems.Get()->Restore(NULL);
	Undo_OnStateChangeEx(SWS_CMD_SHORTNAME(ct), UNDO_STATE_ITEMS, -1);
	UpdateTimeline();
}
Beispiel #27
0
static void SaveExtensionConfig(ProjectStateContext *ctx, bool isUndo, struct project_config_extension_t *reg)
{
	for (int i = 0; i < g_relatedProjects.Get()->GetSize(); i++)
		ctx->AddLine("RELATEDPROJECT \"%s\"", g_relatedProjects.Get()->Get(i)->Get());
}
Beispiel #28
0
static void BeginLoadProjectState(bool isUndo, struct project_config_extension_t *reg)
{
	g_relatedProjects.Get()->Empty(true);
	g_relatedProjects.Cleanup();
}
Beispiel #29
0
static void BeginLoadProjectState(bool isUndo, struct project_config_extension_t *reg)
{
	g_editCursorStack.Cleanup();
	g_editCursorStackPos.Cleanup();
}
Beispiel #30
0
// Save the edit cursor position
void EditCursorSlice()
{
	// Initialize new proj
	if (g_editCursorStack.Get()->GetSize() == 0)
	{
		g_editCursorStack.Get()->Resize(SWS_EDITCURSOR_STACK_SIZE);
		for (int i = 1; i < SWS_EDITCURSOR_STACK_SIZE; i++)
			g_editCursorStack.Get()->Get()[i] = -DBL_MAX;
		*g_editCursorStackPos.Get() = 0;
		*g_editCursorStack.Get()->Get() = GetCursorPosition();
	}

	double dPos = GetCursorPosition();
	if (dPos != g_editCursorStack.Get()->Get()[*g_editCursorStackPos.Get()])
	{
		(*g_editCursorStackPos.Get())++;
		if (*g_editCursorStackPos.Get() >= SWS_EDITCURSOR_STACK_SIZE)
			*g_editCursorStackPos.Get() = 0;

		int iNext = *g_editCursorStackPos.Get();

		while(g_editCursorStack.Get()->Get()[iNext] != -DBL_MAX)
		{
			g_editCursorStack.Get()->Get()[iNext] = -DBL_MAX;
			iNext++;
			if (iNext >= SWS_EDITCURSOR_STACK_SIZE)
				iNext = 0;
		}
		g_editCursorStack.Get()->Get()[*g_editCursorStackPos.Get()] = dPos;
	}
}