diff options
Diffstat (limited to 'src/ui/documentwidget.c')
-rw-r--r-- | src/ui/documentwidget.c | 67 |
1 files changed, 55 insertions, 12 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index e8a0ded9..aab010c9 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -1,5 +1,8 @@ | |||
1 | #include "documentwidget.h" | 1 | #include "documentwidget.h" |
2 | #include "paint.h" | 2 | #include "paint.h" |
3 | #include "util.h" | ||
4 | #include "../gemini.h" | ||
5 | #include "../gmdocument.h" | ||
3 | 6 | ||
4 | #include <the_Foundation/regexp.h> | 7 | #include <the_Foundation/regexp.h> |
5 | #include <the_Foundation/tlsrequest.h> | 8 | #include <the_Foundation/tlsrequest.h> |
@@ -15,9 +18,10 @@ struct Impl_DocumentWidget { | |||
15 | iWidget widget; | 18 | iWidget widget; |
16 | enum iDocumentState state; | 19 | enum iDocumentState state; |
17 | iString *url; | 20 | iString *url; |
18 | iString *source; | ||
19 | int statusCode; | ||
20 | iTlsRequest *request; | 21 | iTlsRequest *request; |
22 | int statusCode; | ||
23 | iString *newSource; | ||
24 | iGmDocument *doc; | ||
21 | }; | 25 | }; |
22 | 26 | ||
23 | iDeclareType(Url) | 27 | iDeclareType(Url) |
@@ -31,7 +35,8 @@ struct Impl_Url { | |||
31 | }; | 35 | }; |
32 | 36 | ||
33 | void init_Url(iUrl *d, const iString *text) { | 37 | void init_Url(iUrl *d, const iString *text) { |
34 | iRegExp *pattern = new_RegExp("(.+)://([^/:?]+)(:[0-9]+)?([^?]*)(\\?.*)?", caseInsensitive_RegExpOption); | 38 | iRegExp *pattern = |
39 | new_RegExp("(.+)://([^/:?]+)(:[0-9]+)?([^?]*)(\\?.*)?", caseInsensitive_RegExpOption); | ||
35 | iRegExpMatch m; | 40 | iRegExpMatch m; |
36 | if (matchString_RegExp(pattern, text, &m)) { | 41 | if (matchString_RegExp(pattern, text, &m)) { |
37 | capturedRange_RegExpMatch(&m, 1, &d->protocol); | 42 | capturedRange_RegExpMatch(&m, 1, &d->protocol); |
@@ -59,22 +64,28 @@ void init_DocumentWidget(iDocumentWidget *d) { | |||
59 | d->state = blank_DocumentState; | 64 | d->state = blank_DocumentState; |
60 | d->url = new_String(); | 65 | d->url = new_String(); |
61 | d->statusCode = 0; | 66 | d->statusCode = 0; |
62 | d->source = new_String(); | ||
63 | d->request = NULL; | 67 | d->request = NULL; |
64 | 68 | d->newSource = new_String(); | |
69 | d->doc = new_GmDocument(); | ||
65 | setUrl_DocumentWidget(d, collectNewCStr_String("gemini.circumlunar.space/")); | 70 | setUrl_DocumentWidget(d, collectNewCStr_String("gemini.circumlunar.space/")); |
66 | } | 71 | } |
67 | 72 | ||
68 | void deinit_DocumentWidget(iDocumentWidget *d) { | 73 | void deinit_DocumentWidget(iDocumentWidget *d) { |
69 | delete_String(d->source); | ||
70 | delete_String(d->url); | 74 | delete_String(d->url); |
75 | delete_String(d->newSource); | ||
76 | iRelease(d->doc); | ||
77 | } | ||
78 | |||
79 | static int documentWidth_DocumentWidget_(const iDocumentWidget *d) { | ||
80 | const iWidget *w = constAs_Widget(d); | ||
81 | const iRect bounds = bounds_Widget(w); | ||
82 | return bounds.size.x; | ||
71 | } | 83 | } |
72 | 84 | ||
73 | void setSource_DocumentWidget(iDocumentWidget *d, const iString *source) { | 85 | void setSource_DocumentWidget(iDocumentWidget *d, const iString *source) { |
74 | /* TODO: lock source during update */ | 86 | /* TODO: lock source during update */ |
75 | set_String(d->source, source); | 87 | setSource_GmDocument(d->doc, source, documentWidth_DocumentWidget_(d)); |
76 | printf("%s\n", cstr_String(d->source)); | 88 | d->state = ready_DocumentState; |
77 | d->state = layout_DocumentState; | ||
78 | } | 89 | } |
79 | 90 | ||
80 | static iRangecc getLine_(iRangecc text) { | 91 | static iRangecc getLine_(iRangecc text) { |
@@ -92,10 +103,12 @@ static void requestFinished_DocumentWidget_(iAnyObject *obj) { | |||
92 | /* First line is the status code. */ { | 103 | /* First line is the status code. */ { |
93 | iString *line = newRange_String(respLine); | 104 | iString *line = newRange_String(respLine); |
94 | trim_String(line); | 105 | trim_String(line); |
95 | printf("response: %s\n", cstr_String(line)); | 106 | d->statusCode = toInt_String(line); |
107 | printf("response (%02d): %s\n", d->statusCode, cstr_String(line)); | ||
108 | /* TODO: post a command with the status code */ | ||
96 | delete_String(line); | 109 | delete_String(line); |
97 | } | 110 | } |
98 | setSource_DocumentWidget(d, collect_String(newRange_String(responseRange))); | 111 | setCStrN_String(d->newSource, responseRange.start, size_Range(&responseRange)); |
99 | delete_Block(response); | 112 | delete_Block(response); |
100 | iReleaseLater(d->request); | 113 | iReleaseLater(d->request); |
101 | d->request = NULL; | 114 | d->request = NULL; |
@@ -135,14 +148,44 @@ void setUrl_DocumentWidget(iDocumentWidget *d, const iString *url) { | |||
135 | 148 | ||
136 | static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *ev) { | 149 | static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *ev) { |
137 | iWidget *w = as_Widget(d); | 150 | iWidget *w = as_Widget(d); |
151 | if (isResize_UserEvent(ev)) { | ||
152 | setWidth_GmDocument(d->doc, documentWidth_DocumentWidget_(d)); | ||
153 | } | ||
138 | return processEvent_Widget(w, ev); | 154 | return processEvent_Widget(w, ev); |
139 | } | 155 | } |
140 | 156 | ||
157 | iDeclareType(DrawContext) | ||
158 | |||
159 | struct Impl_DrawContext { | ||
160 | const iDocumentWidget *d; | ||
161 | iRect bounds; | ||
162 | iPaint paint; | ||
163 | }; | ||
164 | |||
165 | static void drawRun_DrawContext_(void *context, const iGmRun *run) { | ||
166 | iDrawContext *d = context; | ||
167 | iString text; | ||
168 | /* TODO: making a copy is unnecessary; the text routines should accept Rangecc */ | ||
169 | initRange_String(&text, run->text); | ||
170 | drawString_Text(run->font, add_I2(d->bounds.pos, run->bounds.pos), run->color, &text); | ||
171 | deinit_String(&text); | ||
172 | } | ||
173 | |||
141 | static void draw_DocumentWidget_(const iDocumentWidget *d) { | 174 | static void draw_DocumentWidget_(const iDocumentWidget *d) { |
142 | const iWidget *w = constAs_Widget(d); | 175 | const iWidget *w = constAs_Widget(d); |
143 | draw_Widget(w); | 176 | draw_Widget(w); |
177 | /* Update the document? */ | ||
178 | if (!isEmpty_String(d->newSource)) { | ||
179 | /* TODO: Do this in the background. However, that requires a text metrics calculator | ||
180 | that does not try to cache the glyph bitmaps. */ | ||
181 | setSource_GmDocument(d->doc, d->newSource, documentWidth_DocumentWidget_(d)); | ||
182 | clear_String(d->newSource); | ||
183 | iConstCast(iDocumentWidget *, d)->state = ready_DocumentState; | ||
184 | } | ||
144 | if (d->state != ready_DocumentState) return; | 185 | if (d->state != ready_DocumentState) return; |
145 | /* TODO: lock source during draw */ | 186 | iDrawContext ctx = {.d = d, .bounds = bounds_Widget(w) }; |
187 | init_Paint(&ctx.paint); | ||
188 | render_GmDocument(d->doc, (iRangei){ 0, height_Rect(ctx.bounds) }, drawRun_DrawContext_, &ctx); | ||
146 | } | 189 | } |
147 | 190 | ||
148 | iBeginDefineSubclass(DocumentWidget, Widget) | 191 | iBeginDefineSubclass(DocumentWidget, Widget) |