-- TalkerImpl.mesa
-- Paul Rovner, May 4, 1983 5:09 pm
-- Last Edited by: Greene, April 20, 1984 3:25:25 pm PST
-- Last Edited by: Nickell, June 15, 1984 12:33:13 pm PDT
-- Last Edited by: Rumph, June 15, 1984 3:29:29 pm PDT
DIRECTORY
Booting
USING [RegisterProcs, CheckpointProc, RollbackProc],
Commander
USING [Register, CommandProc],
Containers
USING [ChildXBound, ChildYBound],
DefaultRegistry
USING [MakeRegistryExplicit],
Labels
USING [Label, Create, Set],
Icons
USING [IconFlavor, NewIconFromFile],
MBQueue
USING [Queue, Create, CreateMenuEntry, QueueClientAction],
IO
USING [GetTokenRope, IDProc, PutRope,
STREAM, time, char, Put, EndOfStream,
RIS],
Menus
USING[CreateMenu, InsertMenuEntry, Menu, MenuProc],
Process
USING [Detach],
Rope
USING[
ROPE, Concat, Cat, Equal],
RPC
USING[MakeKey],
TalkerOps
USING[],
-- EXPORTS ONLY
TalkerOpsRpcControl
USING[InterfaceRecord, ImportNewInterface, ExportInterface,
UnexportInterface],
TalkerPrivate
USING[Handle, ConversationObject, Conversant, ConversantObject, Puller,
SendOutGoingLines, JoinConversation, ComputeStatus, RemakeStatusLabel,
PaintLine, KillConversation, IsViewer, BlinkOff, FindConversant,
JoinConversationHit, ShowStatusHit, LowerRope,
RemoveConversantFromOtherConversations],
TypeScript
USING [Create,
TS],
UserCredentials
USING [Get],
VFonts
USING [CharWidth, FontHeight],
ViewerClasses
USING [Viewer],
ViewerEvents
USING [EventProc, RegisterEventProc, ViewerEvent],
ViewerIO
USING [CreateViewerStreams],
ViewerOps
USING [CreateViewer],
File
USING [GetVolumeName, SystemVolume];
TalkerImpl:
CEDAR
MONITOR
-- protects "conversations" list
IMPORTS Booting, Commander, Containers, DefaultRegistry, Icons,
IO, Labels,
MBQueue, Menus, Process, Rope,
RPC, TalkerOpsRpcControl, TalkerPrivate, TypeScript,
UserCredentials, VFonts, ViewerEvents, ViewerIO, ViewerOps, File
EXPORTS TalkerOps, TalkerPrivate
=
BEGIN
OPEN Rope, TalkerPrivate;
-- VARIABLES
conversations:
LIST
OF Handle ←
NIL;
talkerIcon: Icons.IconFlavor = Icons.NewIconFromFile["Talker.icons", 0];
viewerEventQueue: MBQueue.Queue = MBQueue.Create[];
-- PROCEDURES
-- ******* interface procedures
-- registered with Commander
Talk: Commander.CommandProc = {
--PROC [cmd: Commander.Handle]
h: Handle ←
NIL;
cls:
IO.
STREAM =
IO.
RIS[cmd.commandLine];
DO
{conversantName:
ROPE ←
NIL;
conversantName ←
IO.GetTokenRope[cls,
IO.IDProc !
IO.EndOfStream =>
GOTO endOfStream;
ANY =>
CONTINUE].token;
IF conversantName #
NIL
THEN {conversantName ←
DefaultRegistry.MakeRegistryExplicit[conversantName,
LIST[$Talk, $Default]];
IF Rope.Equal[conversantName, GetLocalName[],
FALSE]
THEN
GOTO badConversant;
IF h =
NIL
THEN [h, ] ← FindConversation[conversantName
!
ANY =>
GOTO badConversant]
ELSE JoinConversation[h, conversantName
!
ANY =>
GOTO badConversant];
RemoveConversantFromOtherConversations[h, conversantName
!
ANY =>
GOTO badConversant];
EXITS badConversant => cmd.out.PutRope
[Cat[" ***Talker error: no such conversant: ",
conversantName,
"\n"] !
ANY =>
CONTINUE]};
EXITS endOfStream =>
EXIT}
ENDLOOP;
IF h #
NIL
THEN RemakeStatusLabel[h];
};
-- end
Talk
-- RPC magic. These are the only procs called by remote clients.
PutMyLine:
PUBLIC
PROC[myName:
ROPE, line:
ROPE] = {
h: Handle ←
NIL;
rePaintStatus:
BOOL ←
FALSE;
[h, rePaintStatus] ← FindConversation[myName !
ANY =>
CONTINUE];
IF h =
NIL
THEN
RETURN;
PaintLine[h, Cat[myName, ": ", line]];
IF rePaintStatus
THEN RemakeStatusLabel[h];
};
-- end PutMyLine
JoinWith:
PUBLIC
PROC[myName:
ROPE, newConversant:
ROPE] = {
h: Handle ←
NIL;
rePaintStatus:
BOOL ←
FALSE;
IF Equal[newConversant, myName,
FALSE]
THEN
RETURN;
[h, rePaintStatus] ← FindConversation[myName !
ANY =>
CONTINUE];
IF h =
NIL
THEN
RETURN;
JoinConversation[h, newConversant];
RemakeStatusLabel[h];
RemoveConversantFromOtherConversations[h, newConversant];
RemoveConversantFromOtherConversations[h, myName];
};
-- end
JoinWith
DealMeOut:
PUBLIC
PROC[myName:
ROPE] = {
RemoveConversantFromOtherConversations[
NIL, myName];
};
-- end
DealMeOut
-- ******* menu and event procedures
DisconnectHit: Menus.MenuProc = {
-- [parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL]
h: Handle ←
NARROW[clientData, Handle];
KillConversation[h];
RemakeStatusLabel[h];
};
-- end DisconnectHit
VEBundle: TYPE = RECORD[viewer: ViewerClasses.Viewer, event: ViewerEvents.ViewerEvent];
ViewerEvent: ViewerEvents.EventProc = {
PROC [viewer: ViewerClasses.Viewer, event: ViewerEvents.ViewerEvent];
MBQueue.QueueClientAction
[viewerEventQueue,
DoViewerEvent,
NEW[VEBundle ← [viewer, event]]];
};