1 #include <aros/debug.h>
2 #include <exec/alerts.h>
3 #include <intuition/intuition.h>
4 #include <proto/exec.h>
5 #include <proto/intuition.h>
6 #include <proto/kernel.h>
9 #include "exec_intern.h"
10 #include "exec_util.h"
12 static char *startstring
= "Program failed\n";
13 static char *endstring
= "\nWait for disk activity to finish.";
14 static char *deadend_buttons
= "More...|Suspend|Reboot";
15 static char *recoverable_buttons
= "More...|Continue";
19 static LONG
AskSuspend(struct Task
*task
, ULONG alertNum
, struct ExecBase
*SysBase
)
22 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)OpenLibrary("intuition.library", 36);
26 char *buffer
= AllocMem(ALERT_BUFFER_SIZE
, MEMF_ANY
);
31 struct EasyStruct es
= {
32 sizeof (struct EasyStruct
),
39 buf
= Alert_AddString(buffer
, startstring
);
40 buf
= FormatAlert(buf
, alertNum
, task
, SysBase
);
42 buf
= Alert_AddString(buf
, endstring
);
45 es
.es_Title
= Alert_GetTitle(alertNum
);
47 /* Determine set of buttons */
48 es
.es_GadgetFormat
= (alertNum
& AT_DeadEnd
) ? deadend_buttons
: recoverable_buttons
;
50 D(bug("[UserAlert] Body text:\n%s\n", buffer
));
51 choice
= EasyRequestArgs(NULL
, &es
, NULL
, NULL
);
55 /* 'More' has been pressed. Append full alert data */
56 FormatAlertExtra(end
, task
, SysBase
);
58 /* Re-post the alert, without 'More...' this time */
59 es
.es_GadgetFormat
+= MORE_SKIP
;
60 choice
= EasyRequestArgs(NULL
, &es
, NULL
, NULL
);
63 FreeMem(buffer
, ALERT_BUFFER_SIZE
);
66 CloseLibrary(&IntuitionBase
->LibNode
);
72 * This function posts alerts in user-mode via Intuition requester.
73 * Returns initial alert code if something fails and 0 if it was a recoverable
74 * alert and everything went ok.
75 * Note that in case of some crashes (e.g. corrupt memory list) this function
76 * may crash itself, and this has to be handled on a lower level. This is
77 * why we do this trick with iet_AlertCode
79 ULONG
Exec_UserAlert(ULONG alertNum
, struct ExecBase
*SysBase
)
81 struct Task
*task
= SysBase
->ThisTask
;
85 /* Protect ourselves agains really hard crashes where SysBase->ThisTask is NULL.
86 Obviously we won't go far away in such a case */
90 /* Get internal task structure */
91 iet
= GetIntETask(task
);
93 * If we already have alert number for this task, we are in double-crash during displaying
94 * intuition requester. Well, take the initial alert code (because it's more helpful to the programmer)
95 * and proceed with arch-specific Alert().
96 * Since this is a double-crash, we may append AT_DeadEnd flag if our situation has become unrecoverable.
98 D(bug("[UserAlert] Task alert state: 0x%08X\n", iet
->iet_AlertCode
));
99 if (iet
->iet_AlertCode
)
102 * Some more logic here. Nested AN_SysScrnType should not make original alert deadend.
103 * It just means we were unable to display it using Intuition requested because there
104 * are no display drivers at all.
106 if (alertNum
== AN_SysScrnType
)
107 return iet
->iet_AlertCode
;
109 return iet
->iet_AlertCode
| (alertNum
& AT_DeadEnd
);
113 * Otherwise we can try to put up Intuition requester first. Store alert code in order in ETask
114 * in order to indicate crash condition
116 iet
->iet_AlertCode
= alertNum
;
118 * AN_SysScrnType is somewhat special. We remember it in the ETask (just in case),
119 * but propagate it to supervisor mode immetiately. We do it because this error
120 * means we don't have any display modes, so we won't be able to bring up the requester.
122 if (alertNum
== AN_SysScrnType
)
125 /* Issue a requester */
126 res
= AskSuspend(task
, alertNum
, SysBase
);
127 D(bug("[UserAlert] Requester result: %d\n", res
));
129 /* If AskSuspend() failed, fail back to safe-mode alert */
133 /* Halt if we need to */
134 if (alertNum
& AT_DeadEnd
)
139 /* In case if ColdReboot() doesn't work */
140 ShutdownA(SD_ACTION_COLDREBOOT
);
142 D(bug("[UserAlert] Returned from ShutdownA()!\n"));
144 /* Well, stop if the user wants so (or if the reboot didn't work at all) */
148 /* Otherwise clear crash status and return happily */