      PROGRAM TWIMP4
C        a trivial Fortran wimp program which 
C        calculates a spriral and displays it in a window
C        while multitasking
C        needs the Wimp, Utilities and Graphics libraries
C
      COMMON /RUNNUL/ MASK
C        initialise the wimp
      CALL WPINIT('TWIMP4')
C        set up the desk-top
      CALL SETUP
C        go into the wimp loop (without null calls to begin with)
      MASK = 1
      CALL WPLOOP(MASK)
C        that's all we can do here
      END
C
      SUBROUTINE SETUP
C        here we make a menu and put an icon on the icon bar
C        keep its handle in common
      COMMON /HANDLE/ ICBAR,IWH,IWTIME
C        file name
      CHARACTER*4 DUM
C        menus have 7 + 6*(number of entries) words
      COMMON /MENUS/ MENU(43)
C        load window from template file
      CALL WPOPNT('TWtemplate')
C        borrow the MENU space for work space (no indirection)
      CALL WPLDTW('tw4_main',MENU,DUM,IWH)
      CALL WPLDTW('tw4_time',MENU,DUM,IWTIME)
      CALL WPCLST
C        make up menu
      CALL WPMKMB('TestWimp4,start,continue,stop,slow,fast,quit',MENU)
C        make 'continue' and 'stop' item grey
      CALL WPSTMF(2,MENU,1,.TRUE.)
      CALL WPSTMF(2,MENU,2,.TRUE.)
C        set up for slow processing
      CALL WPSTMF(0,MENU,3,.TRUE.)
C        do 1 calculation every 0.1 seconds
      CALL WPNULT(10)
C        get sprites into Wimp sprite area
      CALL OSCLI('IconSprites TWSprites')
C        put icon on icon bar
      CALL WPBARI('tw4_sprite',-1,MENU,ICBAR)
      RETURN
      END
C
      SUBROUTINE WQMENU(IMB,ITEMS,NM)
C           receives click over menu item
      COMMON /MENUS/ MENU(31)
      DIMENSION ITEMS(NM)
      LOGICAL SET
C           'start'
      IF(ITEMS(1).EQ.0) CALL START
C           'continue'
      IF(ITEMS(1).EQ.1) CALL CONTNU
C           'stop'
      IF(ITEMS(1).EQ.2) CALL HALT
C           'slow'
      IF(ITEMS(1).EQ.3) THEN
        CALL WPNULT(10)
C           set the tick marks in the menu
        CALL WPSTMF(0,MENU,3,.TRUE.)
        CALL WPSTMF(0,MENU,4,.FALSE.)
      ENDIF
C           'fast' is opposite to slow
      IF(ITEMS(1).EQ.4) THEN
        CALL WPNULT(0)
C           set the tick marks in the menu
        CALL WPSTMF(0,MENU,4,.TRUE.)
        CALL WPSTMF(0,MENU,3,.FALSE.)
      ENDIF
C           'quit' kills task
      IF(ITEMS(1).EQ.5) CALL WPQUIT
      RETURN
      END
C
      SUBROUTINE START
C           start the calculations and display
      PARAMETER (MAXPT=2000)
      COMMON /POINTS/ NPT,R,PHI,IX(MAXPT),IY(MAXPT)
      COMMON /RUNNUL/ MASK
      COMMON /MENUS/ MENU(31)
      COMMON /HANDLE/ ICBAR,IWH,IWTIME
      COMMON /TIMES/ REALT,CPUT
C
C            set up the first point
      R = 20.
      PHI = 0.
      IX(1) = 20 + 512
      IY(1) = 0 - 512
      NPT = 1
C            allow WQNULL to be called
      MASK = 0
C            set the menu
      CALL WPSTMF(2,MENU,0,.TRUE.)
      CALL WPSTMF(2,MENU,2,.FALSE.)
C            open the windows
      CALL WPOPNW(IWH)
      CALL WPOPNW(IWTIME)
C            get the time
      CALL WPTIME(REALT,CPUT)
      RETURN
      END
C
      SUBROUTINE WQPLOT(IWHAN)
C            draw the one and only window
      PARAMETER (MAXPT=2000)
      COMMON /POINTS/ NPT,R,PHI,IX(MAXPT),IY(MAXPT)
      COMMON /HANDLE/ ICBAR,IWH,IWTIME
      COMMON /TIMES/ REALT,CPUT
      IF(IWHAN.EQ.IWH) THEN
        IF(NPT.GT.1) THEN
C            green colour
          CALL WPSETC(0,11)
C            draw line
          CALL GRPOLY(NPT,IX,IY,.FALSE.)
        ENDIF
      ELSE
C           show the time in white
        CALL WPSETC(0,0)
        CALL GRMOVE(0,-8)
        PRINT 101,'Real Time',REALT
        CALL GRMOVE(0,-48)
        PRINT 101,' CPU Time',CPUT
 101    FORMAT(1X,A9,F7.2,' Secs.')
      ENDIF
      RETURN
      END
C
      SUBROUTINE WQNULL
C           calculate a new point
C           and request it be plotted
      PARAMETER (MAXPT=2000)
      COMMON /POINTS/ NPT,R,PHI,IX(MAXPT),IY(MAXPT)
      COMMON /RUNNUL/ MASK
      COMMON /HANDLE/ ICBAR,IWH,IWTIME
      COMMON /MENUS/ MENU(43)
      COMMON /TIMES/ REALT,CPUT
      PARAMETER (PI2=6.2831852, ALPHA=1.5, SAGIT=0.5)
C           check if finished
      IF(NPT.GE.MAXPT) THEN
        MASK = 1
C            grey out 'stop'
        CALL WPSTMF(2,MENU,2,.TRUE.)
        RETURN
      ENDIF
C           get d(phi)
      DPHI = SQRT(8.*SAGIT/R)
C           get d(R)
      DR = DPHI * ALPHA
C           get new radius
      R = R + DR
C           get new angle
      PHI = PHI + DPHI
      IF(PHI.GT.PI2) PHI = PHI - PI2
C           enter new point
      NPT = NPT + 1
      IX(NPT) = NINT(R*COS(PHI)) + 512
      IY(NPT) = NINT(R*SIN(PHI)) - 512
C           request screen update
      CALL WPUPDT(IWH,-1)
C           update the time
      CALL WPTIME(REALT,CPUT)
      CALL WPUPDT(IWTIME,-1)
      RETURN
      END
C
      SUBROUTINE WQUPDT(IWHAN)
C           just have to draw the last line, and show the time
      PARAMETER (MAXPT=2000)
      COMMON /POINTS/ NPT,R,PHI,IX(MAXPT),IY(MAXPT)
      COMMON /HANDLE/ ICBAR,IWH,IWTIME
      COMMON /TIMES/ REALT,CPUT
      IF(IWHAN.EQ.IWH) THEN
C           plot line in red
        CALL WPSETC(0,11)
        CALL GRLINE(IX(NPT-1),IY(NPT-1),IX(NPT),IY(NPT))
      ELSE
C           clear area
        CALL WPSETC(0,7)
        CALL GRRECT(160,0,272,-80)
C           show the time in white
        CALL WPSETC(0,0)
        CALL GRMOVE(160,-8)
        PRINT 101,REALT
        CALL GRMOVE(160,-48)
        PRINT 101,CPUT
 101    FORMAT(F7.2)
      ENDIF
      RETURN
      END
C
      SUBROUTINE HALT
C            stop the drawing
      COMMON /RUNNUL/ MASK
      COMMON /MENUS/ MENU(43)
C            stop call to WQNULL
      MASK = 1
C            allow 'continue'
      CALL WPSTMF(2,MENU,1,.FALSE.)
C            grey out 'stop'
      CALL WPSTMF(2,MENU,2,.TRUE.)
      RETURN
      END
C
      SUBROUTINE CONTNU
C            continue the drawing
      COMMON /RUNNUL/ MASK
      COMMON /MENUS/ MENU(43)
      COMMON /HANDLE/ ICBAR,IWH,IWTIME
C            start call to WQNULL
      MASK = 0
C            allow 'stop'
      CALL WPSTMF(2,MENU,2,.FALSE.)
C            grey out 'continue'
      CALL WPSTMF(2,MENU,1,.TRUE.)
C            open window (in case user has closed it)
      CALL WPOPNW(IWH)
      CALL WPOPNW(IWTIME)
      RETURN
      END
C
      SUBROUTINE WQCLSW(DUM)
      COMMON /HANDLE/ ICBAR,IWH,IWTIME
C           user has asked to close a window, so also stop calculations
      CALL HALT
C           close both  windows
      CALL WPCLSW(IWH)
      CALL WPCLSW(IWTIME)
      RETURN
      END
