[1mdiff --git a/src/gmrequest.c b/src/gmrequest.c[m
[1mindex c968990c..693bfe4a 100644[m
[1m--- a/src/gmrequest.c[m
[1m+++ b/src/gmrequest.c[m
[36m@@ -116,6 +116,8 @@[m [mvoid deserialize_GmResponse(iGmResponse *d, iStream *ins) {[m
[m
/----------------------------------------------------------------------------------------------/[m
[m
[32m+[m[32mstatic iAtomicInt idGen_;[m
[32m+[m
enum iGmRequestState {[m
initialized_GmRequestState,[m
receivingHeader_GmRequestState,[m
[36m@@ -126,6 +128,7 @@[m [menum iGmRequestState {[m
[m
struct Impl_GmRequest {[m
iObject object;[m
[32m+[m[32m uint32_t id;[m
iMutex * mtx;[m
iGmCerts * certs; /* not owned */[m
enum iGmRequestState state;[m
[36m@@ -471,7 +474,8 @@[m [mstatic void beginGopherConnection_GmRequest_(iGmRequest *d, const iString *host,[m
/----------------------------------------------------------------------------------------------/[m
[m
void init_GmRequest(iGmRequest *d, iGmCerts *certs) {[m
[31m- d->mtx = new_Mutex();[m
[32m+[m[32m d->mtx = new_Mutex();[m
[32m+[m[32m d->id = add_Atomic(&idGen_, 1) + 1;[m
d->resp = new_GmResponse();[m
d->isFilterEnabled = iTrue;[m
d->isRespLocked = iFalse;[m
[36m@@ -713,11 +717,18 @@[m [mvoid unlockResponse_GmRequest(iGmRequest *d) {[m
}[m
}[m
[m
[32m+[m[32muint32_t id_GmRequest(const iGmRequest *d) {[m
[32m+[m[32m return d ? d->id : 0;[m
[32m+[m[32m}[m
[32m+[m
iBool isFinished_GmRequest(const iGmRequest *d) {[m
[31m- iBool done;[m
[31m- iGuardMutex(d->mtx,[m
[31m- done = (d->state == finished_GmRequestState || d->state == failure_GmRequestState));[m
[31m- return done;[m
[32m+[m[32m if (d) {[m
[32m+[m[32m iBool done;[m
[32m+[m[32m iGuardMutex(d->mtx,[m
[32m+[m[32m done = (d->state == finished_GmRequestState || d->state == failure_GmRequestState));[m
[32m+[m[32m return done;[m
[32m+[m[32m }[m
[32m+[m[32m return iTrue;[m
}[m
[m
enum iGmStatusCode status_GmRequest(const iGmRequest *d) {[m
[1mdiff --git a/src/gmrequest.h b/src/gmrequest.h[m
[1mindex 9f20e0eb..2cf9e4ff 100644[m
[1m--- a/src/gmrequest.h[m
[1m+++ b/src/gmrequest.h[m
[36m@@ -73,6 +73,7 @@[m [mvoid cancel_GmRequest (iGmRequest *);[m
iGmResponse * lockResponse_GmRequest (iGmRequest *);[m
void unlockResponse_GmRequest (iGmRequest *);[m
[m
[32m+[m[32muint32_t id_GmRequest (const iGmRequest ); / unique ID */[m
iBool isFinished_GmRequest (const iGmRequest *);[m
enum iGmStatusCode status_GmRequest (const iGmRequest *);[m
const iString * meta_GmRequest (const iGmRequest *);[m
[1mdiff --git a/src/ui/command.c b/src/ui/command.c[m
[1mindex c5ca164e..3ae0f0c9 100644[m
[1m--- a/src/ui/command.c[m
[1m+++ b/src/ui/command.c[m
[36m@@ -50,6 +50,15 @@[m [mint arg_Command(const char *cmd) {[m
return argLabel_Command(cmd, "arg");[m
}[m
[m
[32m+[m[32muint32_t argU32Label_Command(const char *cmd, const char *label) {[m
[32m+[m[32m const iString *tok = tokenString_(label);[m
[32m+[m[32m const char *ptr = strstr(cmd, cstr_String(tok));[m
[32m+[m[32m if (ptr) {[m
[32m+[m[32m return strtoul(ptr + size_String(tok), NULL, 10);[m
[32m+[m[32m }[m
[32m+[m[32m return 0;[m
[32m+[m[32m}[m
[32m+[m
float argfLabel_Command(const char *cmd, const char *label) {[m
const iString *tok = tokenString_(label);[m
const char *ptr = strstr(cmd, cstr_String(tok));[m
[1mdiff --git a/src/ui/command.h b/src/ui/command.h[m
[1mindex 43992b8e..10a29101 100644[m
[1m--- a/src/ui/command.h[m
[1m+++ b/src/ui/command.h[m
[36m@@ -25,16 +25,17 @@[m [mSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */[m
#include <the_Foundation/range.h>[m
#include <the_Foundation/vec2.h>[m
[m
[31m-iBool equal_Command (const char *commandWithArgs, const char *command);[m
[31m-[m
[31m-int arg_Command (const char ); / arg: */[m
[31m-float argf_Command (const char ); / arg: */[m
[31m-int argLabel_Command (const char *, const char *label);[m
[31m-float argfLabel_Command (const char *, const char *label);[m
[31m-void * pointer_Command (const char ); / ptr: */[m
[31m-void * pointerLabel_Command (const char *, const char *label);[m
[31m-iInt2 coord_Command (const char *);[m
[31m-iInt2 dir_Command (const char *);[m
[32m+[m[32miBool equal_Command (const char *commandWithArgs, const char *command);[m
[32m+[m
[32m+[m[32mint arg_Command (const char ); / arg: */[m
[32m+[m[32mfloat argf_Command (const char ); / arg: */[m
[32m+[m[32mint argLabel_Command (const char *, const char *label);[m
[32m+[m[32muint32_t argU32Label_Command (const char *, const char *label);[m
[32m+[m[32mfloat argfLabel_Command (const char *, const char *label);[m
[32m+[m[32mvoid * pointer_Command (const char ); / ptr: */[m
[32m+[m[32mvoid * pointerLabel_Command (const char *, const char *label);[m
[32m+[m[32miInt2 coord_Command (const char *);[m
[32m+[m[32miInt2 dir_Command (const char *);[m
[m
const iString * string_Command (const char *, const char label); / space-delimited */[m
iRangecc range_Command (const char *, const char label); / space-delimited */[m
[1mdiff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c[m
[1mindex f3c9ea82..13ef878f 100644[m
[1m--- a/src/ui/documentwidget.c[m
[1m+++ b/src/ui/documentwidget.c[m
[36m@@ -394,13 +394,21 @@[m [mstatic void requestUpdated_DocumentWidget_(iAnyObject *obj) {[m
iDocumentWidget *d = obj;[m
const int wasUpdated = exchange_Atomic(&d->isRequestUpdated, iTrue);[m
if (!wasUpdated) {[m
[31m- postCommand_Widget(obj, "document.request.updated doc:%p request:%p", d, d->request);[m
[32m+[m[32m postCommand_Widget(obj,[m
[32m+[m[32m "document.request.updated doc:%p reqid:%u request:%p",[m
[32m+[m[32m d,[m
[32m+[m[32m id_GmRequest(d->request),[m
[32m+[m[32m d->request);[m
}[m
}[m
[m
static void requestFinished_DocumentWidget_(iAnyObject *obj) {[m
iDocumentWidget *d = obj;[m
[31m- postCommand_Widget(obj, "document.request.finished doc:%p request:%p", d, d->request);[m
[32m+[m[32m postCommand_Widget(obj,[m
[32m+[m[32m "document.request.finished doc:%p reqid:%u request:%p",[m
[32m+[m[32m d,[m
[32m+[m[32m id_GmRequest(d->request),[m
[32m+[m[32m d->request);[m
}[m
[m
static int documentWidth_DocumentWidget_(const iDocumentWidget *d) {[m
[36m@@ -965,7 +973,7 @@[m [mstatic void updateDocument_DocumentWidget_(iDocumentWidget *d, const iGmResponse[m
if (d->state == ready_RequestState) {[m
return;[m
}[m
[31m- const iBool isRequestFinished = !d->request || isFinished_GmRequest(d->request);[m
[32m+[m[32m const iBool isRequestFinished = isFinished_GmRequest(d->request);[m
/* TODO: Do document update in the background. However, that requires a text metrics calculator[m
that does not try to cache the glyph bitmaps. */[m
const enum iGmStatusCode statusCode = response->statusCode;[m
[36m@@ -1892,7 +1900,7 @@[m [mstatic iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)[m
return iTrue;[m
}[m
else if (equalWidget_Command(cmd, w, "document.request.updated") &&[m
[31m- d->request && pointerLabel_Command(cmd, "request") == d->request) {[m
[32m+[m[32m id_GmRequest(d->request) == argU32Label_Command(cmd, "reqid")) {[m
set_Block(&d->sourceContent, &lockResponse_GmRequest(d->request)->body);[m
unlockResponse_GmRequest(d->request);[m
if (document_App() == d) {[m
[36m@@ -1903,7 +1911,7 @@[m [mstatic iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)[m
return iFalse;[m
}[m
else if (equalWidget_Command(cmd, w, "document.request.finished") &&[m
[31m- d->request && pointerLabel_Command(cmd, "request") == d->request) {[m
[32m+[m[32m id_GmRequest(d->request) == argU32Label_Command(cmd, "reqid")) {[m
set_Block(&d->sourceContent, body_GmRequest(d->request));[m
if (!isSuccess_GmStatusCode(status_GmRequest(d->request))) {[m
format_String(&d->sourceHeader,[m
text/plain
This content has been proxied by September (ba2dc).