try to make sure compiler/include/mmakefile is always refreshed correctly.
[AROS.git] / rom / exec / useralert.c
blob80df6bdc9b04f18619dca91962aa68c5cabfbe0e
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Display an alert in user mode.
6 Lang: english
7 */
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>
16 #include "etask.h"
17 #include "exec_intern.h"
18 #include "exec_util.h"
20 static LONG SafeEasyRequest(struct EasyStruct *es, BOOL full, struct IntuitionBase *IntuitionBase)
22 LONG result;
23 APTR req = BuildEasyRequestArgs(NULL, es, 0, NULL);
25 if (!req)
27 /* Return -1 if requester creation failed. This makes us to fallback to safe-mode alert. */
28 return -1;
33 result = SysReqHandler(req, NULL, TRUE);
35 if (full)
37 switch (result)
39 case 1:
40 NewRawDoFmt("*** Logged alert:\n%s\n", RAWFMTFUNC_SERIAL, NULL, es->es_TextFormat);
41 result = -2;
42 break;
45 } while (result == -2);
47 FreeSysRequest(req);
48 return result;
51 static const char startstring[] = "Program failed\n";
52 static const char endstring[] = "\nWait for disk activity to finish.";
53 static const char deadend_buttons[] = "More...|Suspend|Reboot|Power off";
54 static const char recoverable_buttons[] = "More...|Continue";
55 static const char full_deadend_buttons[] = "Log|Suspend|Reboot|Power off";
56 static const char full_recoverable_buttons[] = "Log|Continue";
58 LONG Alert_AskSuspend(struct Task *task, ULONG alertNum, char * buffer, struct ExecBase *SysBase)
60 LONG choice = -1;
61 struct IntuitionBase *IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 36);
63 if (IntuitionBase)
65 if (buffer)
67 struct IntETask *iet = GetIntETask(task);
68 char *buf, *end;
69 struct EasyStruct es = {
70 sizeof (struct EasyStruct),
72 NULL,
73 buffer,
74 NULL,
77 buf = Alert_AddString(buffer, startstring);
78 buf = FormatAlert(buf, alertNum, task, iet ? iet->iet_AlertLocation : NULL, iet ? iet->iet_AlertType : AT_NONE, SysBase);
79 end = buf;
80 buf = Alert_AddString(buf, endstring);
81 *buf = 0;
83 es.es_Title = Alert_GetTitle(alertNum);
85 /* Determine set of buttons */
86 es.es_GadgetFormat = (alertNum & AT_DeadEnd) ? deadend_buttons : recoverable_buttons;
88 D(bug("[UserAlert] Body text:\n%s\n", buffer));
89 choice = SafeEasyRequest(&es, FALSE, IntuitionBase);
91 if (choice == 1)
93 /* 'More' has been pressed. Append full alert data */
94 FormatAlertExtra(end, iet->iet_AlertStack, iet ? iet->iet_AlertType : AT_NONE, iet ? &iet->iet_AlertData : NULL, SysBase);
96 /* Re-post the alert, without 'More...' this time */
97 es.es_GadgetFormat = (alertNum & AT_DeadEnd) ? full_deadend_buttons : full_recoverable_buttons;
99 choice = SafeEasyRequest(&es, TRUE, IntuitionBase);
103 CloseLibrary(&IntuitionBase->LibNode);
105 return choice;
108 static LONG AskSuspend(struct Task *task, ULONG alertNum, struct ExecBase *SysBase)
110 char * buffer = AllocMem(ALERT_BUFFER_SIZE, MEMF_ANY);
112 LONG choice = Alert_AskSuspend(task, alertNum, buffer, SysBase);
114 FreeMem(buffer, ALERT_BUFFER_SIZE);
116 return choice;
121 * This function posts alerts in user-mode via Intuition requester.
122 * Returns initial alert code if something fails and 0 if it was a recoverable
123 * alert and everything went ok.
124 * Note that in case of some crashes (e.g. corrupt memory list) this function
125 * may crash itself, and this has to be handled on a lower level. This is
126 * why we do this trick with iet_AlertCode
128 ULONG Exec_UserAlert(ULONG alertNum, struct ExecBase *SysBase)
130 struct Task *task = GET_THIS_TASK;
131 struct IntETask *iet;
132 LONG res;
134 /* Protect ourselves agains really hard crashes where SysBase->ThisTask is NULL.
135 Obviously we won't go far away in such a case */
136 if (!task)
137 return alertNum;
139 /* Get internal task structure */
140 if ((iet = GetIntETask(task)))
143 * If we already have alert number for this task, we are in double-crash during displaying
144 * intuition requester. Well, take the initial alert code (because it's more helpful to the programmer)
145 * and proceed with arch-specific Alert().
146 * Since this is a double-crash, we may append AT_DeadEnd flag if our situation has become unrecoverable.
148 D(bug("[UserAlert] Task alert state: 0x%02X\n", iet->iet_AlertFlags));
149 if (iet->iet_AlertFlags & AF_Alert)
152 * Some more logic here. Nested AN_SysScrnType should not make original alert deadend.
153 * It just means we were unable to display it using Intuition requested because there
154 * are no display drivers at all.
156 if (alertNum == AN_SysScrnType)
157 return iet->iet_AlertCode;
158 else
159 return iet->iet_AlertCode | (alertNum & AT_DeadEnd);
163 * Otherwise we can try to put up Intuition requester first. Store alert code in order in ETask
164 * in order to indicate crash condition
166 iet->iet_AlertFlags |= AF_Alert;
167 iet->iet_AlertCode = alertNum;
171 * AN_SysScrnType is somewhat special. We remember it in the ETask (just in case),
172 * but propagate it to supervisor mode immediately. We do it because this error
173 * means we don't have any display modes, so we won't be able to bring up the requester.
175 if (alertNum == AN_SysScrnType)
176 return alertNum;
178 /* Issue a requester */
179 res = AskSuspend(task, alertNum, SysBase);
180 D(bug("[UserAlert] Requester result: %d\n", res));
182 /* If AskSuspend() failed, fail back to safe-mode alert */
183 if (res == -1)
184 return alertNum;
186 /* Halt if we need to */
187 if (alertNum & AT_DeadEnd)
189 switch (res)
191 case 0:
192 ShutdownA(SD_ACTION_POWEROFF);
193 break;
195 case 3:
196 ColdReboot();
197 /* In case if ColdReboot() doesn't work */
198 ShutdownA(SD_ACTION_COLDREBOOT);
199 break;
202 /* Well, stop if the user wants so (or if the reboot didn't work at all) */
203 Wait(0);
205 return 0;