=
BEGIN
ROPE: TYPE = Rope.ROPE;
Handle: TYPE = ReadEvalPrint.Handle;
PDA: PrincOps.PDABase = PrincOps.PDA;
normalButtonName, foregroundButtonName, backgroundButtonName: ROPE;
NoteProfile:
PROC [reason: UserProfile.ProfileChangeReason]
--UserProfile.ProfileChangedProc-- = {
normalButtonName ← UserProfile.Token["CommanderPriority.NormalButtonName", "N"];
foregroundButtonName ← UserProfile.Token["CommanderPriority.ForegroundButtonName", "F"];
backgroundButtonName ← UserProfile.Token["CommanderPriority.BackgroundButtonName", "B"];
};
Background: Menus.MenuProc = {
[parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL]
h: Handle ← NARROW[clientData, Handle];
[] ← ResetPriority[h.mainLoopProcess, Process.priorityBackground ! Process.InvalidProcess => CONTINUE];
};
Foreground: Menus.MenuProc = {
[parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL]
h: Handle ← NARROW[clientData, Handle];
[] ← ResetPriority[h.mainLoopProcess, Process.priorityForeground ! Process.InvalidProcess => CONTINUE];
};
Normal: Menus.MenuProc = {
[parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL]
h: Handle ← NARROW[clientData, Handle];
[] ← ResetPriority[h.mainLoopProcess, Process.priorityNormal ! Process.InvalidProcess => CONTINUE];
};
ResetPriority:
PROC
[process: PROCESS, new: PrincOps.Priority] RETURNS [success: BOOL ← TRUE] = TRUSTED {
This routine sets the priority of the specified process.
This routine was stolen from CollectorWatchdogImpl.
old: PrincOps.Priority;
psb: PrincOps.PsbHandle;
psb ← PrincOpsUtils.PsbIndexToHandle[LOOPHOLE[process]];
PrincOpsUtils.DisableInterrupts[];
old ← PDA[psb].link.priority;
IF old # new
THEN {
self: PrincOps.PsbHandle = PrincOpsUtils.PsbIndexToHandle[
PDA[PrincOpsUtils.PsbIndexToHandle[PDA.ready.tail]].link.next];
npsb: PrincOps.PsbHandle ← PrincOpsUtils.PsbIndexToHandle[PDA[self].link.next];
IF
PDA[psb].link.vector
THEN {
We need to preserve the number of state vectors at various priorities. The easiest way to do this is to transfer a state vector from the new priority list to the old priority list, which allows the current state vector to remain with the process.
nsv: PrincOps.StateVectorHandle ← PDA.state[new];
IF nsv = PrincOps.NullStateVectorHandle
THEN
GO
TO fail;
If there is no available state vector at that priority, then we lose.
Remove the new state vector from its priority chain
PDA.state[new] ← LOOPHOLE[PDA[nsv].stk[0]];
Give the new state vector to the old priority chain.
PDA[nsv].stk[0] ← LOOPHOLE[PDA.state[old]];
PDA.state[old] ← nsv;
};
At this point we can alter the priority and assume success.
PDA[psb].link.priority ← new;
If the process that is getting its priority changed is on the ready queue we must remove it from the queue and put it back, thereby changing its position in the queue. If it was not on the ready queue, we hope that changing its priority did not upset someone who was depending on priorities being sorted within other kinds of queues. We will see what we will see!
DO
IF npsb = self THEN EXIT;
IF npsb = psb
THEN {
PrincOpsUtils.Requeue[@PDA.ready, @PDA.ready, psb];
EXIT;
};
npsb ← PrincOpsUtils.PsbIndexToHandle[PDA[npsb].link.next];
ENDLOOP;
EXITS fail => {success ← FALSE};
};
PrincOpsUtils.EnableInterrupts[];
};
Greet:
PROC [handle: Handle, cmd: Commander.Handle, paint:
BOOL] = {
v: ViewerClasses.Viewer ← handle.viewer;
Add:
PROC [me: Menus.MenuEntry, name:
ROPE] = {
old: Menus.MenuEntry = Menus.FindEntry[v.menu, name];
IF old =
NIL
THEN Menus.AppendMenuEntry[v.menu, me]
ELSE Menus.ReplaceMenuEntry[v.menu, old, me];
};
Add[Menus.CreateEntry[name: normalButtonName, proc: Normal, fork: TRUE, clientData: handle], normalButtonName];
Add[Menus.CreateEntry[name: foregroundButtonName, proc: Foreground, fork: TRUE, clientData: handle], foregroundButtonName];
Add[Menus.CreateEntry[name: backgroundButtonName, proc: Background, fork: TRUE, clientData: handle], backgroundButtonName];
IF paint THEN ViewerOps.PaintViewer[v, menu];
};
CommanderPriorityCmdProc: Commander.CommandProc ~ {
handle: ReadEvalPrint.Handle ← NARROW[
Commander.GetProperty[$ReadEvalPrintHandle, cmd.propertyList]];
Greet[handle, cmd, TRUE];
};
Loader.MakeProcedureResident[ResetPriority];
UserProfile.CallWhenProfileChanges[NoteProfile];
Commander.Register[key: "///Commands/CommanderPriority", proc: CommanderPriorityCmdProc, doc: "registers CommandTool menu buttons priority changes."];