(*-------------------------------------------------------------------------*)
(*                                                                         *)
(*  Amiga Oberon Library Module: Break                Date: 02-Nov-92      *)
(*                                                                         *)
(*   © 1992 by Fridtjof Siebert                                            *)
(*                                                                         *)
(*-------------------------------------------------------------------------*)

(* $IF BreakRq *)
MODULE BreakRq;
(* $ELSE *)
MODULE Break;
(* $END *)

(* $OvflChk- $RangeChk- $StackChk- $NilChk- $ReturnChk- $CaseChk- *)

IMPORT e  := Exec,
       d  := Dos,
       rq := Requests,
       ol := OberonLib,
(* $IF GarbageCollector *)
       gc := GarbageCollector,
(* $END *)
(* $IF BreakRq *)
       arg:= Arguments,
       str:= Strings,
(* $END *)
       s  := SYSTEM;

CONST
  CTRLC = LONGSET{d.ctrlC};

VAR
  ctrlCOff: INTEGER;    (* 0 = CtrtC enabled *)
  oldExceptCode: PROCEDURE();
  oldExceptData: LONGINT;
  oldSigs: LONGSET;

  Me : e.TaskPtr;


PROCEDURE CtrlCOff*;
BEGIN
  IF (ctrlCOff=0) THEN s.SETREG(0,e.SetExcept(LONGSET{},CTRLC)) END;
  INC(ctrlCOff)
END CtrlCOff;


PROCEDURE CtrlCOn *;
BEGIN
  DEC(ctrlCOff);
  IF (ctrlCOff=0) THEN s.SETREG(0,e.SetExcept(CTRLC    ,CTRLC)) END;
END CtrlCOn;


PROCEDURE ShowBreak;
VAR
  name: ARRAY 80 OF CHAR;
BEGIN
(* $IF BreakRq *)
  arg.GetArg(0,name);
  IF str.Length(name)<80 THEN str.AppendChar(name,":") END;
  IF rq.Request(name," *** User Break *** ","","Cancel") THEN END;
  HALT(20);
(* $ELSE *)
  rq.Fail(" *** User Break *** ");
(* $END *)
END ShowBreak;


(*------  Trap Handler:  ------*)


PROCEDURE TrapHandler();
BEGIN
  CtrlCOff;
  ol.Break := FALSE;
(* $IF GarbageCollector *)
  gc.mutator.locals := NIL;
(* $END *)
  s.SETREG(15,ol.OldSP);
  ShowBreak;
END TrapHandler;


PROCEDURE * TrapProc(); (* $EntryExitCode- *)

BEGIN
  ol.SetA5;
  s.SETREG(8,TrapHandler);
  s.INLINE(0201FH,             (*    MOVE.L  (A7)+,D0   *)
           00C40H,00003H,      (*    CMPI.W  #3,D0      *)
           06202H,             (*    BHI.S   l          *)
           0504FH,             (*    ADDQ.W  #8,A7      *)
           02F48H,00002H,      (* l: MOVE.L  A0,2(A7)   *)
           04E73H);            (*    RTE                *)
END TrapProc;



PROCEDURE * ExceptProc(d0{0}: LONGSET; a5{9}: LONGINT): LONGSET;

BEGIN
  s.SETREG(13,a5);
  IF (d.ctrlC IN d0) & ~ ol.closing THEN

    ol.Break := TRUE;
    Me.trapCode := TrapProc;

  END;
  RETURN d0;
END ExceptProc;


PROCEDURE CheckBreak *;

CONST TRAP8 = 04E48H;

BEGIN
  IF ol.Break THEN s.INLINE(TRAP8) END;
END CheckBreak;


BEGIN

  Me := e.FindTask(NIL);

  oldExceptCode := Me.exceptCode;
  oldExceptData := Me.exceptData;
  Me.exceptCode := s.VAL(e.PROC,ExceptProc);
  Me.exceptData := s.REG(13);

  oldSigs := e.SetExcept(LONGSET{12},LONGSET{12});
  ctrlCOff := 0;

CLOSE

  IF e.SetExcept(oldSigs,LONGSET{12})=LONGSET{} THEN END;
  Me.exceptCode := oldExceptCode;
  Me.exceptData := oldExceptData;

(* $IF BreakRq *)
END BreakRq.
(* $ELSE *)
END Break.
(* $END *)



