Esempio n. 1
0
void SaveCueBusIniFile(int _confId, const char* _busName, int _type, bool _trTemplate, const char* _trTemplatePath, bool _showRouting, int _soloDefeat, bool _sendToMaster, int* _hwOuts)
{
	if (_confId>=0 && _confId<SNM_MAX_CUE_BUSS_CONFS && _busName && _trTemplatePath && _hwOuts)
	{
		char iniSection[64]="";
		if (_snprintfStrict(iniSection, sizeof(iniSection), "CueBuss%d", _confId+1) > 0)
		{
			char buf[16]="", slot[16]="";
			WDL_FastString escapedStr;
			escapedStr.SetFormatted(256, "\"%s\"", _busName);
			WritePrivateProfileString(iniSection,"name",escapedStr.Get(),g_SNM_IniFn.Get());
			if (_snprintfStrict(buf, sizeof(buf), "%d" ,_type) > 0)
				WritePrivateProfileString(iniSection,"reatype",buf,g_SNM_IniFn.Get());
			WritePrivateProfileString(iniSection,"track_template_enabled",_trTemplate ? "1" : "0",g_SNM_IniFn.Get());
			escapedStr.SetFormatted(SNM_MAX_PATH, "\"%s\"", _trTemplatePath);
			WritePrivateProfileString(iniSection,"track_template_path",escapedStr.Get(),g_SNM_IniFn.Get());
			WritePrivateProfileString(iniSection,"show_routing",_showRouting ? "1" : "0",g_SNM_IniFn.Get());
			WritePrivateProfileString(iniSection,"send_to_masterparent",_sendToMaster ? "1" : "0",g_SNM_IniFn.Get());
			if (_snprintfStrict(buf, sizeof(buf), "%d", _soloDefeat) > 0)
				WritePrivateProfileString(iniSection,"solo_defeat",buf,g_SNM_IniFn.Get());
			for (int i=0; i<SNM_MAX_HW_OUTS; i++) 
				if (_snprintfStrict(slot, sizeof(slot), "hwout%d", i+1) > 0 && _snprintfStrict(buf, sizeof(buf), "%d", _hwOuts[i]) > 0)
					WritePrivateProfileString(iniSection,slot,_hwOuts[i]?buf:NULL,g_SNM_IniFn.Get());
		}
	}
}
Esempio n. 2
0
int main(int argc, char **argv)
{
  if (argc != 2) { fprintf(stderr,"usage: preproc_test filename\n"); return 0; }
  FILE *fp =fopen(argv[1],"rb");
  if (!fp)  { fprintf(stderr,"error opening '%s'\n",argv[1]); return 1; }

  int insec=0;
  WDL_FastString cursec;
  for (;;)
  {
    char buf[4096];
    buf[0]=0;
    fgets(buf,sizeof(buf),fp);
    if (!buf[0]) break;
    char *p=buf;
    while (*p == ' ' || *p == '\t') p++;
    if (p[0] == '@') 
    {
      insec=1;
      if (ppOut((char*)cursec.Get())) { fprintf(stderr,"Error preprocessing %s!\n",argv[1]); return -1; }
      cursec.Set("");
    }
    else if (insec)
    {
      cursec.Append(buf);
      continue;
    }
    printf("%s",buf);
  }
  if (ppOut((char*)cursec.Get())) { fprintf(stderr,"Error preprocessing %s!\n",argv[1]); return -1; }

  fclose(fp);
  return 0;
}
Esempio n. 3
0
// different from checking a PCM source: this method deals with the chunk
bool SNM_TakeParserPatcher::IsEmpty(int _takeIdx)
{
	WDL_FastString tkChunk;
	if (GetTakeChunk(_takeIdx, &tkChunk))
		return (
			!strncmp(tkChunk.Get(), "TAKE NULL", 9) || // empty take
			strstr(tkChunk.Get(), "<SOURCE EMPTY")); // take with an empty source
	return false;
}
Esempio n. 4
0
// global action timer armed via SNM_Init()/OnInitTimer()
void GlobalStartupActionTimer()
{
	if (int cmdId = NamedCommandLookup(g_globalAction.Get()))
	{
		Main_OnCommand(cmdId, 0);
#ifdef _SNM_DEBUG
		OutputDebugString("GlobalStartupActionTimer() - Performed global startup action '");
		OutputDebugString(g_globalAction.Get());
		OutputDebugString("'\n");
#endif
	}
}
Esempio n. 5
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);
		}
	}
}
Esempio n. 6
0
int FindFirstUnusedGroup()
{
	bool grp[SNM_MAX_TRACK_GROUPS];
	memset(grp, 0, sizeof(bool)*SNM_MAX_TRACK_GROUPS);

	for (int i=0; i <= GetNumTracks(); i++) // incl. master
	{
		//JFB TODO? exclude selected tracks?
		if (MediaTrack* tr = CSurf_TrackFromID(i, false))
		{
			SNM_ChunkParserPatcher p(tr);
			WDL_FastString grpLine;
			if (p.Parse(SNM_GET_SUBCHUNK_OR_LINE, 1, "TRACK", "GROUP_FLAGS", 0, 0, &grpLine, NULL, "TRACKHEIGHT"))
			{
				LineParser lp(false);
				if (!lp.parse(grpLine.Get())) {
					for (int j=1; j < lp.getnumtokens(); j++) { // skip 1st token GROUP_FLAGS
						int val = lp.gettoken_int(j);
						for (int k=0; k < SNM_MAX_TRACK_GROUPS; k++) {
							int grpMask = int(pow(2.0, k*1.0));
							grp[k] |= ((val & grpMask) == grpMask);
						}
					}
				}
			}
		}
	}

	for (int i=0; i < SNM_MAX_TRACK_GROUPS; i++) 
		if (!grp[i]) return i;

	return -1;
}
Esempio n. 7
0
static LRESULT CALLBACK RulerWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	if (uMsg == WM_SETCURSOR && g_actionInProgress && g_actionInProgress->SetMouseCursor)
	{
		if (HCURSOR cursor = g_actionInProgress->SetMouseCursor(BR_ContinuousAction::RULER))
		{
			SetCursor(cursor);
			return 1;
		}
	}
	else if (uMsg == WM_MOUSEMOVE && g_actionInProgress && g_actionInProgress->SetTooltip)
	{
		WDL_FastString tooltip = g_actionInProgress->SetTooltip(BR_ContinuousAction::RULER);
		if (tooltip.GetLength())
		{
			POINT p = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
			ClientToScreen(hwnd, &p);
			SetTooltip(tooltip.Get(), &p);
		}
		else
		{
			SetTooltip(NULL, NULL);
		}
	}
	return g_rulerWndProc(hwnd, uMsg, wParam, lParam);
}
Esempio n. 8
0
	void BR_Timer::Progress (const char* message /*= NULL*/)
	{
		#ifdef WIN32
			LARGE_INTEGER end, ticks;
			QueryPerformanceCounter(&end);
			QueryPerformanceFrequency(&ticks);
			LARGE_INTEGER start = m_start;
			if (m_paused) // in case timer is still paused
				start.QuadPart += end.QuadPart - m_pause.QuadPart;

			double msTime = (double)(end.QuadPart - start.QuadPart) * 1000 / (double)ticks.QuadPart;
		#else
			timeval end;
			gettimeofday(&end, NULL);
			timeval start = m_start;
			if (m_paused) // in case timer is still paused
			{
				timeval temp;
				timersub(&end, &m_pause, &temp);
				timeradd(&m_start, &temp, &start);
			}

			double msTime = (double)(end.tv_sec - start.tv_sec) * 1000 + (double)(end.tv_usec - start.tv_usec) / 1000;
		#endif

		bool paused = m_paused;
		this->Pause();  // ShowConsoleMsg wastes time and Progress can be called at any time during measurement

		WDL_FastString string;
		string.AppendFormatted(256, "%.3f ms to execute: %s\n", msTime, message ? message : m_message.Get());
		ShowConsoleMsg(string.Get());

		if (!paused)  // resume only if time was not paused in the first place
			this->Resume();
	}
Esempio n. 9
0
void CommandTimer (COMMAND_T* ct, int val /*= 0*/, int valhw /*= 0*/, int relmode /*= 0*/, HWND hwnd /*= NULL*/, bool commandHook2 /*= false*/)
{
	#ifdef WIN32
		LARGE_INTEGER ticks, start, end;
		QueryPerformanceFrequency(&ticks);
		QueryPerformanceCounter(&start);
	#else
		timeval start, end;
		gettimeofday(&start, NULL);
	#endif

	if (commandHook2)
		ct->onAction(ct, val, valhw, relmode, hwnd);
	else
		ct->doCommand(ct);

	#ifdef WIN32
		QueryPerformanceCounter(&end);
		int msTime = (int)((double)(end.QuadPart - start.QuadPart) * 1000 / (double)ticks.QuadPart + 0.5);
	#else
		gettimeofday(&end, NULL);
		int msTime = (int)((double)(end.tv_sec - start.tv_sec) * 1000 + (double)(end.tv_usec - start.tv_usec) / 1000 + 0.5);
	#endif

	WDL_FastString string;
	string.AppendFormatted(256, "%d ms to execute: %s\n", msTime, ct->accel.desc);
	ShowConsoleMsg(string.Get());
}
Esempio n. 10
0
// Return TRUE on delete send
bool ResolveMissingRecv(MediaTrack* tr, int iSend, TrackSend* ts, WDL_PtrList<TrackSendFix>* pFix)
{
	WDL_FastString str;
	char* cName = (char*)GetSetMediaTrackInfo(tr, "P_NAME", NULL);
	if (!cName || !cName[0])
		cName = (char*)__LOCALIZE("(unnamed)","sws_DLG_114");
	str.SetFormatted(200, __LOCALIZE_VERFMT("Send %d on track %d \"%s\" is missing its receive track!","sws_DLG_114"), iSend+1, CSurf_TrackToID(tr, false), cName);

	g_cErrorStr = str.Get();
	g_ts = ts;
	g_send = tr;
	g_recv = NULL;

	DialogBox(g_hInst, MAKEINTRESOURCE(IDD_RECVMISSING), g_hwndParent, doResolve);

	if (g_iResolveRet == 1)
		return true;
	else if (g_iResolveRet == 2)
	{
		GUID* newGuid = (GUID*)GetSetMediaTrackInfo(g_recv, "GUID", NULL);
		if (pFix)
			pFix->Add(new TrackSendFix(ts->GetGuid(), newGuid));
		ts->SetGuid(newGuid);
	}

	return false;
}
Esempio n. 11
0
int sInst::runcode(const char *code, bool showerr, bool canfree)
{
  if (m_vm) 
  {
    m_pc.Set("");
    eel_preprocess_strings(this,m_pc,code);
    NSEEL_CODEHANDLE code = NSEEL_code_compile_ex(m_vm,m_pc.Get(),1,canfree ? 0 : NSEEL_CODE_COMPILE_FLAG_COMMONFUNCS);
    char *err;
    if (!code && (err=NSEEL_code_getcodeerror(m_vm)))
    {
      if (NSEEL_code_geterror_flag(m_vm)&1) return 1;
      if (showerr) fprintf(stderr,"NSEEL_code_compile: %s\n",err);
      return -1;
    }
    else
    {
      if (code)
      {
        NSEEL_VM_enumallvars(m_vm,varEnumProc, this);
        NSEEL_code_execute(code);
        if (canfree) NSEEL_code_free(code);
        else m_code_freelist.Add((void*)code);
      }
      return 0;
    }
  }
  return -1;
}
Esempio n. 12
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);
}
Esempio n. 13
0
// appends _tr's state to _chunkOut
//JFB TODO: save envs with beat position info (like it is done for items)
void SaveSingleTrackTemplateChunk(MediaTrack* _tr, WDL_FastString* _chunkOut, bool _delItems, bool _delEnvs)
{
	if (_tr && _chunkOut)
	{
		SNM_TrackEnvParserPatcher p(_tr, false); // no auto-commit!
		if (_delEnvs)
			p.RemoveEnvelopes();

		// systematically remove items whatever is _delItems, then
		// replace them with items + optional beat pos info, if !_delItems (i.e. mimic native templates)
		p.RemoveSubChunk("ITEM", 2, -1);

		_chunkOut->Append(p.GetChunk()->Get());

		if (!_delItems)
		{
			double d;
			WDL_FastString beatInfo;
			for (int i=0; i<GetTrackNumMediaItems(_tr); i++)
			{
				if (MediaItem* item = GetTrackMediaItem(_tr, i))
				{
					SNM_ChunkParserPatcher pitem(item, false); // no auto-commit!
					int posChunk = pitem.GetLinePos(1, "ITEM", "POSITION", 1, 0); // look for the *next* line
					if (--posChunk>=0) { // --posChunk to zap "\n"
						TimeMap2_timeToBeats(NULL, *(double*)GetSetMediaItemInfo(item, "D_POSITION", NULL), NULL, NULL, &d, NULL);
						beatInfo.SetFormatted(32, " %.14f", d);
						pitem.GetChunk()->Insert(beatInfo.Get(), posChunk);
					}
					posChunk = pitem.GetLinePos(1, "ITEM", "SNAPOFFS", 1, 0);
					if (--posChunk>=0) {
						TimeMap2_timeToBeats(NULL, *(double*)GetSetMediaItemInfo(item, "D_SNAPOFFSET", NULL), NULL, NULL, &d, NULL);
						beatInfo.SetFormatted(32, " %.14f", d);
						pitem.GetChunk()->Insert(beatInfo.Get(), posChunk);
					}
					posChunk = pitem.GetLinePos(1, "ITEM", "LENGTH", 1, 0);
					if (--posChunk>=0) {
						TimeMap2_timeToBeats(NULL, *(double*)GetSetMediaItemInfo(item, "D_LENGTH", NULL), NULL, NULL, &d, NULL);
						beatInfo.SetFormatted(32, " %.14f", d);
						pitem.GetChunk()->Insert(beatInfo.Get(), posChunk);
					}
					_chunkOut->Insert(pitem.GetChunk(), _chunkOut->GetLength()-2); // -2: before ">\n"
				}
			}
		}
	}
}
// the API function file_exists() is a bit different, it returns false for folders
bool FileOrDirExists(const char* _fn)
{
	if (_fn && *_fn && *_fn!='.') // valid absolute path (1/2)?
	{
		if (const char* p = strrchr(_fn, PATH_SLASH_CHAR)) // valid absolute path (2/2)?
		{
			WDL_FastString fn;
			fn.Set(_fn, *(p+1)? 0 : (int)(p-_fn)); // // bug fix for directories, skip last PATH_SLASH_CHAR if needed
			struct stat s;
#ifdef _WIN32
			return (statUTF8(fn.Get(), &s) == 0);
#else
			return (stat(fn.Get(), &s) == 0);
#endif
		}
	}
	return false;
}
Esempio n. 15
0
// Functions for getting/setting track FX chains
void GetFXChain(MediaTrack* tr, WDL_TypedBuf<char>* buf)
{
	SNM_ChunkParserPatcher p(tr);
	WDL_FastString chainChunk;
	if (p.GetSubChunk("FXCHAIN", 2, 0, &chainChunk, "<ITEM") > 0) {
		buf->Resize(chainChunk.GetLength() + 1);
		strcpy(buf->Get(), chainChunk.Get());
	}
}
Esempio n. 16
0
bool ItemNotesMatch(MediaItem* _item, const char* _searchStr)
{
	bool match = false;
	if (_item)
	{
		SNM_ChunkParserPatcher p(_item);
		WDL_FastString notes;
		if (p.GetSubChunk("NOTES", 2, 0, &notes, "VOLPAN") >= 0) // rmk: we use VOLPAN as it also exists for empty items
			//JFB TODO? we compare a formated string with a normal one here, oh well..
			match = (stristr(notes.Get(), _searchStr) != NULL);
	}
	return match;
}
Esempio n. 17
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;
}
Esempio n. 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;
}
Esempio n. 19
0
    const char *GetStringForIndex(EEL_F val, WDL_FastString **isWriteableAs=NULL)
    {
      int idx = (int) (val+0.5);
      if (idx>=0 && idx < MAX_USER_STRINGS)
      {
        if (isWriteableAs)
        {
          if (!m_rw_strings[idx]) m_rw_strings[idx] = new WDL_FastString;
          *isWriteableAs = m_rw_strings[idx];
        }
        return m_rw_strings[idx]?m_rw_strings[idx]->Get():"";
      }

      WDL_FastString *s = m_strings.Get(idx - STRING_INDEX_BASE);
      if (isWriteableAs) *isWriteableAs=s;
      return s ? s->Get() : NULL;
    }
Esempio n. 20
0
void PasteTrackGrouping(COMMAND_T* _ct)
{
	int updates = 0;
	for (int i=0; i <= GetNumTracks(); i++) // incl. master
	{
		MediaTrack* tr = CSurf_TrackFromID(i, false);
		if (tr && *(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL))
		{
			SNM_ChunkParserPatcher p(tr);
			updates += p.RemoveLines("GROUP_FLAGS", true); // brutal removing ok: "GROUP_FLAGS" is not part of freeze data
			int patchPos = p.Parse(SNM_GET_CHUNK_CHAR, 1, "TRACK", "TRACKHEIGHT", 0, 0, NULL, NULL, "MAINSEND");
			if (patchPos > 0)
			{
				p.GetChunk()->Insert(g_trackGrpClipboard.Get(), --patchPos);
				p.IncUpdates(); // as we're directly working on the cached chunk..
				updates++;
			}
		}
	}
	if (updates)
		Undo_OnStateChangeEx2(NULL, SWS_CMD_SHORTNAME(_ct), UNDO_STATE_ALL, -1);
}
Esempio n. 21
0
bool GetMarkerRegionDesc(const char* _name, bool _isrgn, int _num, double _pos, double _end, int _flags, bool _wantNum, bool _wantName, bool _wantTime, char* _descOut, int _outSz)
{
	if (_descOut && _outSz &&
		((_isrgn && _flags&SNM_REGION_MASK) || (!_isrgn && _flags&SNM_MARKER_MASK)))
	{
		WDL_FastString desc;
		bool comma = !_wantNum;

		if (_wantNum)
			desc.SetFormatted(64, "%d", _num);

		if (_wantName && _name && *_name)
		{
			if (!comma) { desc.Append(": "); comma = true; }
			desc.Append(_name);
		}

		if (_wantTime)
		{
			if (!comma) { desc.Append(": "); comma = true; }
			char timeStr[64] = "";
			format_timestr_pos(_pos, timeStr, sizeof(timeStr), -1);
			desc.Append(" [");
			desc.Append(timeStr);
			if (_isrgn)
			{
				desc.Append(" -> ");
				format_timestr_pos(_end, timeStr, sizeof(timeStr), -1);
				desc.Append(timeStr);
			}
			desc.Append("]");
		}
		lstrcpyn(_descOut, desc.Get(), _outSz);
		return true;
	}
	return false;
}
Esempio n. 22
0
bool SetTrackGroup(int _group)
{
	int updates = 0;
	WDL_FastString defFlags;
	if (GetDefaultGroupFlags(&defFlags, _group))
	{
		for (int i=0; i <= GetNumTracks(); i++) // incl. master
		{
			MediaTrack* tr = CSurf_TrackFromID(i, false);
			if (tr && *(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL))
			{
				SNM_ChunkParserPatcher p(tr);
				updates += p.RemoveLine("TRACK", "GROUP_FLAGS", 1, 0, "TRACKHEIGHT");
				int pos = p.Parse(SNM_GET_CHUNK_CHAR, 1, "TRACK", "TRACKHEIGHT", 0, 0, NULL, NULL, "INQ");
				if (pos > 0) {
					pos--; // see SNM_ChunkParserPatcher..
					p.GetChunk()->Insert(defFlags.Get(), pos);
					p.SetUpdates(++updates); // as we're directly working on the cached chunk..
				}
			}
		}
	}
	return (updates > 0);
}
Esempio n. 23
0
bool BR_MidiEditor::Build ()
{
	m_take = (m_midiEditor) ? SWS_MIDIEditor_GetTake(m_midiEditor) : m_take;

	if (m_take)
	{
		MediaItem* item = GetMediaItemTake_Item(m_take);
		int takeId = GetTakeId(m_take, item);
		if (takeId >= 0)
		{
			SNM_TakeParserPatcher p(item, CountTakes(item));
			WDL_FastString takeChunk;
			if (p.GetTakeChunk(takeId, &takeChunk))
			{
				SNM_ChunkParserPatcher ptk(&takeChunk, false);
				LineParser lp(false);

				int laneId = 0;
				WDL_FastString lineLane;
				while (ptk.Parse(SNM_GET_SUBCHUNK_OR_LINE, 1, "SOURCE", "VELLANE", laneId++, -1, &lineLane))
				{
					lp.parse(lineLane.Get());
					m_ccLanes.push_back(lp.gettoken_int(1));
					m_ccLanesHeight.push_back(lp.gettoken_int(((m_midiEditor) ? 2 : 3)));
					if (!m_midiEditor && m_ccLanesHeight.back() == 0)
						m_ccLanesHeight.back() = INLINE_MIDI_LANE_DIVIDER_H; // sometimes REAPER will return 0 when lane is completely hidden, but divider will still be visible
					lineLane.DeleteSub(0, lineLane.GetLength());
				}

				WDL_FastString dataLine;
				if (ptk.Parse(SNM_GET_SUBCHUNK_OR_LINE, 1, "SOURCE", "HASDATA", 0, -1, &dataLine))
				{
					lp.parse(dataLine.Get());
					m_ppq = lp.gettoken_int(2);
				}
				else if (ptk.Parse(SNM_GET_SUBCHUNK_OR_LINE, 1, "SOURCE", "FILE", 0, -1, &dataLine))
				{
					lp.parse(dataLine.Get());
					m_ppq = GetMIDIFilePPQ (lp.gettoken_str(1));
					if (!m_ppq)
						return false;
				}
				else
					return false;

				WDL_FastString lineView;
				if (ptk.Parse(SNM_GET_SUBCHUNK_OR_LINE, 1, "SOURCE", "CFGEDITVIEW", 0, -1, &lineView))
				{
					lp.parse(lineView.Get());
					m_startPos = (m_midiEditor) ? lp.gettoken_float(1) : GetMediaItemInfo_Value(GetMediaItemTake_Item(m_take), "D_POSITION");
					m_hZoom    = (m_midiEditor) ? lp.gettoken_float(2) : GetHZoomLevel();
					m_vPos     = (m_midiEditor) ? lp.gettoken_int(3) : lp.gettoken_int(7);
					m_vZoom    = (m_midiEditor) ? lp.gettoken_int(4) : lp.gettoken_int(6);
				}
				else
					return false;

				WDL_FastString lineFilter;
				if (ptk.Parse(SNM_GET_SUBCHUNK_OR_LINE, 1, "SOURCE", "EVTFILTER", 0, -1, &lineFilter))
				{
					lp.parse(lineFilter.Get());
					m_filterEnabled        = !!GetBit(lp.gettoken_int(7), 0);
					m_filterInverted       = !!GetBit(lp.gettoken_int(7), 2);
					m_filterChannel        = lp.gettoken_int(1);
					m_filterEventType      = lp.gettoken_int(2);
					m_filterEventParam     = !!lp.gettoken_int(16);
					m_filterEventVal       = !!lp.gettoken_int(8);
					m_filterEventPos       = !!lp.gettoken_int(14);
					m_filterEventLen       = !!lp.gettoken_int(9);
					m_filterEventParamLo   = lp.gettoken_int(17);
					m_filterEventParamHi   = lp.gettoken_int(18);
					m_filterEventValLo     = lp.gettoken_int(4);
					m_filterEventValHi     = lp.gettoken_int(5);
					m_filterEventPosRepeat = lp.gettoken_float(15);
					m_filterEventPosLo     = lp.gettoken_float(12);
					m_filterEventPosHi     = lp.gettoken_float(13);
					m_filterEventLenLo     = lp.gettoken_float(10);
					m_filterEventLenHi     = lp.gettoken_float(11);
				}
				else
					return false;

				WDL_FastString lineProp;
				if (ptk.Parse(SNM_GET_SUBCHUNK_OR_LINE, 1, "SOURCE", "CFGEDIT", 0, -1, &lineProp))
				{
					lp.parse(lineProp.Get());
					m_pianoroll    = (m_midiEditor) ? lp.gettoken_int(6) : 0; // inline midi editor doesn't have piano roll modes
					m_drawChannel  = lp.gettoken_int(9) - 1;
					m_noteshow     = lp.gettoken_int(18);
					m_timebase     = (m_midiEditor) ? lp.gettoken_int(19) : PROJECT_SYNC;
				}
				else
					return false;

				// A few "corrections" for easier manipulation afterwards
				if (m_filterChannel == 0)     m_filterChannel = ~m_filterChannel;
				if (m_filterEventParamLo < 0) m_filterEventParamLo = 0;
				if (m_filterEventParamHi < 0) m_filterEventParamHi = INT_MAX;
				if (m_filterEventValLo   < 0) m_filterEventValLo   = 0;
				if (m_filterEventValHi   < 0) m_filterEventValHi   = INT_MAX;
				if (m_filterEventPosLo   < 0) m_filterEventPosLo   = 0;
				if (m_filterEventPosHi   < 0) m_filterEventPosHi   = INT_MAX;
				m_filterEventLenLo     = (m_filterEventLenLo     < 0) ? (0)       : (m_ppq * 4 * m_filterEventLenLo);
				m_filterEventLenHi     = (m_filterEventLenHi     < 0) ? (INT_MAX) : (m_ppq * 4 * m_filterEventLenHi);
				m_filterEventPosLo     = (m_filterEventPosLo     < 0) ? (0)       : (m_ppq * 4 * m_filterEventPosLo);
				m_filterEventPosHi     = (m_filterEventPosHi     < 0) ? (INT_MAX) : (m_ppq * 4 * m_filterEventPosHi);
				m_filterEventPosRepeat = (m_filterEventPosRepeat < 0) ? (0)       : (m_ppq * 4 * m_filterEventPosRepeat);

				return true;
			}
		}
	}
	return false;
}
Esempio n. 24
0
void MultiTab_Editor::OpenFileInTab(const char *fnp)
{
  // try to find file to open
  WDL_FastString s;        
  FILE *fp=NULL;
  {
    const char *ptr = fnp;
    while (!fp && *ptr)
    {          
      // first try same path as loading effect
      if (m_filename.Get()[0])
      {
        s.Set(m_filename.Get());
        const char *sp=s.Get()+s.GetLength();
        while (sp>=s.Get() && *sp != '\\' && *sp != '/') sp--;
        s.SetLen(sp + 1 - s.Get());
        if (s.GetLength())
        {
          s.Append(ptr);
          fp=fopenUTF8(s.Get(),"rb");
        }
      }

      // scan past any / or \\, and try again
      if (!fp)
      {
        while (*ptr && *ptr != '\\' && *ptr != '/') ptr++;
        if (*ptr) ptr++;
      }
    }
  }

  if (!fp) 
  {
    s.Set("");
    fp = tryToFindOrCreateFile(fnp,&s);
  }

  if (!fp && s.Get()[0])
  {
    m_newfn.Set(s.Get());

    if (COLS > 25)
    {
      int allowed = COLS-25;
      if (s.GetLength()>allowed)
      {
        s.DeleteSub(0,s.GetLength() - allowed + 3);
        s.Insert("...",0);
      }
      s.Insert("Create new file '",0);
      s.Append("' (Y/n)? ");
    }
    else
      s.Set("Create new file (Y/n)? ");

    m_state=UI_STATE_SAVE_AS_NEW;
    attrset(m_color_message);
    bkgdset(m_color_message);
    mvaddstr(LINES-1,0,s.Get());
    clrtoeol();
    attrset(0);
    bkgdset(0);
  }
  else if (fp)
  {
    fclose(fp);
    int x;
    for (x=0;x<GetTabCount();x++)
    {
      MultiTab_Editor *e = GetTab(x);
      if (e && !stricmp(e->GetFileName(),s.Get()))
      {
        SwitchTab(x,false);
        return;
      }
    }
    AddTab(s.Get());
  }
}
Esempio n. 25
0
// supports folders, multi-selection and routings between tracks too
void SaveSelTrackTemplates(bool _delItems, bool _delEnvs, WDL_FastString* _chunkOut)
{
	if (!_chunkOut)
		return;

	WDL_PtrList<MediaTrack> tracks;

	// append selected track chunks (+ folders) -------------------------------
	for (int i=0; i <= GetNumTracks(); i++) // incl. master
	{
		MediaTrack* tr = CSurf_TrackFromID(i, false);
		if (tr && *(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL))
		{
			SaveSingleTrackTemplateChunk(tr, _chunkOut, _delItems, _delEnvs);
			tracks.Add(tr);

			// folder: save child templates
			WDL_PtrList<MediaTrack>* childTracks = GetChildTracks(tr);
			if (childTracks)
			{
				for (int j=0; j < childTracks->GetSize(); j++) {
					SaveSingleTrackTemplateChunk(childTracks->Get(j), _chunkOut, _delItems, _delEnvs);
					tracks.Add(childTracks->Get(j));
				}
				i += childTracks->GetSize(); // skip children
				delete childTracks;
			}
		}
	}

	// update receives ids ----------------------------------------------------
	// no break keyword used here: multiple tracks in the template
	SNM_ChunkParserPatcher p(_chunkOut);
	WDL_FastString line;
	int occurence = 0;
	int pos = p.Parse(SNM_GET_SUBCHUNK_OR_LINE, 1, "TRACK", "AUXRECV", occurence, 1, &line); 
	while (pos > 0)
	{
		pos--; // see SNM_ChunkParserPatcher

		bool replaced = false;
		line.SetLen(line.GetLength()-1); // remove trailing '\n'
		LineParser lp(false);
		if (!lp.parse(line.Get()) && lp.getnumtokens() > 1)
		{
			int success, curId = lp.gettoken_int(1, &success);
			if (success)
			{
				MediaTrack* tr = CSurf_TrackFromID(curId+1, false);
				int newId = tracks.Find(tr);
				if (newId >= 0)
				{
					const char* p3rdTokenToEol = strchr(line.Get(), ' ');
					if (p3rdTokenToEol) p3rdTokenToEol = strchr((char*)(p3rdTokenToEol+1), ' ');
					if (p3rdTokenToEol)
					{
						WDL_FastString newRcv;
						newRcv.SetFormatted(SNM_MAX_CHUNK_LINE_LENGTH, "AUXRECV %d%s\n", newId, p3rdTokenToEol);
						replaced = p.ReplaceLine(pos, newRcv.Get());
						if (replaced)
							occurence++;
					}
				}
			}
		}

		if (!replaced)
			replaced = p.ReplaceLine(pos, "");
		if (!replaced) // skip, just in case..
			occurence++;

		line.Set("");
		pos = p.Parse(SNM_GET_SUBCHUNK_OR_LINE, 1, "TRACK", "AUXRECV", occurence, 1, &line);
	}
}
void WDL_CursesEditor::runSearch()
{
   if (s_search_string[0]) 
   {
     int wrapflag=0,found=0;
     int line;
     int numlines = m_text.GetSize();
     int startx=m_curs_x+1;
     const int srchlen=strlen(s_search_string);
     for (line = m_curs_y; line < numlines && !found; line ++)
     {
       WDL_FastString *tl = m_text.Get(line);
       const char *p;

       if (tl && (p=tl->Get()))
       {
         const int linelen = tl->GetLength();
         for (; startx <= linelen-srchlen; startx++)
           if (!strnicmp(p+startx,s_search_string,srchlen)) 
           {
             m_select_y1=m_select_y2=m_curs_y=line;
             m_select_x1=m_curs_x=startx;
             m_select_x2=startx+srchlen;
             m_selecting=1;
             found=1;
             break;
           }
       }
            

       startx=0;
     }
     if (!found && (m_curs_y>0 || m_curs_x > 0))
     {
       wrapflag=1;
       numlines = min(m_curs_y+1,numlines);
       for (line = 0; line < numlines && !found; line ++)
       {
         WDL_FastString *tl = m_text.Get(line);
         const char *p;

         if (tl && (p=tl->Get()))
         {
           const int linelen = tl->GetLength();
           for (; startx <= linelen-srchlen; startx++)
             if (!strnicmp(p+startx,s_search_string,srchlen)) 
             {
               m_select_y1=m_select_y2=m_curs_y=line;
               m_select_x1=m_curs_x=startx;
               m_select_x2=startx+srchlen;
               m_selecting=1;
               found=1;
               break;
             }
         }           
         startx=0;
       }
     }
     if (found)
     {
       draw();
       setCursor();
       char buf[512];
       snprintf(buf,sizeof(buf),"Found %s'%s'  Ctrl+G:next",wrapflag?"(wrapped) ":"",s_search_string);
       draw_message(buf);
       return;
     }
   }

   draw();
   setCursor();
   char buf[512];
   if (s_search_string[0]) snprintf(buf,sizeof(buf),"String '%s' not found",s_search_string);
   else lstrcpyn_safe(buf,"No search string",sizeof(buf));
   draw_message(buf);
}
int WDL_CursesEditor::onChar(int c)
{
  if (m_state == -3 || m_state == -4)
  {
    switch (c)
    {
       case '\r': case '\n':
         m_state=0;
         runSearch();
       break;
       case 27: 
         m_state=0; 
         draw();
         setCursor();
         draw_message("Find cancelled.");
       break;
       case KEY_BACKSPACE: if (s_search_string[0]) s_search_string[strlen(s_search_string)-1]=0; m_state=-4; break;
       default: 
         if (VALIDATE_TEXT_CHAR(c)) 
         { 
           int l=m_state == -3 ? 0 : strlen(s_search_string); 
           m_state = -4;
           if (l < (int)sizeof(s_search_string)-1) { s_search_string[l]=c; s_search_string[l+1]=0; } 
         } 
        break;
     }
     if (m_state)
     {
       attrset(m_color_message);
       bkgdset(m_color_message);
       mvaddstr(LINES-1,29,s_search_string);
       clrtoeol(); 
       attrset(0);
       bkgdset(0);
     }
     return 0;
  }
  if (c==KEY_DOWN || c==KEY_UP || c==KEY_PPAGE||c==KEY_NPAGE || c==KEY_RIGHT||c==KEY_LEFT||c==KEY_HOME||c==KEY_END)
  {
    if (SHIFT_KEY_DOWN)      
    {
      if (!m_selecting)
      {
        m_select_x2=m_select_x1=m_curs_x; m_select_y2=m_select_y1=m_curs_y;
        m_selecting=1;
      }
    }
    else if (m_selecting) { m_selecting=0; draw(); }
  }

  switch(c)
  {
    case 'O'-'A'+1:
      if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN)
      {
        if (m_pane_div <= 0.0 || m_pane_div >= 1.0)
        {
          onChar('P'-'A'+1);
        }
        if (m_pane_div > 0.0 && m_pane_div < 1.0) 
        {
          m_curpane=!m_curpane;
          draw();
          draw_status_state();
          int paney[2], paneh[2];
          GetPaneDims(paney, paneh);
          if (m_curs_y-m_paneoffs_y[m_curpane] < 0) m_curs_y=m_paneoffs_y[m_curpane];
          else if (m_curs_y-m_paneoffs_y[m_curpane] >= paneh[m_curpane]) m_curs_y=paneh[m_curpane]+m_paneoffs_y[m_curpane]-1;
          setCursor();
        }
      }
    break;
    case 'P'-'A'+1:
      if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN)
      {
        if (m_pane_div <= 0.0 || m_pane_div >= 1.0) 
        {
          m_pane_div=0.5;
          m_paneoffs_y[1]=m_paneoffs_y[0];
        }
        else 
        {
          m_pane_div=1.0;
          if (m_curpane) m_paneoffs_y[0]=m_paneoffs_y[1];
          m_curpane=0;
        }
        draw();
        draw_status_state();

        int paney[2], paneh[2];
        const int pane_divy=GetPaneDims(paney, paneh);
        setCursor();
      }
    break;
    
    case 407:
    case 'Z'-'A'+1:
      if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN)
      {
        if (m_undoStack_pos > 0)
        {
           m_undoStack_pos--;
           loadUndoState(m_undoStack.Get(m_undoStack_pos));
           draw();
           setCursor();
           char buf[512];
           snprintf(buf,sizeof(buf),"Undid action - %d items in undo buffer",m_undoStack_pos);
           draw_message(buf);
        }
        else 
        {
          draw_message("Can't Undo");
        }   
        break;
      }
    // fall through
    case 'Y'-'A'+1:
      if ((c == 'Z'-'A'+1 || !SHIFT_KEY_DOWN) && !ALT_KEY_DOWN)
      {
        if (m_undoStack_pos < m_undoStack.GetSize()-1)
        {
          m_undoStack_pos++;
          loadUndoState(m_undoStack.Get(m_undoStack_pos));
          draw();
          setCursor();
          char buf[512];
          snprintf(buf,sizeof(buf),"Redid action - %d items in redo buffer",m_undoStack.GetSize()-m_undoStack_pos-1);
          draw_message(buf);
        }
        else 
        {
          draw_message("Can't Redo");  
        }
      }
    break;
    case KEY_IC:
      if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN)
      {
        s_overwrite=!s_overwrite;
        setCursor();
        break;
      }
      // fqll through
    case 'V'-'A'+1:
      if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN)
      {
        // generate a m_clipboard using win32 clipboard data
        WDL_PtrList<const char> lines;
        WDL_String buf;
#ifdef WDL_IS_FAKE_CURSES
        if (CURSES_INSTANCE)
        {
          OpenClipboard(CURSES_INSTANCE->m_hwnd);
          HANDLE h=GetClipboardData(CF_TEXT);
          if (h)
          {
            char *t=(char *)GlobalLock(h);
            int s=GlobalSize(h);
            buf.Set(t,s);
            GlobalUnlock(t);        
          }
          CloseClipboard();
        }
        else
#endif
        {
          buf.Set(s_fake_clipboard.Get());
        }

        if (buf.Get() && buf.Get()[0])
        {
          char *src=buf.Get();
          while (*src)
          {
            char *seek=src;
            while (*seek && *seek != '\r' && *seek != '\n') seek++;
            char hadclr=*seek;
            if (*seek) *seek++=0;
            lines.Add(src);

            if (hadclr == '\r' && *seek == '\n') seek++;

            if (hadclr && !*seek)
            {
              lines.Add("");
            }
            src=seek;
          }
        }
        if (lines.GetSize())
        {
          removeSelect();
          // insert lines at m_curs_y,m_curs_x
          if (m_curs_y >= m_text.GetSize()) m_curs_y=m_text.GetSize()-1;
          if (m_curs_y < 0) m_curs_y=0;

          preSaveUndoState();
          WDL_FastString poststr;
          int x;
          int indent_to_pos = -1;
          for (x = 0; x < lines.GetSize(); x ++)
          {
            WDL_FastString *str=m_text.Get(m_curs_y);
            const char *tstr=lines.Get(x);
            if (!tstr) tstr="";
            if (!x)
            {
              if (str)
              {
                if (m_curs_x < 0) m_curs_x=0;
                int tmp=str->GetLength();
                if (m_curs_x > tmp) m_curs_x=tmp;
  
                poststr.Set(str->Get()+m_curs_x);
                str->SetLen(m_curs_x);

                const char *p = str->Get();
                while (*p == ' ' || *p == '\t') p++;
                if (!*p && p > str->Get())
                {
                  if (lines.GetSize()>1)
                  {
                    while (*tstr == ' ' || *tstr == '\t') tstr++;
                  }
                  indent_to_pos = m_curs_x;
                }

                str->Append(tstr);
              }
              else
              {
                m_text.Insert(m_curs_y,(str=new WDL_FastString(tstr)));
              }
              if (lines.GetSize() > 1)
              {
                m_curs_y++;
              }
              else
              {
                m_curs_x = str->GetLength();
                str->Append(poststr.Get());
              }
           }
           else if (x == lines.GetSize()-1)
           {
             WDL_FastString *s=newIndentedFastString(tstr,indent_to_pos);
             m_curs_x = s->GetLength();
             s->Append(poststr.Get());
             m_text.Insert(m_curs_y,s);
           }
           else
           {
             m_text.Insert(m_curs_y,newIndentedFastString(tstr,indent_to_pos));
             m_curs_y++;
           }
         }
         draw();
         setCursor();
         draw_message("Pasted");
         saveUndoState();
       }
       else 
       {
         setCursor();
         draw_message("Clipboard empty");
       }
     }
  break;

  case KEY_DC:
    if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN)
    {
      WDL_FastString *s;
      if (m_selecting)
      {
        preSaveUndoState();
        removeSelect();
        draw();
        saveUndoState();
        setCursor();
      }
      else if ((s=m_text.Get(m_curs_y)))
      {
        if (m_curs_x < s->GetLength())
        {
          preSaveUndoState();

          bool hadCom = LineCanAffectOtherLines(s->Get(),m_curs_x,1); 
          s->DeleteSub(m_curs_x,1);
          if (!hadCom) hadCom = LineCanAffectOtherLines(s->Get(),-1,-1);
          draw(hadCom ? -1 : m_curs_y);
          saveUndoState();
          setCursor();
        }
        else // append next line to us
        {
          if (m_curs_y < m_text.GetSize()-1)
          {
            preSaveUndoState();

            WDL_FastString *nl=m_text.Get(m_curs_y+1);
            if (nl)
            {
              s->Append(nl->Get());
            }
            m_text.Delete(m_curs_y+1,true);

            draw();
            saveUndoState();
            setCursor();
          }
        }
      }
      break;
    }
  case 'C'-'A'+1:
  case 'X'-'A'+1:
    if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN && m_selecting)
    {
      if (c!= 'C'-'A'+1) m_selecting=0;
      int miny,maxy,minx,maxx;
      int x;
      getselectregion(minx,miny,maxx,maxy);
      const char *status="";
      char statusbuf[512];

      if (minx != maxx|| miny != maxy) 
      {
        int bytescopied=0;
        s_fake_clipboard.Set("");

        int lht=0,fht=0;
        if (c != 'C'-'A'+1) preSaveUndoState();

        for (x = miny; x <= maxy; x ++)
        {
          WDL_FastString *s=m_text.Get(x);
          if (s) 
          {
            const char *str=s->Get();
            int sx,ex;
            if (x == miny) sx=max(minx,0);
            else sx=0;
            int tmp=s->GetLength();
            if (sx > tmp) sx=tmp;
      
            if (x == maxy) ex=min(maxx,tmp);
            else ex=tmp;
      
            bytescopied += ex-sx + (x!=maxy);
            if (s_fake_clipboard.Get() && s_fake_clipboard.Get()[0]) s_fake_clipboard.Append("\r\n");
            s_fake_clipboard.Append(ex-sx?str+sx:"",ex-sx);

            if (c != 'C'-'A'+1)
            {
              if (sx == 0 && ex == tmp) // remove entire line
              {
                m_text.Delete(x,true);
                if (x==miny) miny--;
                x--;
                maxy--;
              }
              else { if (x==miny) fht=1; if (x == maxy) lht=1; s->DeleteSub(sx,ex-sx); }
            }
          }
        }
        if (fht && lht && miny+1 == maxy)
        {
          m_text.Get(miny)->Append(m_text.Get(maxy)->Get());
          m_text.Delete(maxy,true);
        }
        if (c != 'C'-'A'+1)
        {
          m_curs_y=miny;
          if (m_curs_y < 0) m_curs_y=0;
          m_curs_x=minx;
          saveUndoState();
          snprintf(statusbuf,sizeof(statusbuf),"Cut %d bytes",bytescopied);
        }
        else
          snprintf(statusbuf,sizeof(statusbuf),"Copied %d bytes",bytescopied);

#ifdef WDL_IS_FAKE_CURSES
        if (CURSES_INSTANCE)
        {
          int l=s_fake_clipboard.GetLength()+1;
          HANDLE h=GlobalAlloc(GMEM_MOVEABLE,l);
          void *t=GlobalLock(h);
          memcpy(t,s_fake_clipboard.Get(),l);
          GlobalUnlock(h);
          OpenClipboard(CURSES_INSTANCE->m_hwnd);
          EmptyClipboard();
          SetClipboardData(CF_TEXT,h);
          CloseClipboard();
        }
#endif

        status=statusbuf;
      }
      else status="No selection";

      draw();
      setCursor();
      draw_message(status);
    }
  break;
  case 'A'-'A'+1:
    if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN)
    {
      m_selecting=1;
      m_select_x1=0;
      m_select_y1=0;
      m_select_y2=m_text.GetSize()-1;
      m_select_x2=0;
      if (m_text.Get(m_select_y2))
        m_select_x2=m_text.Get(m_select_y2)->GetLength();
      draw();
      setCursor();
    }
  break;
  case 27:
    if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN && m_selecting)
    {
      m_selecting=0;
      draw();
      setCursor();
      break;
    }
  break;
  case KEY_F3:
  case 'G'-'A'+1:
    if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN && s_search_string[0])
    {
      runSearch();
      return 0;
    }
  // fall through
  case 'F'-'A'+1:
    if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN)
    {
      draw_message("");
      attrset(m_color_message);
      bkgdset(m_color_message);
      mvaddstr(LINES-1,0,"Find string (ESC to cancel): ");
      if (m_selecting && m_select_y1==m_select_y2)
      {
        WDL_FastString* s=m_text.Get(m_select_y1);
        if (s)
        {
          const char* p=s->Get();
          int xlo=min(m_select_x1, m_select_x2);
          int xhi=max(m_select_x1, m_select_x2);
          int i;
          for (i=xlo; i < xhi; ++i)
          {
            if (!isalnum(p[i]) && p[i] != '_') break;
          }
          if (i == xhi && xhi > xlo && xhi-xlo < sizeof(s_search_string))
          {
            lstrcpyn(s_search_string, p+xlo, xhi-xlo+1);
          }
        }
      }
      addstr(s_search_string);
      clrtoeol();
      attrset(0);
      bkgdset(0);
      m_state=-3; // find, initial (m_state=4 when we've typed something)
    }
  break;
  case KEY_DOWN:
    {
      if (CTRL_KEY_DOWN)
      {
        int paney[2], paneh[2];
        GetPaneDims(paney, paneh);
        int maxscroll=m_text.GetSize()-paneh[m_curpane]+4;
        if (m_paneoffs_y[m_curpane] < maxscroll-1)
        {
          m_paneoffs_y[m_curpane]++;
          if (m_curs_y < m_paneoffs_y[m_curpane]) m_curs_y=m_paneoffs_y[m_curpane];
          draw();
        }
      }
      else
      {
        m_curs_y++;
        if (m_curs_y>=m_text.GetSize()) m_curs_y=m_text.GetSize()-1;
        if (m_curs_y < 0) m_curs_y=0;
      }
      if (m_selecting) { setCursor(1); m_select_x2=m_curs_x; m_select_y2=m_curs_y; draw(); }
      setCursor(1);
    }
  break;
  case KEY_UP:
    {
      if (CTRL_KEY_DOWN)
      {
        if (m_paneoffs_y[m_curpane] > 0)
        {
          int paney[2], paneh[2];
          GetPaneDims(paney, paneh);
          m_paneoffs_y[m_curpane]--;
          if (m_curs_y >  m_paneoffs_y[m_curpane]+paneh[m_curpane]-1) m_curs_y = m_paneoffs_y[m_curpane]+paneh[m_curpane]-1;
          if (m_curs_y < 0) m_curs_y=0;
          draw();
        }
      }
      else
      {
        if(m_curs_y>0) m_curs_y--;
      }
      if (m_selecting) { setCursor(1); m_select_x2=m_curs_x; m_select_y2=m_curs_y; draw(); }
      setCursor(1);
    }
  break;
  case KEY_PPAGE:
    {
      if (m_curs_y > m_paneoffs_y[m_curpane])
      {
        m_curs_y=m_paneoffs_y[m_curpane];
        if (m_curs_y < 0) m_curs_y=0;
      }
      else 
      {
        int paney[2], paneh[2];
        GetPaneDims(paney, paneh);
        m_curs_y -= paneh[m_curpane];
        if (m_curs_y < 0) m_curs_y=0;
        m_paneoffs_y[m_curpane]=m_curs_y;
      }
      if (m_selecting) { setCursor(1); m_select_x2=m_curs_x; m_select_y2=m_curs_y; }
      draw();
      setCursor(1);
    }
  break; 
  case KEY_NPAGE:
    {
      int paney[2], paneh[2]; 
      GetPaneDims(paney, paneh);
      if (m_curs_y >= m_paneoffs_y[m_curpane]+paneh[m_curpane]-1) m_paneoffs_y[m_curpane]=m_curs_y-1;
      m_curs_y = m_paneoffs_y[m_curpane]+paneh[m_curpane]-1;
      if (m_curs_y >= m_text.GetSize()) m_curs_y=m_text.GetSize()-1;
      if (m_curs_y < 0) m_curs_y=0;
      if (m_selecting) { setCursor(1); m_select_x2=m_curs_x; m_select_y2=m_curs_y; }
      draw();
      setCursor(1);
    }
  break;
  case KEY_RIGHT:
    {
      if (1) // wrap across lines
      {
        WDL_FastString *s = m_text.Get(m_curs_y);
        if (s && m_curs_x >= s->GetLength() && m_curs_y < m_text.GetSize()) { m_curs_y++; m_curs_x = -1; }
      }

      if(m_curs_x<0) 
      {
        m_curs_x=0;
      }
      else
      {
        if (CTRL_KEY_DOWN)
        {
          WDL_FastString *s = m_text.Get(m_curs_y);
          if (!s||m_curs_x >= s->GetLength()) break;
          int lastType = categorizeCharForWordNess(s->Get()[m_curs_x++]);
          while (m_curs_x < s->GetLength())
          {
            int thisType = categorizeCharForWordNess(s->Get()[m_curs_x]);
            if (thisType != lastType && thisType != 0) break;
            lastType=thisType;
            m_curs_x++;
          }
        }
        else 
        {
          m_curs_x++;
        }
      }
      if (m_selecting) { setCursor(); m_select_x2=m_curs_x; m_select_y2=m_curs_y; draw(); }
      setCursor();
    }
  break;
  case KEY_LEFT:
    {
      bool doMove=true;
      if (1) // wrap across lines
      {
        WDL_FastString *s = m_text.Get(m_curs_y);
        if (s && m_curs_y>0 && m_curs_x == 0) 
        { 
          s = m_text.Get(--m_curs_y);
          if (s) 
          {
            m_curs_x = s->GetLength(); 
            doMove=false;
          }
        }
      }

      if(m_curs_x>0 && doMove) 
      {
        if (CTRL_KEY_DOWN)
        {
          WDL_FastString *s = m_text.Get(m_curs_y);
          if (!s) break;
          if (m_curs_x > s->GetLength()) m_curs_x = s->GetLength();
          m_curs_x--;

          int lastType = categorizeCharForWordNess(s->Get()[m_curs_x--]);
          while (m_curs_x >= 0)
          {
            int thisType = categorizeCharForWordNess(s->Get()[m_curs_x]);
            if (thisType != lastType && lastType != 0) break;
            lastType=thisType;
            m_curs_x--;
          }
          m_curs_x++;
        }
        else 
        {
          m_curs_x--;
        }
      }
      if (m_selecting) { setCursor(); m_select_x2=m_curs_x; m_select_y2=m_curs_y; draw(); }
      setCursor();
    }
  break;
  case KEY_HOME:
    {
      m_curs_x=0;
      if (CTRL_KEY_DOWN) m_curs_y=0;
      if (m_selecting) { setCursor(); m_select_x2=m_curs_x; m_select_y2=m_curs_y; draw(); }
      setCursor();
    }
  break;
  case KEY_END:
    {
      if (m_text.Get(m_curs_y)) m_curs_x=m_text.Get(m_curs_y)->GetLength();
      if (CTRL_KEY_DOWN) m_curs_y=m_text.GetSize();
      if (m_selecting) { setCursor(); m_select_x2=m_curs_x; m_select_y2=m_curs_y; draw(); }
      setCursor();
    }
  break;
  case KEY_BACKSPACE: // backspace, baby
    if (m_selecting)
    {
      preSaveUndoState();
      removeSelect();
      draw();
      saveUndoState();
      setCursor();
    }
    else if (m_curs_x > 0)
    {
      WDL_FastString *tl=m_text.Get(m_curs_y);
      if (tl)
      {
        preSaveUndoState();

        bool hadCom = LineCanAffectOtherLines(tl->Get(), m_curs_x-1,1);
        tl->DeleteSub(--m_curs_x,1);
        if (!hadCom) hadCom = LineCanAffectOtherLines(tl->Get(),-1,-1);
        draw(hadCom?-1:m_curs_y);
        saveUndoState();
        setCursor();
      }
    }
    else // append current line to previous line
    {
      WDL_FastString *fl=m_text.Get(m_curs_y-1), *tl=m_text.Get(m_curs_y);
      if (!tl) 
      {
        m_curs_y--;
        if (fl) m_curs_x=fl->GetLength();
        draw();
        saveUndoState();
        setCursor();
      }
      else if (fl)
      {
        preSaveUndoState();
        m_curs_x=fl->GetLength();
        fl->Append(tl->Get());

        m_text.Delete(m_curs_y--,true);
        draw();
        saveUndoState();
        setCursor();
      }
    }
  break;
  case 'L'-'A'+1:
    if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN)
    {
      draw();
      setCursor();
    }
  break;
  case 13: //KEY_ENTER:
    //insert newline
    preSaveUndoState();

    if (m_selecting) { removeSelect(); draw(); setCursor(); }
    if (m_curs_y >= m_text.GetSize())
    {
      m_curs_y=m_text.GetSize();
      m_text.Add(new WDL_FastString);
    }
    if (s_overwrite)
    {
      WDL_FastString *s = m_text.Get(m_curs_y);
      int plen=0;
      const char *pb=NULL;
      if (s)
      {
        pb = s->Get();
        while (plen < m_curs_x && (pb[plen]== ' ' || pb[plen] == '\t')) plen++;
      }
      if (++m_curs_y >= m_text.GetSize())
      {
        m_curs_y = m_text.GetSize();
        WDL_FastString *ns=new WDL_FastString;
        if (plen>0) ns->Set(pb,plen);
        m_text.Insert(m_curs_y,ns);
      }
      s = m_text.Get(m_curs_y);
      if (s && plen > s->GetLength()) plen=s->GetLength();
      m_curs_x=plen;
    }
    else 
    {
      WDL_FastString *s = m_text.Get(m_curs_y);
      if (s)
      {
        if (m_curs_x > s->GetLength()) m_curs_x = s->GetLength();
        WDL_FastString *nl = new WDL_FastString();
        int plen=0;
        const char *pb = s->Get();
        while (plen < m_curs_x && (pb[plen]== ' ' || pb[plen] == '\t')) plen++;

        if (plen>0) nl->Set(pb,plen);

        nl->Append(pb+m_curs_x);
        m_text.Insert(++m_curs_y,nl);
        s->SetLen(m_curs_x);
        m_curs_x=plen;
      }
    }
    m_offs_x=0;

    draw();
    saveUndoState();
    setCursor();
  break;
  case '\t':
    if (m_selecting)
    {
      preSaveUndoState();

      bool isRev = !!(GetAsyncKeyState(VK_SHIFT)&0x8000);
      indentSelect(isRev?-m_indent_size:m_indent_size);
      // indent selection:
      draw();
      setCursor();
      saveUndoState();
      break;
    }
  default:
    //insert char
    if(VALIDATE_TEXT_CHAR(c))
    { 
      preSaveUndoState();

      if (m_selecting) { removeSelect(); draw(); setCursor(); }
      if (!m_text.Get(m_curs_y)) m_text.Insert(m_curs_y,new WDL_FastString);

      WDL_FastString *ss;
      if ((ss=m_text.Get(m_curs_y)))
      {
        char str[64];
        int slen ;
        if (c == '\t') 
        {
          slen = min(m_indent_size,64);
          if (slen<1) slen=1;
          int x; 
          for(x=0;x<slen;x++) str[x]=' ';
        }
        else
        {
          str[0]=c;
          slen = 1;
        }


        bool hadCom = LineCanAffectOtherLines(ss->Get(),-1,-1);
        if (s_overwrite)
        {
          if (!hadCom) hadCom = LineCanAffectOtherLines(ss->Get(),m_curs_x,slen);
          ss->DeleteSub(m_curs_x,slen);
        }
        ss->Insert(str,m_curs_x,slen);
        if (!hadCom) hadCom = LineCanAffectOtherLines(ss->Get(),m_curs_x,slen);

        m_curs_x += slen;

        draw(hadCom ? -1 : m_curs_y);
      }
      saveUndoState();
      setCursor();
    }
    break;
  }
  return 0;
}
Esempio n. 28
0
static bool ContinuousActionInit (bool init, int cmd, BR_ContinuousAction* action)
{
	static accelerator_register_t s_accelerator = { ContinuousActionTranslateAccel, TRUE, NULL };

	bool initSuccessful = true;
	if (init)
	{
		GetConfig("tooltips", g_tooltips);
		g_actionInProgress = action;
		if (g_actionInProgress)
		{
			if (g_actionInProgress->Init)
				initSuccessful = g_actionInProgress->Init(true);
		}
		else
			initSuccessful = false;

		if (initSuccessful)
		{
			if (g_actionInProgress->SetMouseCursor || g_actionInProgress->SetTooltip)
			{
				SetConfig("tooltips", SetBit(SetBit(SetBit(g_tooltips, 0), 1), 2));

				if (!g_arrangeWndProc && GetArrangeWnd())
				{
					if (g_actionInProgress->SetTooltip)
					{
						WDL_FastString tooltip = g_actionInProgress->SetTooltip(BR_ContinuousAction::ARRANGE);
						if (tooltip.GetLength())
						{
							POINT p; GetCursorPos(&p);
							SetTooltip(tooltip.Get(), &p);
						}
					}
					g_arrangeWndProc = (WNDPROC)SetWindowLongPtr(GetArrangeWnd(), GWLP_WNDPROC, (LONG_PTR)ArrangeWndProc);
					if (g_actionInProgress->SetMouseCursor && g_actionInProgress->SetMouseCursor(BR_ContinuousAction::ARRANGE))
						SendMessage(GetArrangeWnd(), WM_SETCURSOR, (WPARAM)GetArrangeWnd(), 0);
					InvalidateRect(GetArrangeWnd(), NULL, TRUE); // kill existing native tooltip, if any
				}

				if (!g_rulerWndProc && GetRulerWndAlt())
				{
					if (g_actionInProgress->SetTooltip)
					{
						WDL_FastString tooltip = g_actionInProgress->SetTooltip(BR_ContinuousAction::RULER);
						if (tooltip.GetLength())
						{
							POINT p; GetCursorPos(&p);
							SetTooltip(tooltip.Get(), &p);
						}
					}

					g_rulerWndProc = (WNDPROC)SetWindowLongPtr(GetRulerWndAlt(), GWLP_WNDPROC, (LONG_PTR)RulerWndProc);
					if (g_actionInProgress->SetMouseCursor && g_actionInProgress->SetMouseCursor(BR_ContinuousAction::RULER))
						SendMessage(GetRulerWndAlt(), WM_SETCURSOR, (WPARAM)GetRulerWndAlt(), 0);
					InvalidateRect(GetRulerWndAlt(), NULL, TRUE);
				}
			}

			plugin_register("accelerator", &s_accelerator);
			plugin_register("timer", (void*)ContinuousActionTimer);
		}
		else
		{
			g_actionInProgress = NULL;
		}
	}
	else
	{
		SetConfig("tooltips", g_tooltips);

		if (g_arrangeWndProc && GetArrangeWnd())
		{
			SetWindowLongPtr(GetArrangeWnd(), GWLP_WNDPROC, (LONG_PTR)g_arrangeWndProc);
			SendMessage(GetArrangeWnd(), WM_SETCURSOR, (WPARAM)GetArrangeWnd(), 0);
			InvalidateRect(GetArrangeWnd(), NULL, FALSE);
			g_arrangeWndProc = NULL;
		}

		if (g_rulerWndProc && GetRulerWndAlt())
		{
			SetWindowLongPtr(GetRulerWndAlt(), GWLP_WNDPROC, (LONG_PTR)g_rulerWndProc);
			SendMessage(GetRulerWndAlt(), WM_SETCURSOR, (WPARAM)GetRulerWndAlt(), 0);
			InvalidateRect(GetRulerWndAlt(), NULL, FALSE);
			g_rulerWndProc = NULL;
		}

		SetTooltip(NULL, NULL);

		plugin_register("-accelerator", &s_accelerator);
		plugin_register("-timer", (void*)ContinuousActionTimer);

		if (g_actionInProgress->Init)
			g_actionInProgress->Init(false);
		g_actionInProgress = NULL;
	}

	return initSuccessful;
}
Esempio n. 29
0
int EEL_Editor::GetCommentStateForLineStart(int line)
{
  
#ifdef START_ON_VARS_KEYWORD
  s_declaredFuncs.DeleteAll();
  s_declaredVars.DeleteAll();
#endif
  m_indent_size=2;
  const bool uses_code_start_lines = !!is_code_start_line(NULL);

  int state=0;
  int x=0;

  if (uses_code_start_lines)
  {
    state=STATE_BEFORE_CODE;
    for (;;x++)
    {
      WDL_FastString *t = m_text.Get(x);
      if (!t || is_code_start_line(t->Get())) break;
    
      const char *p=t->Get();

      if (!strnicmp(p,"tabsize:",8))
      {
        int a = atoi(p+8);
        if (a>0 && a < 32) m_indent_size = a;
      }

      #ifdef START_ON_VARS_KEYWORD
      if (!strnicmp(p,"var",3) && isspace(p[3]))
      {
        const char *endp=p + t->GetLength();
        const char *tok;
        int toklen;
        p+=4;
        while (NULL != (tok = sh_tokenize(&p,endp,&toklen,NULL)))
        {
          if (isalpha(tok[0]) || tok[0] == '_' || tok[0] == '#')
          {
            char buf[512];
            if (toklen > sizeof(buf)-1) toklen=sizeof(buf)-1;
            lstrcpyn_safe(buf,tok,toklen+1);
            s_declaredVars.AddUnsorted(buf,1);
          }
        }
      }
      #endif
    }


    // scan backwards to find line starting with @
    for (x=line;x>=0;x--)
    {
      WDL_FastString *t = m_text.Get(x);
      if (!t) break;
      if (is_code_start_line(t->Get()))
      {
        state=0;
        break;
      }
    }
    x++;
  }

  #ifdef START_ON_VARS_KEYWORD
  s_declaredVars.Resort();
  #endif
  s_draw_parentokenstack.Resize(0,false);

  for (;x<line;x++)
  {
    WDL_FastString *t = m_text.Get(x);
    const char *p = t?t->Get():"";
    if (is_code_start_line(p)) 
    {
      s_draw_parentokenstack.Resize(0,false);
      state=0; 
    }
    else if (state != STATE_BEFORE_CODE)
    {
      const int ll=t?t->GetLength():0;
      const char *endp = p+ll;
      int toklen;
      const char *tok;
      while (NULL != (tok=sh_tokenize(&p,endp,&toklen,&state))) // eat all tokens, updating state
      {
        sh_func_ontoken(tok,toklen);
        sh_draw_parentokenstack_update(tok,toklen);
      }
    }
  }
  return state;
}
Esempio n. 30
0
// _type: 0=Post-Fader (Post-Pan), 1=Pre-FX, 2=deprecated, 3=Pre-Fader (Post-FX)
// _undoMsg: NULL=no undo
bool CueBuss(const char* _undoMsg, const char* _busName, int _type, bool _showRouting,
			 int _soloDefeat, char* _trTemplatePath, bool _sendToMaster, int* _hwOuts) 
{
	if (!SNM_CountSelectedTracks(NULL, false))
		return false;

	WDL_FastString tmplt;
	if (_trTemplatePath && (!FileOrDirExists(_trTemplatePath) || !LoadChunk(_trTemplatePath, &tmplt) || !tmplt.GetLength()))
	{
		char msg[SNM_MAX_PATH] = "";
		lstrcpyn(msg, __LOCALIZE("Cue buss not created!\nNo track template file defined","sws_DLG_149"), sizeof(msg));
		if (*_trTemplatePath)
			_snprintfSafe(msg, sizeof(msg), __LOCALIZE_VERFMT("Cue buss not created!\nTrack template not found (or empty): %s","sws_DLG_149"), _trTemplatePath);
		MessageBox(GetMainHwnd(), msg, __LOCALIZE("S&M - Error","sws_DLG_149"), MB_OK);
		return false;
	}

	bool updated = false;
	MediaTrack * cueTr = NULL;
	SNM_SendPatcher* p = NULL;
	for (int i=1; i <= GetNumTracks(); i++) // skip master
	{
		MediaTrack* tr = CSurf_TrackFromID(i, false);
		if (tr && *(int*)GetSetMediaTrackInfo(tr, "I_SELECTED", NULL))
		{
			GetSetMediaTrackInfo(tr, "I_SELECTED", &g_i0);

			// add the buss track, done once!
			if (!cueTr)
			{
				InsertTrackAtIndex(GetNumTracks(), false);
				TrackList_AdjustWindows(false);
				cueTr = CSurf_TrackFromID(GetNumTracks(), false);
				GetSetMediaTrackInfo(cueTr, "P_NAME", (void*)_busName);

				p = new SNM_SendPatcher(cueTr);

				if (tmplt.GetLength())
				{
					WDL_FastString chunk;
					MakeSingleTrackTemplateChunk(&tmplt, &chunk, true, true, false);
					ApplyTrackTemplate(cueTr, &chunk, false, false, p);
				}
				updated = true;
			}

			// add a send
			if (cueTr && p && tr != cueTr)
				AddReceiveWithVolPan(tr, cueTr, _type, p);
		}
	}

	if (cueTr && p)
	{
		// send to master/parent init
		if (!tmplt.GetLength())
		{
			// solo defeat
			if (_soloDefeat) {
				char one[2] = "1";
				updated |= (p->ParsePatch(SNM_SET_CHUNK_CHAR, 1, "TRACK", "MUTESOLO", 0, 3, one) > 0);
			}
			
			// master/parend send
			WDL_FastString mainSend;
			mainSend.SetFormatted(SNM_MAX_CHUNK_LINE_LENGTH, "MAINSEND %d 0", _sendToMaster?1:0);

			// adds hw outputs
			if (_hwOuts)
			{
				int monoHWCount=0; 
				while (GetOutputChannelName(monoHWCount)) monoHWCount++;

				bool cr = false;
				for(int i=0; i<SNM_MAX_HW_OUTS; i++)
				{
					if (_hwOuts[i])
					{
						if (!cr) {
							mainSend.Append("\n"); 
							cr = true;
						}
						if (_hwOuts[i] >= monoHWCount) 
							mainSend.AppendFormatted(32, "HWOUT %d ", (_hwOuts[i]-monoHWCount) | 1024);
						else
							mainSend.AppendFormatted(32, "HWOUT %d ", _hwOuts[i]-1);

						mainSend.Append("0 ");
						mainSend.AppendFormatted(20, "%.14f ", *(double*)GetConfigVar("defhwvol"));
						mainSend.Append("0.00000000000000 0 0 0 -1.00000000000000 -1\n");
					}
				}
				if (!cr)
					mainSend.Append("\n"); // hot
			}

			// patch both updates (no break keyword here: new empty track)
			updated |= p->ReplaceLine("TRACK", "MAINSEND", 1, 0, mainSend.Get());
		}

		p->Commit();
		delete p;

		if (updated)
		{
			GetSetMediaTrackInfo(cueTr, "I_SELECTED", &g_i1);
			UpdateTimeline();
			ScrollSelTrack(true, true);
			if (_showRouting) 
				Main_OnCommand(40293, 0);
			if (_undoMsg)
				Undo_OnStateChangeEx2(NULL, _undoMsg, UNDO_STATE_ALL, -1);
		}
	}
	return updated;
}