Exemple #1
0
Exec_stat MCF_parsetextatts(Properties which, MCStringRef data,
                            uint4 &flags, MCStringRef &fname, uint2 &height,
                            uint2 &size, uint2 &style)
{
	int2 i1;
	switch (which)
	{
	case P_TEXT_ALIGN:
		flags &= ~F_ALIGNMENT;
		if (MCStringIsEqualToCString(data, MCleftstring, kMCCompareCaseless) || MCStringIsEmpty(data))
			flags |= F_ALIGN_LEFT;
		else
			if (MCStringIsEqualToCString(data, MCcenterstring, kMCCompareCaseless))
				flags |= F_ALIGN_CENTER;
			else
				if (MCStringIsEqualToCString(data, MCrightstring, kMCCompareCaseless))
					flags |= F_ALIGN_RIGHT;
				else
					if (MCStringIsEqualToCString(data, MCjustifystring, kMCCompareCaseless))
						flags |= F_ALIGN_JUSTIFY;
					else
					{
						MCeerror->add(EE_OBJECT_BADALIGN, 0, 0, data);
						return ES_ERROR;
					}
		break;
	case P_TEXT_FONT:
		{// MW-2012-02-17: [[ IntrinsicUnicode ]] Strip any lang tag from the
			//   fontname.
			uindex_t t_offset;
			if (MCStringFirstIndexOfChar(data, ',', 0, kMCCompareExact, t_offset))
				/* UNCHECKED */ MCStringCopySubstring(data, MCRangeMake(t_offset + 1, MCStringGetLength(data) - (t_offset + 1)), fname);
			else
				fname = MCValueRetain(data);
		}
		break;
	case P_TEXT_HEIGHT:
		if (!MCU_stoi2(data, i1))
		{
			MCeerror->add
			(EE_OBJECT_TEXTHEIGHTNAN, 0, 0, data);
			return ES_ERROR;
		}
		height = i1;
		break;
	case P_TEXT_SIZE:
		if (MCStringIsEmpty(data))
			i1 = 0;
		else
			if (!MCU_stoi2(data, i1))
			{
				MCeerror->add
				(EE_OBJECT_TEXTSIZENAN, 0, 0, data);
				return ES_ERROR;
			}
		size = i1;
		break;
	case P_TEXT_STYLE:
		{
			// MW-2012-02-17: [[ SplitTextAttrs ]] If the string is empty, then
			//   return 0 for the style - indicating to unset the property.
            if (MCStringIsEmpty(data))
				style = 0;
			else
            {
                style = FA_DEFAULT_STYLE;
                uindex_t t_start_pos, t_end_pos;
                t_end_pos = 0;
                
                while (t_end_pos < MCStringGetLength(data))
                {
                    t_start_pos = t_end_pos;
                    // skip spaces at the beginning or after a comma (if any)
                    MCU_skip_spaces(data, t_start_pos);
                    
                    uindex_t t_comma;
                    if (!MCStringFirstIndexOfChar(data, ',', t_start_pos, kMCCompareExact, t_comma))
                        t_end_pos = MCStringGetLength(data);
                    else
                        t_end_pos = t_comma;
                    
                    MCAutoStringRef tdata;
                    /* UNCHECKED */ MCStringCopySubstring(data, MCRangeMake(t_start_pos, t_end_pos - t_start_pos), &tdata);
                    t_end_pos++;
                    if (MCF_setweightstring(style, *tdata))
						continue;
					if (MCF_setexpandstring(style, *tdata))
						continue;
					if (MCF_setslantlongstring(style, *tdata))
						continue;
					if (MCStringIsEqualToCString(*tdata, MCplainstring, kMCCompareCaseless))
					{
						style = FA_DEFAULT_STYLE;
						continue;
					}
					if (MCStringIsEqualToCString(*tdata, MCmixedstring, kMCCompareCaseless))
					{
						style = FA_DEFAULT_STYLE;
						continue;
					}
					if (MCStringIsEqualToCString(*tdata, MCboxstring, kMCCompareCaseless))
					{
						style &= ~FA_3D_BOX;
						style |= FA_BOX;
						continue;
                    }
                
					if (MCStringIsEqualToCString(*tdata, MCthreedboxstring, kMCCompareCaseless))
					{
						style &= ~FA_BOX;
						style |= FA_3D_BOX;
						continue;
					}
					if (MCStringIsEqualToCString(*tdata, MCunderlinestring, kMCCompareCaseless))
					{
						style |= FA_UNDERLINE;
						continue;
					}
					if (MCStringIsEqualToCString(*tdata, MCstrikeoutstring, kMCCompareCaseless))
					{
						style |= FA_STRIKEOUT;
						continue;
					}
					if (MCStringIsEqualToCString(*tdata, MCgroupstring, kMCCompareCaseless) || MCStringIsEqualToCString(*tdata, MClinkstring, kMCCompareCaseless))
					{
						style |= FA_LINK;
						continue;
					}
					MCeerror->add(EE_OBJECT_BADSTYLE, 0, 0, data);
					return ES_ERROR;
				}
			}
		}
		break;
	default:
		break;
	}
	return ES_NORMAL;
}
Exemple #2
0
void MCSort::additem(MCExecPoint &ep, MCSortnode *&items, uint4 &nitems, Sort_type form, MCString &s, MCExpression *by)
{
	if (by != NULL)
	{
		MCerrorlock++;
		ep.setsvalue(s);
		MCeach->store(ep, False);
		if (by->eval(ep) == ES_NORMAL)
			s = ep.getsvalue();
		else
			s = MCnullmcstring;
		MCerrorlock--;
	}
	switch (form)
	{
	case ST_DATETIME:
		ep.setsvalue(s);
		if (MCD_convert(ep, CF_UNDEFINED, CF_UNDEFINED, CF_SECONDS, CF_UNDEFINED))
		{
			if (!MCU_stor8(ep.getsvalue(), items[nitems].nvalue))
				items[nitems].nvalue = -MAXREAL8;
		}
		else
			items[nitems].nvalue = -MAXREAL8;
		break;
	case ST_NUMERIC:
		{
			const char *sptr = s.getstring();
			uint4 length = s.getlength();
			
			// MW-2013-03-21: [[ Bug ]] Make sure we skip any whitespace before the
			//   number starts - making it consistent with string->number conversions
			//   elsewhere.
			MCU_skip_spaces(sptr, length);
			
		    // REVIEW - at the moment the numeric prefix of the string is used to
			//   derive the sort key e.g. 1000abc would get processed as 1000.
			while (length && (isdigit((uint1)*sptr) ||
			                  *sptr == '.' || *sptr == '-' || *sptr == '+'))
			{
				sptr++;
				length--;
			}
			s.setlength(s.getlength() - length);
			if (!MCU_stor8(s, items[nitems].nvalue))
				items[nitems].nvalue = -MAXREAL8;
		}
		break;
	default:
		if (ep.getcasesensitive() && by == NULL)
			items[nitems].svalue = (char *)s.getstring();
		else
			if (ep.getcasesensitive())
				items[nitems].svalue = s.clone();
			else
			{
#if defined(_MAC_DESKTOP) || defined(_IOS_MOBILE)
				if (form == ST_INTERNATIONAL)
				{
					extern char *MCSystemLowercaseInternational(const MCString& s);
					items[nitems].svalue = MCSystemLowercaseInternational(s);
				}
				else
#endif

				{
					items[nitems].svalue = new char[s.getlength() + 1];
					MCU_lower(items[nitems].svalue, s);
					items[nitems].svalue[s.getlength()] = '\0';
				}
			}
		break;
	}
	nitems++;
}
Exemple #3
0
Exec_stat MCF_parsetextatts(Properties which, const MCString &data,
                            uint4 &flags, char *&fname, uint2 &height,
                            uint2 &size, uint2 &style)
{
	int2 i1;
	switch (which)
	{
	case P_TEXT_ALIGN:
		flags &= ~F_ALIGNMENT;
		if (data == MCleftstring || data.getlength() == 0)
			flags |= F_ALIGN_LEFT;
		else
			if (data == MCcenterstring)
				flags |= F_ALIGN_CENTER;
			else
				if (data == MCrightstring)
					flags |= F_ALIGN_RIGHT;
				else
					if (data == MCjustifystring)
						flags |= F_ALIGN_JUSTIFY;
					else
					{
						MCeerror->add(EE_OBJECT_BADALIGN, 0, 0, data);
						return ES_ERROR;
					}
		break;
	case P_TEXT_FONT:
		{
			fname = data.clone();
			
			// MW-2012-02-17: [[ IntrinsicUnicode ]] Strip any lang tag from the
			//   fontname.
			char *t_tag;
			t_tag = strchr(fname, ',');
			if (t_tag != nil)
				t_tag[0] = '\0';
		}
		break;
	case P_TEXT_HEIGHT:
		if (!MCU_stoi2(data, i1))
		{
			MCeerror->add
			(EE_OBJECT_TEXTHEIGHTNAN, 0, 0, data);
			return ES_ERROR;
		}
		height = i1;
		break;
	case P_TEXT_SIZE:
		if (data.getlength() == 0)
			i1 = 0;
		else
			if (!MCU_stoi2(data, i1))
			{
				MCeerror->add
				(EE_OBJECT_TEXTSIZENAN, 0, 0, data);
				return ES_ERROR;
			}
		size = i1;
		break;
	case P_TEXT_STYLE:
		{
			// MW-2012-02-17: [[ SplitTextAttrs ]] If the string is empty, then
			//   return 0 for the style - indicating to unset the property.
			uint4 l = data.getlength();
			const char *sptr = data.getstring();
			if (l == 0)
				style = 0;
			else
			{
				style = FA_DEFAULT_STYLE;
				while (l)
				{
					const char *startptr = sptr;
					if (!MCU_strchr(sptr, l, ','))
					{
						sptr += l;
						l = 0;
					}
					MCString tdata(startptr, sptr - startptr);
					MCU_skip_char(sptr, l);
					MCU_skip_spaces(sptr, l);
					if (MCF_setweightstring(style, tdata))
						continue;
					if (MCF_setexpandstring(style, tdata))
						continue;
					if (MCF_setslantlongstring(style, tdata))
						continue;
					if (tdata == MCplainstring)
					{
						style = FA_DEFAULT_STYLE;
						continue;
					}
					if (tdata == MCmixedstring)
					{
						style = FA_DEFAULT_STYLE;
						continue;
					}
					if (tdata == MCboxstring)
					{
						style &= ~FA_3D_BOX;
						style |= FA_BOX;
						continue;
					}
					if (tdata == MCthreedboxstring)
					{
						style &= ~FA_BOX;
						style |= FA_3D_BOX;
						continue;
					}
					if (tdata == MCunderlinestring)
					{
						style |= FA_UNDERLINE;
						continue;
					}
					if (tdata == MCstrikeoutstring)
					{
						style |= FA_STRIKEOUT;
						continue;
					}
					if (tdata == MCgroupstring || tdata == MClinkstring)
					{
						style |= FA_LINK;
						continue;
					}
					MCeerror->add(EE_OBJECT_BADSTYLE, 0, 0, data);
					return ES_ERROR;
				}
			}
		}
		break;
	default:
		break;
	}
	return ES_NORMAL;
}
Exemple #4
0
Exec_stat MCFunction::evalparams(Functions func, MCParameter *params,
                                 MCExecPoint &ep)
{
	uint4 nparams = 0;
	real8 n, tn, oldn;
	n = oldn = 0.0;
	MCSortnode *mditems = NULL;
	// JS-2013-06-19: [[ StatsFunctions ]] Support for new stats functions based on arithmeticMean
	if (func == F_AVG_DEV || func == F_POP_STD_DEV || func == F_POP_VARIANCE || func == F_SMP_STD_DEV || func == F_SMP_VARIANCE)
	{ //use recursion to get average first
		if (evalparams(F_ARI_MEAN, params, ep) != ES_NORMAL)
			return ES_ERROR;
		oldn = ep.getnvalue();
	}
	// JS-2013-06-19: [[ StatsFunctions ]] Support for geometricMean
	if (func == F_GEO_MEAN)
	{ //use recursion to count items first
		if (evalparams(F_UNDEFINED, params, ep) != ES_NORMAL)
			return ES_ERROR;
		oldn = ep.getnvalue();
	}
	if (func == F_MEDIAN)
	{ //use recursion to count items first
		if (evalparams(F_UNDEFINED, params, ep) != ES_NORMAL)
			return ES_ERROR;
		mditems = new MCSortnode[(uint4)ep.getnvalue()];
	}
	if (params != NULL && params->getnext() == NULL)
	{
		if (params->eval(ep) != ES_NORMAL)
		{
			MCeerror->add(EE_FUNCTION_BADSOURCE, line, pos);
			return ES_ERROR;
		}
		if (ep.getformat() == VF_ARRAY)
		{
			if (ep.getarray() -> is_array() && ep.getarray()->get_array()->dofunc(ep, func, nparams, n, oldn, mditems) != ES_NORMAL)
			{
				MCeerror->add(EE_FUNCTION_BADSOURCE, line, pos);
				return ES_ERROR;
			}
		}
		else
		{
			MCString s(ep.getsvalue());
			uint4 length = s.getlength();
			const char *sptr = s.getstring();
			MCU_skip_spaces(sptr, length);
			while (length != 0)
			{
				s.setstring(sptr);
				if (!MCU_strchr(sptr, length, ','))
				{
					s.setlength(length);
					length = 0;
				}
				else
				{
					s.setlength(sptr - s.getstring());
					MCU_skip_char(sptr, length);
					MCU_skip_spaces(sptr, length);
				}
				if (s.getlength() == 0)
					tn = 0.0;
				else
					if (!MCU_stor8(s, tn))
					{
						MCeerror->add
						(EE_FUNCTION_NAN, 0, 0, s);
						return ES_ERROR;
					}
				MCU_dofunc(func, nparams, n, tn, oldn, mditems);
			}
		}
	}
	else
	{
		MCParameter *tparam = params;
		while (tparam != NULL)
		{
			if (tparam->eval(ep) != ES_NORMAL || ep.ton() != ES_NORMAL)
			{
				MCeerror->add(EE_FUNCTION_BADSOURCE, line, pos);
				return ES_ERROR;
			}
			MCU_dofunc(func, nparams, n, ep.getnvalue(), oldn, mditems);
			tparam = tparam->getnext();
		}
	}
	
	if (nparams != 0)
		switch (func)
	{
		// JS-2013-06-19: [[ StatsFunctions ]] Support for arithmeticMean (was average)
		case F_ARI_MEAN:
			n /= nparams;
			break;
		// JS-2013-06-19: [[ StatsFunctions ]] Support for averageDeviation
		case F_AVG_DEV:
			n /= nparams;
			break;
		// JS-2013-06-19: [[ StatsFunctions ]] Support for harmonicMean
		case F_HAR_MEAN:
			n = nparams/n;
			break;
		case F_MEDIAN:
			{
				uint4 toffset;
				MCU_sort(mditems, nparams, ST_ASCENDING, ST_NUMERIC);
				toffset = (nparams + 1)/2 - 1;
				if ((nparams % 2) != 0) //odd
					n = mditems[toffset].nvalue;
				else //even average 2 closest values
					n = (mditems[toffset].nvalue + mditems[toffset+1].nvalue)/2;
				break;
			}
		// JS-2013-06-19: [[ StatsFunctions ]] Support for populationStandardDeviation
		case F_POP_STD_DEV:
			n = sqrt(n/nparams);
			break;
		// JS-2013-06-19: [[ StatsFunctions ]] Support for populationVariance
		case F_POP_VARIANCE:
			n /= nparams;
			break;
		// JS-2013-06-19: [[ StatsFunctions ]] Support for sampleStandardDeviation (was stdDev)
		case F_SMP_STD_DEV:
			n = sqrt(n/(nparams - 1));
			break;
		// JS-2013-06-19: [[ StatsFunctions ]] Support for sampleVariance
		case F_SMP_VARIANCE:
			n /= nparams - 1;
			break;
		case F_UNDEFINED:
			n = nparams;
			break;
		default:
			break;
		}
	ep.setnvalue(n);
	delete mditems;
	return ES_NORMAL;
}
Exemple #5
0
Exec_stat MCRepeat::exec(MCExecPoint &ep)
{
	real8 endn = 0.0;
	int4 count = 0;
	MCExecPoint ep2(ep);
	MCScriptPoint *sp = NULL;
	Parse_stat ps;
	const char *sptr;
	uint4 l;
	MCVariableValue *tvar = NULL;
	MCHashentry *hptr = NULL;
	uint4 kindex = 0;
	Boolean donumeric = False;
	Exec_stat stat;
	switch (form)
	{
	case RF_FOR:
		if (loopvar != NULL)
		{
			while ((stat = endcond->eval(ep2)) != ES_NORMAL
			        && (MCtrace || MCnbreakpoints) && !MCtrylock && !MClockerrors)
				MCB_error(ep2, getline(), getpos(), EE_REPEAT_BADFORCOND);
			if (stat != ES_NORMAL)
			{
				MCeerror->add(EE_REPEAT_BADFORCOND, line, pos);
				return ES_ERROR;
			}
			if (each == FU_ELEMENT)
			{
				tvar = ep2.getarray();
				if (tvar != NULL && tvar -> is_array())
				{
					l = 1;
					kindex = 0;
					donumeric = tvar -> get_array() -> isnumeric();
					hptr = tvar -> get_array() -> getnextelement(kindex, hptr, donumeric, ep);
					if (hptr == NULL)
					{
						kindex = 0;
						donumeric = False;
						hptr = tvar -> get_array() -> getnextelement(kindex, hptr, donumeric, ep);
					}
				}
				else
					l = 0;
			}
			else if (each == FU_KEY)
			{
				tvar = ep2.getarray();
				if (tvar != NULL && tvar -> is_array())
				{
					l = 1;
					kindex = 0;
					donumeric = False;
					hptr = tvar -> get_array() -> getnextkey(kindex, hptr);
					// [[ Bug 3871 ]] : If hptr is NULL then we are done already (this can happen
					//                  with an empty custom property set).
					if (hptr == NULL)
						l = 0;
				}
				else
					l = 0;
			}
			else
			{
				sptr = ep2.getsvalue().getstring();
				l = ep2.getsvalue().getlength();
				if (each == FU_WORD)
					MCU_skip_spaces(sptr, l);
				else
					if (each == FU_TOKEN)
					{
						sp = new MCScriptPoint(ep2);
						ps = sp->nexttoken();
						if (ps == PS_ERROR || ps == PS_EOF)
							l = 0;
					}
			}
		}
		else
		{
			while (((stat = endcond->eval(ep)) != ES_NORMAL
			        || (stat = ep.ton()) != ES_NORMAL) && (MCtrace || MCnbreakpoints)
			        && !MCtrylock && !MClockerrors)
				MCB_error(ep, getline(), getpos(), EE_REPEAT_BADFORCOND);
			if (stat != ES_NORMAL)
			{
				MCeerror->add
				(EE_REPEAT_BADFORCOND, line, pos);
				return ES_ERROR;
			}
			count = MCU_max(ep.getint4(), 0);
		}
		break;
	case RF_WITH:
		if (step != NULL)
		{
			while (((stat = step->eval(ep)) != ES_NORMAL
			        || (stat = ep.ton()) != ES_NORMAL) && (MCtrace || MCnbreakpoints)
			        && !MCtrylock && !MClockerrors)
				MCB_error(ep, getline(), getpos(), EE_REPEAT_BADWITHSTEP);
			stepval = ep.getnvalue();
			if (stat != ES_NORMAL || stepval == 0.0)
			{
				MCeerror->add
				(EE_REPEAT_BADWITHSTEP, line, pos);
				return ES_ERROR;
			}
		}
		while (((stat = startcond->eval(ep)) != ES_NORMAL
		        || (stat = ep.ton()) != ES_NORMAL) && (MCtrace || MCnbreakpoints)
		        && !MCtrylock && !MClockerrors)
			MCB_error(ep, getline(), getpos(), EE_REPEAT_BADWITHSTART);
		if (stat != ES_NORMAL)
		{
			MCeerror->add
			(EE_REPEAT_BADWITHSTART, line, pos);
			return ES_ERROR;
		}
		ep.setnvalue(ep.getnvalue() - stepval);
		while ((stat = loopvar->set
		               (ep)) != ES_NORMAL
		        && (MCtrace || MCnbreakpoints) && !MCtrylock && !MClockerrors)
			MCB_error(ep, getline(), getpos(), EE_REPEAT_BADWITHVAR);
		if (stat != ES_NORMAL)
		{
			MCeerror->add
			(EE_REPEAT_BADWITHVAR, line, pos);
			return ES_ERROR;
		}
		while (((stat = endcond->eval(ep)) != ES_NORMAL
		        || (stat = ep.ton()) != ES_NORMAL)
		        && (MCtrace || MCnbreakpoints) && !MCtrylock && !MClockerrors)
			MCB_error(ep, getline(), getpos(), EE_REPEAT_BADWITHEND);
		if (stat != ES_NORMAL)
		{
			MCeerror->add
			(EE_REPEAT_BADWITHEND, line, pos);
			return ES_ERROR;
		}
		endn = ep.getnvalue();
		break;
	default:
		break;
	}

	MCString s;
	Boolean done = False;
	bool t_first;
	t_first = false;
	while (True)
	{
		switch (form)
		{
		case RF_FOREVER:
			break;
		case RF_FOR:
			if (loopvar != NULL)
			{
				if (l == 0)
				{
					done = True;
					// OK-2007-12-05 : Bug 5605. If there has been at least one iteration, set the loop variable to 
					// whatever the value was in the last iteration. 
					if (!t_first)
					{
						// MW-2011-02-08: [[ Bug ]] Make sure we don't use 's' if the repeat type is 'key' or
						//   'element'.
						if (each != FU_ELEMENT && each != FU_KEY)
						{
							ep.setsvalue(s);
							loopvar->set(ep);
						}
					}
				}
				else
				{
					const char *startptr; // = sptr;
					switch (each)
					{
					case FU_KEY:
						// MW-2010-12-15: [[ Bug 9218 ]] Make a copy of the key so that it can't be mutated
						//   accidentally.
						ep . setstaticcstring(hptr -> string);
						loopvar -> set(ep);
						hptr = tvar -> get_array() -> getnextkey(kindex, hptr);
						if (hptr == NULL)
							l = 0;
						break;
					case FU_ELEMENT:
						hptr -> value . fetch(ep);
						loopvar -> set(ep);
						hptr = tvar -> get_array() -> getnextelement(kindex, hptr, donumeric, ep);
						if (hptr == NULL)
							l = 0;
						break;
					case FU_LINE:
						startptr = sptr;
						if (!MCU_strchr(sptr, l, ep.getlinedel()))
						{
							sptr += l;
							l = 0;
						}
						s.set(startptr, sptr - startptr);
						MCU_skip_char(sptr, l);
						break;
					case FU_ITEM:
						startptr = sptr;
						if (!MCU_strchr(sptr, l, ep.getitemdel()))
						{
							sptr += l;
							l = 0;
						}
						s.set(startptr, sptr - startptr);
						MCU_skip_char(sptr, l);
						break;
					case FU_WORD:
						startptr = sptr;
						if (*sptr == '\"')
						{
							MCU_skip_char(sptr, l);
							while (l && *sptr != '\"' && *sptr != '\n')
								MCU_skip_char(sptr, l);
							MCU_skip_char(sptr, l);
						}
						else
							while (l && !isspace((uint1)*sptr))
								MCU_skip_char(sptr, l);
						s.set(startptr, sptr - startptr);
						MCU_skip_spaces(sptr, l);
						break;
					case FU_TOKEN:
						s = sp->gettoken();
						ps = sp->nexttoken();
						if (ps == PS_ERROR || ps == PS_EOF)
							l = 0;
						break;
					case FU_CHARACTER:
					default:
						startptr = sptr;
						s.set(startptr, 1);
						MCU_skip_char(sptr, l);
					}
					// MW-2010-12-15: [[ Bug 9218 ]] Added KEY to the type of repeat that already
					//   copies the value.
					if (each != FU_ELEMENT && each != FU_KEY)
					{
						if (MCtrace)
						{
							ep.setsvalue(s);
							loopvar->set(ep);
						}
						else
							loopvar->sets(s);
					}
				}
			}
			else
				done = count-- == 0;
			break;
		case RF_UNTIL:
			while ((stat = endcond->eval(ep)) != ES_NORMAL
			        && (MCtrace || MCnbreakpoints) && !MCtrylock && !MClockerrors)
				MCB_error(ep, getline(), getpos(), EE_REPEAT_BADUNTILCOND);
			if (stat != ES_NORMAL)
			{
				MCeerror->add
				(EE_REPEAT_BADUNTILCOND, line, pos);
				return ES_ERROR;
			}
			done = ep.getsvalue() == MCtruemcstring;
			break;
		case RF_WHILE:
			while ((stat = endcond->eval(ep)) != ES_NORMAL
			        && (MCtrace || MCnbreakpoints) && !MCtrylock && !MClockerrors)
				MCB_error(ep, getline(), getpos(), EE_REPEAT_BADWHILECOND);
			if (stat != ES_NORMAL)
			{
				MCeerror->add
				(EE_REPEAT_BADWHILECOND, line, pos);
				return ES_ERROR;
			}
			done = ep.getsvalue() != MCtruemcstring;
			break;
		case RF_WITH:
			while (((stat = loopvar->eval(ep)) != ES_NORMAL
			        || (stat = ep.ton()) != ES_NORMAL)
			        && (MCtrace || MCnbreakpoints) && !MCtrylock && !MClockerrors)
				MCB_error(ep, getline(), getpos(), EE_REPEAT_BADWITHVAR);
			if (stat != ES_NORMAL)
			{
				MCeerror->add
				(EE_REPEAT_BADWITHVAR, line, pos);
				return ES_ERROR;
			}
			if (stepval < 0)
			{
				if (ep.getnvalue() <= endn)
					done = True;
			}
			else
				if (ep.getnvalue() >= endn)
					done = True;
			if (!done)
			{
				ep.setnvalue(ep.getnvalue() + stepval);
				while ((stat = loopvar->set
				               (ep)) != ES_NORMAL
				        && (MCtrace || MCnbreakpoints) && !MCtrylock && !MClockerrors)
					MCB_error(ep, getline(), getpos(), EE_REPEAT_BADWITHVAR);
				if (stat != ES_NORMAL)
				{
					MCeerror->add
					(EE_REPEAT_BADWITHVAR, line, pos);
					return ES_ERROR;
				}
			}
			break;
		default:
			break;
		}
		if (done)
			break;

		Exec_stat stat;
		MCStatement *tspr = statements;
		while (tspr != NULL)
		{
			if (MCtrace || MCnbreakpoints)
			{
				MCB_trace(ep, tspr->getline(), tspr->getpos());
				if (MCexitall)
					break;
			}
			ep.setline(tspr->getline());

			stat = tspr->exec(ep);

			// MW-2011-08-17: [[ Redraw ]] Flush any screen updates.
			MCRedrawUpdateScreen();
			
			switch(stat)
			{
			case ES_NORMAL:
				if (MCexitall)
				{
					// OK-2007-12-05 : Bug 5605 : If exiting loop, set the loop variable to the value it had
					//   in the last iteration.
					// MW-2011-02-08: [[ Bug ]] Make sure we don't use 's' if the repeat type is 'key' or
					//   'element'.
					if (form == RF_FOR && loopvar != NULL && each != FU_ELEMENT && each != FU_KEY)
					{
						ep.setsvalue(s);
						loopvar->set(ep);
					}
					delete sp;
					return ES_NORMAL;
				}
				tspr = tspr->getnext();
				break;
			case ES_NEXT_REPEAT:
				tspr = NULL;
				break;
			case ES_EXIT_REPEAT:
				// OK-2007-12-05 : Bug 5605 : If exiting loop, set the loop variable to the value it had
				//   in the last iteration.
				// MW-2011-02-08: [[ Bug ]] Make sure we don't use 's' if the repeat type is 'key' or
				//   'element'.
				if (form == RF_FOR && loopvar != NULL && each != FU_ELEMENT && each != FU_KEY)
				{
					ep.setsvalue(s);
					loopvar->set(ep);
				}
				delete sp;
				return ES_NORMAL;
			case ES_ERROR:
				if ((MCtrace || MCnbreakpoints) && !MCtrylock && !MClockerrors)
					do
					{
						MCB_error(ep, tspr->getline(), tspr->getpos(),
						          EE_REPEAT_BADSTATEMENT);
					}
					while (MCtrace && (stat = tspr->exec(ep)) != ES_NORMAL);
				if (stat == ES_ERROR)
				{
					// OK-2007-12-05 : Bug 5605 : If exiting loop, set the loop variable to the value it had
					//   in the last iteration.
					// MW-2011-02-08: [[ Bug ]] Make sure we don't use 's' if the repeat type is 'key' or
					//   'element'.
					if (form == RF_FOR && loopvar != NULL && each != FU_ELEMENT && each != FU_KEY)
					{
						ep.setsvalue(s);
						loopvar->set(ep);
					}
					delete sp;
					if (MCexitall)
						return ES_NORMAL;
					else
					{
						MCeerror->add(EE_REPEAT_BADSTATEMENT, line, pos);
						return ES_ERROR;
					}
				}
				else
					tspr = tspr->getnext();
				break;
			default:
				// OK-2007-12-05 : Bug 5605 : If exiting loop, set the loop variable to the value it had
				//   in the last iteration.
				// MW-2011-02-08: [[ Bug ]] Make sure we don't use 's' if the repeat type is 'key' or
				//   'element'.
				if (form == RF_FOR && loopvar != NULL && each != FU_ELEMENT && each != FU_KEY)
				{
					ep.setsvalue(s);
					loopvar->set(ep);
				}
				delete sp;
				return stat;
			}
		}
		if (MCscreen->abortkey())
		{
			// OK-2007-12-05 : Bug 5605 : If exiting loop, set the loop variable to the value it had
			//   in the last iteration.
			// MW-2011-02-08: [[ Bug ]] Make sure we don't use 's' if the repeat type is 'key' or
			//   'element'.
			if (form == RF_FOR && loopvar != NULL && each != FU_ELEMENT && each != FU_KEY)
			{
				ep.setsvalue(s);
				loopvar->set(ep);
			}
			delete sp;
			MCeerror->add(EE_REPEAT_ABORT, line, pos);
			return ES_ERROR;
		}
		if (MCtrace || MCnbreakpoints)
		{
			MCB_trace(ep, getline(), getpos());
			if (MCexitall)
				break;
		}

		t_first = false;
	}
	delete sp;
	return ES_NORMAL;
}