/*
    LocaleTime version 1.0
    Copyright (C) 1996 Piotr Pawlow (PP/UNION)

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

MODULE 'locale','libraries/locale','dos/notify','exec/ports','exec/nodes',
       'amigalib/ports','devices/timer','exec/io','resources/battclock',
       'detatch','dos/dos'

DEF myport=0:PTR TO mp
DEF ioreq=0:PTR TO timerequest
DEF clockresbase

PROC main() HANDLE
DEF notr:notifyrequest,port:PTR TO mp,msg:PTR TO mn
DEF oldtimecorrection,settingsfile,handle

  detatch('LocaleTime')

  settingsfile:='S:LocaleTime.settings'

  Forbid()
    port:=FindPort('localetime_port')
  Permit()
  IF port THEN Raise("INST")
  IF (myport:=CreateMsgPort())=0 THEN Raise("PORT")
  myport.ln.name:='localetime_port'
  AddPort(myport)
  notr.port:=myport
  notr.flags:=NRF_SEND_MESSAGE
  notr.name:='ENV:sys/locale.prefs'
  IF (StartNotify(notr)=0) THEN Raise("NOTF")
  readoffset()
  IF (handle:=Open(settingsfile,OLDFILE))
    Read(handle,{timecorrection},4)
    Close(handle)
  ENDIF
  oldtimecorrection:=Long({timecorrection})
  IF (clockresbase:=OpenResource('battclock.resource'))=0 THEN Raise("RESR")
  PutLong({oldreadclock},SetFunction(clockresbase,-12,{newreadclock}))
  PutLong({oldwriteclock},SetFunction(clockresbase,-18,{newwriteclock}))
  opentimer()
  settime(readclock())
  LOOP
    IF msg:=GetMsg(myport)
      addtime(readoffset())
      ReplyMsg(msg)
    ENDIF
    IF CtrlC() THEN Raise("CTRC")
    IF (Long({timecorrection})<>oldtimecorrection)
      oldtimecorrection:=Long({timecorrection})
      IF oldtimecorrection=0
        DeleteFile(settingsfile)
      ELSE
        IF (handle:=Open(settingsfile,NEWFILE))
          Write(handle,{timecorrection},4)
          Close(handle)
        ELSE
          information('Couldn''t write settings')
        ENDIF
      ENDIF
    ENDIF
    Delay(50)
  ENDLOOP

EXCEPT DO
  closetimer()
  IF Long({oldreadclock})
    SetFunction(clockresbase,-12,Long({oldreadclock}))
    SetFunction(clockresbase,-18,Long({oldwriteclock}))
    EndNotify(notr)
  ENDIF
  IF myport
    RemPort(myport)
    DeleteMsgPort(myport)
  ENDIF
  SELECT exception
    CASE "LOCL"; information('Couldn''t open locale.library\n')
    CASE "RESR"; information('Couldn''t open battclock.resource\n')
    CASE "PORT"; information('Couldn''t create message port\n')
    CASE "OLOC"; information('Couldn''t open locale\n')
    CASE "NOTF"; information('Couldn''t start notification on ENV:sys/locale.prefs\n')
    CASE "INST"
      IF information('LocaleTime is already installed.\nDo you want to remove it ?','Yes|No','LocaleTime request')=1
        Forbid()
          port:=FindPort('localetime_port')
        Permit()
        IF port THEN Signal(port.sigtask,SIGBREAKF_CTRL_C)
      ENDIF
    CASE "TIMR"; WriteF('Couldn''t open timer.device\n')
  ENDSELECT
ENDPROC 0

PROC information(text,gads=0,winname=0)
  IF gads=0 THEN gads:='OK'
  IF winname=0 THEN winname:='LocaleTime information:'
ENDPROC EasyRequestArgs(NIL,[20,0,winname,text,gads],0,0)

PROC readoffset()
DEF loc:PTR TO locale,oldoffset
  IF (localebase:=OpenLibrary('locale.library',0))=0 THEN Raise("LOCL")
  IF (loc:=OpenLocale(NIL))=0 THEN Raise("OLOC")
  oldoffset:=Long({timeoffset})
  PutLong({timeoffset},-loc.gmtoffset*60)
  CloseLocale(loc)
  CloseLibrary(localebase)
ENDPROC Long({timeoffset})-oldoffset

PROC opentimer()
  IF (ioreq:=CreateIORequest(myport,SIZEOF timerequest))=0 THEN Raise("IORQ")
  IF OpenDevice('timer.device',0,ioreq,0) THEN Raise("TIMR")
ENDPROC

PROC closetimer()
  IF ioreq
    CloseDevice(ioreq)
    DeleteIORequest(ioreq)
  ENDIF
ENDPROC

PROC settime(s,m=0)
  ioreq.io.command:=TR_SETSYSTIME
  ioreq.io.flags:=0
  ioreq.time.secs:=s
  ioreq.time.micro:=m
  DoIO(ioreq)
ENDPROC

PROC gettime()
DEF s,m
  ioreq.io.command:=TR_GETSYSTIME
  ioreq.io.flags:=0
  DoIO(ioreq)
  s:=ioreq.time.secs
  m:=ioreq.time.micro
ENDPROC s,m

PROC addtime(offset)
DEF s,m
  s,m:=gettime()
  settime(s+offset,m)
ENDPROC

PROC readclock()
    MOVE.L  clockresbase,A6
    JSR     -12(A6)
ENDPROC D0

newreadclock:
    MOVE.L  A3,-(A7)
    MOVE.L  oldreadclock(PC),A3
    JSR     (A3)
    MOVE.L  (A7)+,A3
    ADD.L   timeoffset(PC),D0
    ADD.L   timecorrection(PC),D0
    RTS

newwriteclock:
    SUB.L   timeoffset(PC),D0
    MOVEM.L D0/D1/A3,-(A7)
    MOVE.L  D0,-(A7)
    MOVE.L  oldwriteclock(PC),A3
    JSR     (A3)
    MOVE.L  oldreadclock(PC),A3
    JSR     (A3)
    MOVE.L  (A7)+,D1
    SUB.L   D0,D1
    LEA     timecorrection(PC),A3
    MOVE.L  D1,(A3)
    MOVEM.L (A7)+,D0/D1/A3
    RTS

oldreadclock:   LONG 0
oldwriteclock:  LONG 0
timeoffset:     LONG 0
timecorrection: LONG 0

CHAR '$VER: LocaleTime 1.0 (19-12-1996) by PP/UNION.',0
