;-----------------------------------------------------------PowerPPL v3.Oá---
; File           : GCHAT.PPS
; Original by    : LONE RUNNER on 05/29/1996 at 13:16:07
; Last update by : LONE RUNNER on 10/27/1996 at  2:52:19
;----------------------------------------------------------------------------
;
;
;  This is a part of the Project Frontier's Source code.
;
;  Copyright (C) 1997-98 Francis Gastellu
;                    aka Lone Runner/Aegis
;
;  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
;
; Global chat - multinode realtime chatter

'$USEFUNCS
;----------------------------------------------------------------------------
#user

String MyBuffer
String Buffer(9), K
Int A, B
Int localLine(9)
Int localCol(9)
Int topLine(9)
Int OldLevel(9)
String OldName(9)
Int OldMinutes(9)
Int nLines
Int nUsers
String separatorBar
String logo(29)
Int logoLevels(29)
String unknownLevelLogo
Int nLogos
int commandLine
String curLine(9)
Int thisWindow
UByte pass(9)
Int lastOff(9)
String exportBuffer
Dword exportTick, checkTick, infUpdateTick
String DataFile(9)
String InfoFile(9)
Ubyte p, w
Int windowUsed(9)
Int checkDelay
Int infUpdateDelay
Dword line0tick
Int c_x, c_y, c_c
DWord line0Delay
Time OldFileTime(9)

Declare Function takeKey() String
Declare procedure readConfig()
Declare Procedure drawScreen()
Declare Procedure updateWindow(Int wNum)
Declare Function getBuffer(Int wNum) String
Declare Procedure addBuffer(Int wNum, String Str)
Declare Procedure insertBuffer(Int wNum, String Str)
Declare Procedure wnNewLine(Int wNum)
Declare Procedure checkInput(Int wNum)
Declare Procedure export(String k)
Declare Procedure initChat()
Declare Procedure unInitChat()
Declare Procedure checkNewUsers()
Declare Procedure checkLine0()
Declare Procedure writeLine0(String Str)
Declare Procedure RestStat()
Declare Procedure SaveStat()
Declare Function Tick() DWord
Declare Procedure UpdateInfos(Int wNum)
Declare Procedure InfUpdate()

;----------------------------------------------------------------------------

Begin

StartDisp FNS
GetUser
nUsers = 3
infUpdateDelay = 180
readConfig()
drawScreen()
initChat()

writeLine0("@X08.@X04o@X0CO@X0F[ Welcome in the AEGiS MultiChat v2.Oá ]@X0CO@X04o@X08.")
While (K != Chr(27)) Do
	K = takeKey()
	If (k != "") Then
		addBuffer(thisWindow, k)
		updateWindow(thisWindow)
	Endif
	export(k)
	If (Tick() > checkTick + checkDelay) Then
		For A = 0 To nUsers-1
			If (A != thisWindow && windowUsed(A) = 1) Then
				checkInput(A)
				updateWindow(A)
			Endif
		Next
	checkNewUsers()
	checkTick = Tick()
	checkLine0()
	Endif
	If (Tick() > infUpdateTick + infUpdateDelay) Then
	InfUpdate()
	infUpdateTick = Tick()
	Endif
Endwhile
UninitChat()

End

;----------------------------------------------------------------------------
Function takeKey() String

If (MyBuffer = "") Then
	takeKey = inkey()
Else
	takeKey = Left(MyBuffer, 1)
	MyBuffer = Mid(MyBuffer, 2, Len(MyBuffer) - 1)
Endif

Endfunc

;----------------------------------------------------------------------------
Procedure drawScreen()

;AnsiPos 1, 2
;Print separatorBar
;localLine(0) = 1
;localCol(0) = 1
;topLine(0) = 3
Cls
Select Case nUsers
	Case 3
		nLines = 6
	Case 4
		nLines = 5
	Case 5
		nLines = 4
	Case 6
		nLines = 3
	Case 7,8,9,10
		nLines = 2
End Select
For A = 0 to nUsers
	topLine(A) = A*nLines+3
	localCol(A) = 1
	localLine(A) = 1
	AnsiPos 1, topLine(A)-1
	Print separatorBar
Next
commandLine = topLine(A-1)+nLines

Endproc

;----------------------------------------------------------------------------
Procedure readConfig()

String Temp
Int Cnt
Ubyte p, w

Fopen 1, PPEPath() + "GCHAT.CFG", O_RD, S_DN
Fget 1, separatorBar
Fget 1, checkDelay 
Fget 1, line0Delay 
Fget 1, unknownLevelLogo
Eval Ferr(1)
Fget 1, Temp
Cnt = 0
While (!Ferr(1)) Do
	logoLevels(Cnt) = S2i(Temp, 10)
	Fget 1, logo(Cnt)
	Inc Cnt
	Fget 1, Temp
Endwhile
Fclose 1
nLogos = Cnt-1

For Cnt = 0 To 9
	DataFile(Cnt) = PPEPath() + "WINDOW" + String(Cnt) + ".DAT"
	InfoFile(Cnt) = PPEPath() + "WINDOW" + String(Cnt) + ".INF"
Next
Endproc

;----------------------------------------------------------------------------
Procedure updateWindow(Int wNum)

Int A
String k

While (True) Do
	k = getBuffer(wNum)
	If (k = "") Break
	
;	export(k)
	
	Select Case k
		Case ""
			If (curLine(wNum) != "") Then
				Dec localCol(wNum)
				AnsiPos localCol(wNum), topLine(wNum)+localLine(wNum)-1
				Print " "
				AnsiPos localCol(wNum), topLine(wNum)+localLine(wNum)-1
				curLine(wNum) = Left(curLine(wNum), Len(curLine(wNum))-1)
			Endif

		Case Chr(13)
			wnNewLine(wNum)
			AnsiPos localCol(wNum), topLine(wNum)+localLine(wNum)-1
			
		Case Else
	
			If (localCol(wNum) = 78) Then
				For A = 77 to 1 Step -1
					If (Mid(curLine(wNum), A, 1) == " ") Break
				Next
				If (A != 0) Then
					AnsiPos A, topLine(wNum)+localLine(wNum)-1
					ClrEol
					InsertBuffer(wNum, Right(curLine(wNum), 78 - A - 1))
				Endif
				wnNewLine(wNum)
				addBuffer(wNum, k)
				Continue
			Endif

			AnsiPos localCol(wNum), topLine(wNum)+localLine(wNum)-1
			Print K
			localCol(wNum) = localCol(wNum) + 1
			curLine(wNum) = curLine(wNum) + K
			
	End Select
	
EndWhile

Endproc

;----------------------------------------------------------------------------
Procedure insertBuffer(Int wNum, String Str)

Buffer(wNum) = Str + Buffer(wNum)

Endproc

;----------------------------------------------------------------------------
Procedure addBuffer(Int wNum, String Str)

Buffer(wNum) = Buffer(wNum) + Str

Endproc

;----------------------------------------------------------------------------
Function getBuffer(Int wNum) String

If (Buffer(wNum) == "") Then
	getBuffer = ""
Else
	getBuffer = Left(Buffer(wNum), 1)
	Buffer(wNum) = Mid(Buffer(wNum), 2, Len(Buffer(wNum)) - 1)
Endif

Endfunc

;----------------------------------------------------------------------------
Procedure wnNewLine(Int wNum)

Int A

Inc localLine(wNum)
localCol(wNum) = 1
If (localLine(wNum)+1 > nLines) Then
	localLine(wNum) = 1
	For A = 1 To nLines-1
		AnsiPos 1, topLine(wNum)+A-1
		ClrEol
	Next
Endif
curLine(wNum) = ""
Endproc

;----------------------------------------------------------------------------
Procedure checkInput(Int wNum)

Ubyte p, w

	If (!Exist(DataFile(wNum))) Then
		writeLine0(OldName(wNum) + " has quit gCHAT")
		windowUsed(wNum) = 0
		AnsiPos 1, topLine(wNum)-1
		Print separatorBar
	Else
    	Fopen 1, DataFile(wNum), O_RD, S_DN
    	Fseek 1, lastOff(wNum), SEEK_SET
    	While (True) Do
    		Fread 1, p, 1
    		If (p != Pass(wNum)) Break
    		Fread 1, w, 1
    		addBuffer(wNum, Chr(w))
    		lastOff(wNum) = lastOff(wNum) + 2
    		If (lastOff(wNum) > 2048) Then
    			If (pass(wNum) == 0) Then
    				pass(wNum) = 1
    			Else
    				pass(wNum) = 0
    			Endif
    			lastOff(wNum) = 0
    			Fseek 1, 0, SEEK_SET
    		Endif
    	Endwhile
    	Fclose 1
    Endif
Endproc

;----------------------------------------------------------------------------
Procedure export(String k)

Int A
UByte w

exportBuffer = exportBuffer + k
If (Tick() > exportTick + checkdelay) Then
	Fopen 1, DataFile(thisWindow), O_RW, S_DN
	Fseek 1, lastOff(thisWindow), SEEK_SET
	For A = 1 To Len(exportBuffer)
		Fwrite 1, Pass(thisWindow), 1
		w = Asc(Mid(exportBuffer, A, 1))
		Fwrite 1, w, 1
		lastOff(thisWindow) = lastOff(thisWindow) + 2
		If (lastOff(thisWindow) > 2048) Then
			If (pass(thisWindow) == 0) Then
				pass(thisWindow) = 1
			Else
				pass(thisWindow) = 0
			Endif
			lastOff(thisWindow) = 0
			Fseek 1, 0, SEEK_SET
		Endif
	Next
	Fclose 1
	exportBuffer = ""
	exportTick = Tick()
Endif

Endproc

;----------------------------------------------------------------------------
Procedure initChat()

Int Cnt

thisWindow = -1

For Cnt = 0 To nUsers
	If (Exist(DataFile(Cnt))) Then
		windowUsed(Cnt) = 1
	Else
		If (thisWindow == -1) thisWindow = Cnt
	Endif
	If (windowUsed(Cnt)) UpdateInfos(Cnt)
Next	

InfUpdate()

Fcreate 1, DataFile(thisWindow), O_WR, S_DN
For Cnt = 1 To 64
	Fwrite 1, "XXXXXXXXXXXXXXXX", 32
Next
Fclose 1

AnsiPos localCol(thisWindow), topLine(thisWindow)+localLine(thisWindow)-1

Endproc

;----------------------------------------------------------------------------
Procedure checkNewUsers()

Int Cnt

For Cnt = 0 To nUsers
	If (Exist(DataFile(Cnt))) Then
		If (windowUsed(Cnt) == 0) Then
			windowUsed(Cnt) = 1
			updateInfos(Cnt)
		Else
			If (FileInf(InfoFile(Cnt), 3) != OldFileTime(Cnt)) updateInfos(Cnt)
		Endif
	Endif
Next	

Endproc

;----------------------------------------------------------------------------
Procedure unInitChat()
Delete DataFile(thisWindow)
Delete InfoFile(thisWindow)
Endproc

;----------------------------------------------------------------------------
Procedure checkLine0()

If (line0Tick != 0 && Tick() > line0Tick + line0delay) Then
	SaveStat()
	AnsiPos 1, 1
	Print "@X0F"+Space(80)
	line0Tick = 0
	RestStat()
Endif

Endproc

;----------------------------------------------------------------------------
Procedure writeLine0(String Str)

Str = Space(40 - Len(StripAtx(Str)) / 2) + Str
SaveStat()
AnsiPos 1, 1
Print "@X0F" + Str
RestStat()
line0Tick = Tick()

Endproc

;----------------------------------------------------------------------------
Function Tick() DWord
Tick = PeekDW(MKADDR(0040h,006Ch))
Endfunc

;----------------------------------------------------------------------------
Procedure SaveStat()
c_x = Getx()
c_y = Gety()
c_c = CurColor()
Endproc

;----------------------------------------------------------------------------
Procedure RestStat()
AnsiPos c_x, c_y
Color c_c
Endproc

;----------------------------------------------------------------------------
Procedure UpdateInfos(Int wNum)
String Name
Int Level
Int Minutes
Int A

SaveStat()

Fopen 1, InfoFile(wNum), O_RD, S_DN
FGet 1, Name
FGet 1, Level
FGet 1, Minutes
FClose 1

If (Name != OldName(wNum) || Level != OldLevel(wNum) || Minutes != OldMinutes(wNum)) Then
	AnsiPos 1, topLine(wNum)-1
	Print separatorBar
	AnsiPos 5, topLine(wNum)-1
	For A = 0 To 29
		If (LogoLevels(A) == Level) Then
			Print Logo(A)
			Break
		Endif
	Next
	If (A == 30) Print unknownLevelLogo
	Print " ", Name
	AnsiPos 73, topLine(wNum)-1
	Print "@X0F", Minutes
	OldName(wNum) = Name
	OldMinutes(wNum) = Minutes
	OldLevel(wNum) = Level
	OldFileTime(wNum) = FileInf(InfoFile(wNum), 3)
Endif		

RestStat()
Endproc

;----------------------------------------------------------------------------
Procedure InfUpdate()
Fcreate 1, InfoFile(thisWindow), O_WR, S_DN
FPutLn 1, U_Name()
FPutLn 1, U_SEC
FPutLn 1, ToInteger(PCBMAC("@TIMELEFT@"))
Fclose 1
EndProc

;----------------------------------------------------------------------------
