// This program is used to break a running program
//
// Any program that is acting on the break signals
// CTRL-C (bit 12), CTRL-D (bit 13), CTRL-E (bit 14)
// or CTRL-F (bit 15) can be breaked.
//
// A running Comal program acts on CTRL-C.

USE System
USE ExecLists
USE ExecLibrary
USE CITScreen
USE CITWindow
USE CITGadgets

DIM TaskList OF List
DIM Task OF ULONG
DIM TaskName$ OF 40
DIM BreakSigMask OF ULONG
DIM Error OF SHORT
DIM Stop OF SHORT

ReadTasks(TaskList)

DIM BreakWindow OF CITWindow
BreakWindow.Position(20,20)
BreakWindow.Size(600,170)
BreakWindow.Activate
ComalScreen.InsObject(BreakWindow,Error)
IF Error THEN
  STOP "Could'nt open the window"
ENDIF

// Make a string input gadget for our ListView gadget below
// NOTE: do not create explicitely. ListView will do it for you
DIM StringGad OF StringGadget
StringGad.Size(300,14)

// Now, make the ListView
DIM ListView OF ListViewGadget
ListView.Position(10,15)
ListView.Size(300,100)
ListView.Label("Select task to break",ABOVE+HIGHLIGHT)
ListView.ChoiceList(TaskList)
ListView.ShowSelected(StringGad)
ListView.Selected(0)
BreakWindow.InsObject(ListView,Error)

DIM Text OF TextGadget
Text.Position(400,2)
Text.Label("Break Signals",INSIDE+HIGHLIGHT)
BreakWindow.InsObject(Text,Error)

DIM CtrlC_Gad OF CheckboxGadget
CtrlC_Gad.Label("Control-C",LEFT)
CtrlC_Gad.Size(30,14)
CtrlC_Gad.Position(470,20)
CtrlC_Gad.On
BreakWindow.InsObject(CtrlC_Gad,Error)

DIM CtrlD_Gad OF CheckboxGadget
CtrlD_Gad.Label("Control-D",LEFT)
CtrlD_Gad.Size(30,14)
CtrlD_Gad.Position(470,40)
BreakWindow.InsObject(CtrlD_Gad,Error)

DIM CtrlE_Gad OF CheckboxGadget
CtrlE_Gad.Label("Control-E",LEFT)
CtrlE_Gad.Size(30,14)
CtrlE_Gad.Position(470,60)
BreakWindow.InsObject(CtrlE_Gad,Error)

DIM CtrlF_Gad OF CheckboxGadget
CtrlF_Gad.Label("Control-F",LEFT)
CtrlF_Gad.Size(30,14)
CtrlF_Gad.Position(470,80)
BreakWindow.InsObject(CtrlF_Gad,Error)

DIM BreakPrgGad OF ButtonGadget
BreakPrgGad.Size(120,16)
BreakPrgGad.Position(10,-(16+5))
BreakPrgGad.Label("Break Program",INSIDE)
BreakWindow.InsObject(BreakPrgGad,Error)

DIM CancelGad OF ButtonGadget
CancelGad.Size(120,16)
CancelGad.Position(-(120+10),-(16+5))
CancelGad.Label("Cancel",INSIDE)
BreakWindow.InsObject(CancelGad,Error)

IF Error THEN
  PRINT "Could'nt create one or more of the gadgets"
ELSE
  REPEAT
    IF BreakPrgGad.Pressed THEN
      IF CtrlC_Gad.Value THEN BreakSigMask:=BreakSigMask BITOR %0001000000000000
      IF CtrlD_Gad.Value THEN BreakSigMask:=BreakSigMask BITOR %0010000000000000
      IF CtrlE_Gad.Value THEN BreakSigMask:=BreakSigMask BITOR %0100000000000000
      IF CtrlF_Gad.Value THEN BreakSigMask:=BreakSigMask BITOR %1000000000000000
      Forbid
      TaskName$:=StringGad.Value$
      Task:=FindTask(ADR(TaskName$))
      IF Task THEN
        Signal(Task,BreakSigMask)
      ENDIF
      Permit
      Stop:=TRUE
    ELIF CancelGad.Pressed THEN
      Stop:=TRUE
    ENDIF
  UNTIL Stop
ENDIF

ComalScreen.RemObject(BreakWindow)

// Make an Exec list with all task names (except this task)
PROC ReadTasks(REF List OF List)
  LOCAL ExecBase OF POINTER TO ULONG
  LOCAL TaskReady OF POINTER TO List
  LOCAL TaskWait OF POINTER TO List
  LOCAL tn OF POINTER TO Node
  LOCAL n OF POINTER TO TaskNode

  ExecBase:=$0004
  TaskReady:=ExecBase@+406
  TaskWait:=ExecBase@+420

  Forbid
  tn:=TaskReady@.lh_Head
  WHILE tn@.ln_Succ DO
    ALLOCATE(n)
    n@.Name$:=CharArrayToString$(tn@.ln_Name)
    AddTail(ADR(List),n)
    tn:=tn@.ln_Succ
  ENDWHILE
  tn:=TaskWait@.lh_Head
  WHILE tn@.ln_Succ DO
    ALLOCATE(n)
    n@.Name$:=CharArrayToString$(tn@.ln_Name)
    AddTail(ADR(List),n)
    tn:=tn@.ln_Succ
  ENDWHILE
  Permit
ENDPROC ReadTasks

STRUC TaskNode
  INHERIT Node

  DIM Name$ OF 40

  FUNC Init CONSTRUCTOR
    ln_Name:=ADR(Name$)
    RETURN TRUE
  ENDFUNC Init

ENDSTRUC TaskNode
