2 Copyright © 1995-2012, The AROS Development Team. All rights reserved.
5 Desc: Display an alert in user mode.
9 #include <aros/debug.h>
10 #include <exec/alerts.h>
11 #include <exec/rawfmt.h>
12 #include <intuition/intuition.h>
13 #include <proto/exec.h>
14 #include <proto/intuition.h>
15 #include <proto/kernel.h>
18 #include "exec_intern.h"
19 #include "exec_util.h"
21 static LONG
SafeEasyRequest(struct EasyStruct
*es
, BOOL full
, struct IntuitionBase
*IntuitionBase
)
24 APTR req
= BuildEasyRequestArgs(NULL
, es
, 0, NULL
);
28 /* Return -1 if requester creation failed. This makes us to fallback to safe-mode alert. */
34 result
= SysReqHandler(req
, NULL
, TRUE
);
41 NewRawDoFmt("*** Logged alert:\n%s\n", RAWFMTFUNC_SERIAL
, NULL
, es
->es_TextFormat
);
46 } while (result
== -2);
52 static const char startstring
[] = "Program failed\n";
53 static const char endstring
[] = "\nWait for disk activity to finish.";
54 static const char deadend_buttons
[] = "More...|Suspend|Reboot|Power off";
55 static const char recoverable_buttons
[] = "More...|Continue";
56 static const char full_deadend_buttons
[] = "Log|Suspend|Reboot|Power off";
57 static const char full_recoverable_buttons
[] = "Log|Continue";
59 LONG
Alert_AskSuspend(struct Task
*task
, ULONG alertNum
, char * buffer
, struct ExecBase
*SysBase
)
62 struct IntuitionBase
*IntuitionBase
= (struct IntuitionBase
*)OpenLibrary("intuition.library", 36);
68 struct IntETask
*iet
= GetIntETask(task
);
70 struct EasyStruct es
= {
71 sizeof (struct EasyStruct
),
78 buf
= Alert_AddString(buffer
, startstring
);
79 buf
= FormatAlert(buf
, alertNum
, task
, iet
? iet
->iet_AlertLocation
: NULL
, iet
? iet
->iet_AlertType
: AT_NONE
, SysBase
);
81 buf
= Alert_AddString(buf
, endstring
);
84 es
.es_Title
= Alert_GetTitle(alertNum
);
86 /* Determine set of buttons */
87 es
.es_GadgetFormat
= (alertNum
& AT_DeadEnd
) ? deadend_buttons
: recoverable_buttons
;
89 D(bug("[UserAlert] Body text:\n%s\n", buffer
));
90 choice
= SafeEasyRequest(&es
, FALSE
, IntuitionBase
);
94 /* 'More' has been pressed. Append full alert data */
95 FormatAlertExtra(end
, iet
->iet_AlertStack
, iet
? iet
->iet_AlertType
: AT_NONE
, iet
? &iet
->iet_AlertData
: NULL
, SysBase
);
97 /* Re-post the alert, without 'More...' this time */
98 es
.es_GadgetFormat
= (alertNum
& AT_DeadEnd
) ? full_deadend_buttons
: full_recoverable_buttons
;
100 choice
= SafeEasyRequest(&es
, TRUE
, IntuitionBase
);
104 CloseLibrary(&IntuitionBase
->LibNode
);
109 static LONG
AskSuspend(struct Task
*task
, ULONG alertNum
, struct ExecBase
*SysBase
)
111 char * buffer
= AllocMem(ALERT_BUFFER_SIZE
, MEMF_ANY
);
113 LONG choice
= Alert_AskSuspend(task
, alertNum
, buffer
, SysBase
);
115 FreeMem(buffer
, ALERT_BUFFER_SIZE
);
122 * This function posts alerts in user-mode via Intuition requester.
123 * Returns initial alert code if something fails and 0 if it was a recoverable
124 * alert and everything went ok.
125 * Note that in case of some crashes (e.g. corrupt memory list) this function
126 * may crash itself, and this has to be handled on a lower level. This is
127 * why we do this trick with iet_AlertCode
129 ULONG
Exec_UserAlert(ULONG alertNum
, struct ExecBase
*SysBase
)
131 struct Task
*task
= GET_THIS_TASK
;
132 struct IntETask
*iet
;
135 /* Protect ourselves agains really hard crashes where SysBase->ThisTask is NULL.
136 Obviously we won't go far away in such a case */
140 /* Get internal task structure */
141 if ((iet
= GetIntETask(task
)))
144 * If we already have alert number for this task, we are in double-crash during displaying
145 * intuition requester. Well, take the initial alert code (because it's more helpful to the programmer)
146 * and proceed with arch-specific Alert().
147 * Since this is a double-crash, we may append AT_DeadEnd flag if our situation has become unrecoverable.
149 D(bug("[UserAlert] Task alert state: 0x%02X\n", iet
->iet_AlertFlags
));
150 if (iet
->iet_AlertFlags
& AF_Alert
)
153 * Some more logic here. Nested AN_SysScrnType should not make original alert deadend.
154 * It just means we were unable to display it using Intuition requested because there
155 * are no display drivers at all.
157 if (alertNum
== AN_SysScrnType
)
158 return iet
->iet_AlertCode
;
160 return iet
->iet_AlertCode
| (alertNum
& AT_DeadEnd
);
164 * Otherwise we can try to put up Intuition requester first. Store alert code in order in ETask
165 * in order to indicate crash condition
167 iet
->iet_AlertFlags
|= AF_Alert
;
168 iet
->iet_AlertCode
= alertNum
;
172 * AN_SysScrnType is somewhat special. We remember it in the ETask (just in case),
173 * but propagate it to supervisor mode immediately. We do it because this error
174 * means we don't have any display modes, so we won't be able to bring up the requester.
176 if (alertNum
== AN_SysScrnType
)
179 /* Issue a requester */
180 res
= AskSuspend(task
, alertNum
, SysBase
);
181 D(bug("[UserAlert] Requester result: %d\n", res
));
183 /* If AskSuspend() failed, fail back to safe-mode alert */
187 /* Halt if we need to */
188 if (alertNum
& AT_DeadEnd
)
193 ShutdownA(SD_ACTION_POWEROFF
);
198 /* In case if ColdReboot() doesn't work */
199 ShutdownA(SD_ACTION_COLDREBOOT
);
203 /* Well, stop if the user wants so (or if the reboot didn't work at all) */