Replacing goto simply for the replacements sake is generally a bad idea, goto is not bad because there is something inherently bad in using this keyword, but because it leads to poorly designed code.
Meaning a 1-1 substitution, while getting rid of goto, will not get rid of the design of the code, and therefore does not improve code quality.
The clearest example for this I can think of:
label foo;
begin
...
goto foo;
...
foo:
...
can be replaced with:
type TGotoFooException = class;
begin
try
...
raise TGotoFooException.Create;
...
except on e: TGotoFooException do;
end;
...
I think it is pretty obvious that the second code, even though it does not contain goto is actually worse in every way.
So I am also not really fond of the way it was done by marcov, because the code does not really get more readable with these while true, continue-break approaches, because this is basically the same jumping around, just less obvious.
IMHO you should change the design of that function a bit to use the full extend of the tools available to you. These are:
1. Try-Finally to allow you to jump to a final code block that should be executed in the end, meaning together with exit() this can be used as "jump to end"
2. If blocks let you jump over blocks depending on a condition, which can basically express a jump down to
3. repeat until lets you jump back to the beginning of a block if a condition is true, which basically expresses a jump up to
4. While basically combines the features of if and repeat-until
5. Functions allow you to call code blocks by name independently of the current position in code.
Your function does basically the following:
1. if a certain condition is fulfilled, simply skip the whole function
2. execute some code (reload, disploop)
3. with the results of step 2 do other code and either decide if you are finished, need to start over at 2 or start over at 2 but skip the reloading.
4. on finish execute some final code (even if step 1 skip is done)
First the obvious the 4. point can be realized with a try-finally and the first point with the exit "function".
try
if Condition1 then
Exit;
// LOOPCode
finally
Code14
end;
So let's look into the loop code.
First and foremost it is always a good idea to put code in separate functions to have concise and readable functions (use nested functions to not fill up your scope with one-time use functions), so for all your Code #N comments I will simply assume that there is a function for it called CodeN
The next thing is, Reload and DispLoop belong together, if Reload is executed disploop will always be also executed. So Reload is optional and disploop is mandatory. There are two ways to implement this, explicitly skip Reload or explicitly execute Reload.
Because the number of Reloads is not so significantly different from the number of disploops without reloads, I think the best option would be to explicitely skip reload so we can simply do this function:
procedure DispLoop(reload: boolean);
begin
if Reload then // (explicit) skip of reload if not requested
Code4; // reload section
Code5; // disploop section
end;
Your loop then can be expressed by a repeat-until (as you want it to run at least once and multiple times if requested). Whether you want to execute reload or not needs to be saved in some form of state variable:
repeat
DispLoop(doReload); // function defined above
// Condition 2
if Condition 3
// case statement
until Condition3 Or VK = 0;
The two loop breaking cases Condition 3 and VK = 0 are already covered by the loop condition, so if you read your code you will now see on a first glance what the stop condition is (which is much more complicated if it is a break or continue or goto buried somewhere deep in your code).
For condition2 you have two possibilities, using continue, which will directly jump to the beginning of the loop again, or to combine condition 3 and 2:
// first option:
repeat
DispLoop(Reload); // function defined above
Reload = false;
if Condition2 then Continue;
if Condition 3
// case statement
unti notl Condition3 Or VK = 0;
// Second option
repeat
DispLoop(Reload); // function defined above
if not Condition2 and Condition 3
// case statement
until (not Condition2 and Condition3) Or VK = 0;
Personally I think the continue call is cleaner if you follow my advice and encapsulate the DispLoop and reload functionality into another function (and therefore the loop will be pretty slim). If you decide to pack everything in here and create a monster loop, I think that the second approach will be better because otherwise the continue will be buried in the code and not be visible that simple
So finally your case statement reduces to setting the reload variable
case VK of
1:
begin
Reload := not Condition4;
if Reload then
Code6;
end;
2:
begin
Reload := true;
Code7;
end;
3:
begin
Code8;
Reload := not Condition5;
if Reload then
Code10
else
Code9;
end;
4:
begin
Code11;
Reload := False;
if not Condition6 and Condition7 then
begin
Code12;
Reload := True;
end;
end;
5:
begin
Code13;
Reload := False;
end;
end;
Of course how the conditions inside the if are built can be up to you (I like only setting reload an then branching over reload)
Putting it all together
var
Reload: Boolean = true;
begin
try
if Condition1 then Exit;
repeat
DispLoop(Reload);
Reload := False;
If Condition2 then Continue;
if Condition3 then
case VK of
1:
begin
Reload := not Condition4;
if Reload then
Code6;
end;
2:
begin
Reload := true;
Code7;
end;
3:
begin
Code8;
Reload := not Condition5;
if Reload then
Code10
else
Code9;
end;
4:
begin
Code11;
Reload := False;
if not Condition6 and Condition7 then
begin
Code12;
Reload := True;
end;
end;
5:
begin
Code13;
Reload := False;
end;
end;
until not Condition3 or (VK=0);
finally
Code14;
end;
end;