XlErrorHandlingWithFeedback.mesa
Copyright Ó 1991, 1992 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, November 6, 1991 10:11:20 am PST
Christian Jacobi, February 2, 1993 11:35 am PST
Willie-s, November 25, 1991 4:48 pm PST
Non essential impl module for Xl.
Registers error handlers making X errors legible.
DIRECTORY
BasicTime, IO, Rope, SimpleFeedback, Xl, XlPrivateErrorHandling, XlPrivate;
XlErrorHandlingWithFeedback: CEDAR MONITOR
IMPORTS BasicTime, IO, Rope, SimpleFeedback, XlPrivate, XlPrivateErrorHandling
SHARES Xl ~
BEGIN
Explain: PROC [errorEvent: Xl.ErrorNotifyEvent] = {
Ap0: PROC [r: Rope.ROPE] = {
ev.explanation ¬ Rope.Cat[ev.explanation, r, " "];
};
Ap: PROC [format: Rope.ROPE, v1: IO.Value ¬ [null[]]] = {
Ap0[IO.PutFR1[format, v1]]
};
ev: REF Xl.EventRep.errorNotify;
IF errorEvent#NIL AND errorEvent.explanation=NIL THEN {
TRUSTED { ev ¬ LOOPHOLE[errorEvent] }; --read-write
ev.originalCodeByte ¬ ORD[Xl.EventCode[errorNotify]];
WITH ev.replyText SELECT FROM
r: XlPrivate.Reply => {
IF XlPrivate.Get8[r, 0]#0 THEN Ap0["package is not an error event"]
ELSE {
XlPrivate.SetPos[r, 1];
ev.errorKind ¬ VAL[XlPrivate.Read8[r]];
ev.seq ¬ XlPrivate.ERead16[r];
ev.badValue ¬ XlPrivate.ERead32[r];
ev.minorOpCode ¬ XlPrivate.ERead16[r];
ev.majorOpCode ¬ VAL[XlPrivate.ERead8[r]];
SELECT ev.errorKind FROM
nil => Ap0["nil error"];
request => Ap["bad request: %g", IO.card[ev.majorOpCode]];
value => Ap["bad value: %g", IO.card[ev.badValue]];
window => Ap["bad window id: %g", IO.card[ev.badValue]];
pixmap => Ap["bad pixmap id: %g", IO.card[ev.badValue]];
atom => Ap["bad atom id: %g", IO.card[ev.badValue]];
cursor => Ap["bad cursor id: %g", IO.card[ev.badValue]];
font => Ap["bad font id: %g", IO.card[ev.badValue]];
match => Ap0["match error"];
drawable => Ap["bad drawable id: %g", IO.card[ev.badValue]];
access => Ap0["access error"];
alloc => Ap0["server out of memory"];
colormap => Ap["bad colormap id: %g", IO.card[ev.badValue]];
gContext => Ap["bad gContext id: %g", IO.card[ev.badValue]];
idChoice => Ap["idChoice error: bad id: %g", IO.card[ev.badValue]];
name => Ap0["name error"];
length => Ap0["length error"];
implementation => Ap0["implementation error"];
connectionWedged => Ap0["connection wedged"];
requestFromDeadConnection => Ap0["connection closed"];
VAL[241] => Ap0["reply inconsistent"];
ENDCASE => Ap["unknown error (%g)", IO.card[ORD[ev.errorKind]]];
Ap[" (majorOpCode: %g)", IO.card[ev.majorOpCode]];
IF ev.minorOpCode#0 THEN
Ap[" (minorOpCode: %g)", IO.card[ev.minorOpCode]];
};
};
ENDCASE => {Ap0["reply wrong"]};
};
};
lastErrorEvent, secondLastErrorEvent: Xl.ErrorNotifyEvent ¬ NIL;
lastTime: BasicTime.GMT ¬ BasicTime.earliestGMT;
SwapLastError: ENTRY PROC [newLastError: Xl.ErrorNotifyEvent, now: BasicTime.GMT] RETURNS [previous, older: Xl.ErrorNotifyEvent, time: BasicTime.GMT] = {
previous ¬ lastErrorEvent;
older ¬ secondLastErrorEvent;
secondLastErrorEvent ¬ lastErrorEvent;
lastErrorEvent ¬ newLastError;
time ¬ lastTime;
lastTime ¬ now;
};
ErrorEventProc: Xl.EventProcType = {
c: Xl.Connection ¬ event.connection;
message: Rope.ROPE ¬ "Xl: unknown error";
WITH event SELECT FROM
error: Xl.ErrorNotifyEvent => {
XlPrivateErrorHandling.Explain[error];
BEGIN -- little hack to avoid reporting the same kind of error message over and over
now: BasicTime.GMT ¬ BasicTime.earliestGMT;
previous, previous2: Xl.ErrorNotifyEvent; lastTime: BasicTime.GMT;
now ¬ BasicTime.Now[! BasicTime.TimeNotKnown => CONTINUE];
[previous, previous2, lastTime] ¬ SwapLastError[error, now];
IF previous#NIL AND previous.connection=c THEN {
IF previous.errorKind=error.errorKind THEN {
IF BasicTime.Period[from: lastTime, to: now]<=2 THEN {
--ok, we surpress some messaging
IF previous2=NIL OR previous2.connection#c
THEN {
SimpleFeedback.Append[$X11Errors, oneLiner, $XlErrors, "...Similar X window error(s) suppressed...\n"];
}
ELSE {
--be completely quiet
};
RETURN
}
}
};
END;
message ¬ IO.PutFR["XError [%g, kind:%g", IO.rope[error.explanation], IO.card[ORD[error.errorKind]]];
message ¬ IO.PutFR["%g, major:%g, minor:%g", IO.rope[message], IO.card[error.majorOpCode], IO.card[error.minorOpCode]];
message ¬ IO.PutFR["%g, bad:%g", IO.rope[message], IO.card[error.badValue]];
IF c#NIL THEN {
message ¬ IO.PutFR["%g, event sequenceNo: %g last sequenceNo: %g", IO.rope[message], IO.card[error.seq], IO.card[c.sequenceNumber]];
};
message ¬ Rope.Concat[message, "]"];
};
ENDCASE => {};
SimpleFeedback.Append[$X11Errors, oneLiner, $XlErrors, message];
SimpleFeedback.Blink[$X11Errors, $XlError];
};
XlPrivateErrorHandling.RegisterErrorReportProc[ErrorEventProc];
XlPrivateErrorHandling.RegisterExplainer[Explain];
END.