Port the SB128 code to AROS.
[AROS.git] / rom / exec / useralert.c
blob23501b40ff911dd05411c766093827e405fff137
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>
8 #include "etask.h"
9 #include "exec_intern.h"
10 #include "exec_util.h"
12 static const char startstring[] = "Program failed\n";
13 static const char endstring[] = "\nWait for disk activity to finish.";
14 static const char deadend_buttons[] = "More...|Suspend|Reboot";
15 static const char recoverable_buttons[] = "More...|Continue";
17 #define MORE_SKIP 8
19 static LONG AskSuspend(struct Task *task, ULONG alertNum, struct ExecBase *SysBase)
21 LONG choice = -1;
22 struct IntuitionBase *IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 36);
24 if (IntuitionBase)
26 char *buffer = AllocMem(ALERT_BUFFER_SIZE, MEMF_ANY);
28 if (buffer)
30 struct IntETask *iet = GetIntETask(task);
31 char *buf, *end;
32 struct EasyStruct es = {
33 sizeof (struct EasyStruct),
35 NULL,
36 buffer,
37 NULL,
40 buf = Alert_AddString(buffer, startstring);
41 buf = FormatAlert(buf, alertNum, task, iet->iet_AlertLocation, iet->iet_AlertType, SysBase);
42 end = buf;
43 buf = Alert_AddString(buf, endstring);
44 *buf = 0;
46 es.es_Title = Alert_GetTitle(alertNum);
48 /* Determine set of buttons */
49 es.es_GadgetFormat = (alertNum & AT_DeadEnd) ? deadend_buttons : recoverable_buttons;
51 D(bug("[UserAlert] Body text:\n%s\n", buffer));
52 choice = EasyRequestArgs(NULL, &es, NULL, NULL);
54 if (choice == 1)
56 /* 'More' has been pressed. Append full alert data */
57 FormatAlertExtra(end, iet->iet_AlertStack, iet->iet_AlertType, &iet->iet_AlertData, SysBase);
59 /* Re-post the alert, without 'More...' this time */
60 es.es_GadgetFormat += MORE_SKIP;
61 choice = EasyRequestArgs(NULL, &es, NULL, NULL);
64 FreeMem(buffer, ALERT_BUFFER_SIZE);
67 CloseLibrary(&IntuitionBase->LibNode);
69 return choice;
73 * This function posts alerts in user-mode via Intuition requester.
74 * Returns initial alert code if something fails and 0 if it was a recoverable
75 * alert and everything went ok.
76 * Note that in case of some crashes (e.g. corrupt memory list) this function
77 * may crash itself, and this has to be handled on a lower level. This is
78 * why we do this trick with iet_AlertCode
80 ULONG Exec_UserAlert(ULONG alertNum, struct ExecBase *SysBase)
82 struct Task *task = SysBase->ThisTask;
83 struct IntETask *iet;
84 LONG res;
86 /* Protect ourselves agains really hard crashes where SysBase->ThisTask is NULL.
87 Obviously we won't go far away in such a case */
88 if (!task)
89 return alertNum;
91 /* Get internal task structure */
92 iet = GetIntETask(task);
94 * If we already have alert number for this task, we are in double-crash during displaying
95 * intuition requester. Well, take the initial alert code (because it's more helpful to the programmer)
96 * and proceed with arch-specific Alert().
97 * Since this is a double-crash, we may append AT_DeadEnd flag if our situation has become unrecoverable.
99 D(bug("[UserAlert] Task alert state: 0x%02X\n", iet->iet_AlertFlags));
100 if (iet->iet_AlertFlags & AF_Alert)
103 * Some more logic here. Nested AN_SysScrnType should not make original alert deadend.
104 * It just means we were unable to display it using Intuition requested because there
105 * are no display drivers at all.
107 if (alertNum == AN_SysScrnType)
108 return iet->iet_AlertCode;
109 else
110 return iet->iet_AlertCode | (alertNum & AT_DeadEnd);
114 * Otherwise we can try to put up Intuition requester first. Store alert code in order in ETask
115 * in order to indicate crash condition
117 iet->iet_AlertFlags |= AF_Alert;
118 iet->iet_AlertCode = alertNum;
120 * AN_SysScrnType is somewhat special. We remember it in the ETask (just in case),
121 * but propagate it to supervisor mode immediately. We do it because this error
122 * means we don't have any display modes, so we won't be able to bring up the requester.
124 if (alertNum == AN_SysScrnType)
125 return alertNum;
127 /* Issue a requester */
128 res = AskSuspend(task, alertNum, SysBase);
129 D(bug("[UserAlert] Requester result: %d\n", res));
131 /* If AskSuspend() failed, fail back to safe-mode alert */
132 if (res == -1)
133 return alertNum;
135 /* Halt if we need to */
136 if (alertNum & AT_DeadEnd)
138 if (res == 0)
140 ColdReboot();
141 /* In case if ColdReboot() doesn't work */
142 ShutdownA(SD_ACTION_COLDREBOOT);
144 D(bug("[UserAlert] Returned from ShutdownA()!\n"));
146 /* Well, stop if the user wants so (or if the reboot didn't work at all) */
147 Wait(0);
149 return 0;