UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2025 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #import "webview.h" 30 #import "Container.h" 31 32 UIWIDGET ui_webview_create(UiObject *obj, UiWebviewArgs *args) { 33 UiVar *var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_GENERIC); 34 35 WKWebView *webview = [[WKWebView alloc]init]; 36 37 UiLayout layout = UI_ARGS2LAYOUT(args); 38 ui_container_add(obj, webview, &layout); 39 40 if(var) { 41 UiGeneric *value = var->value; 42 value->get = ui_webview_get; 43 value->get_type = ui_webview_get_type; 44 value->set = ui_webview_set; 45 value->destroy = ui_webview_destroy; 46 value->obj = (__bridge void*)webview; 47 if(value->value) { 48 ui_webview_set(value, value->value, UI_WEBVIEW_OBJECT_TYPE); 49 } else { 50 UiWebViewData *data = malloc(sizeof(UiWebViewData)); 51 memset(data, 0, sizeof(UiWebViewData)); 52 data->webview = (__bridge void*)webview; 53 data->javascript = TRUE; 54 data->zoom = 1; 55 value->value = value; 56 } 57 } 58 59 return (__bridge void*)webview; 60 } 61 62 UiWebViewData* ui_webview_data_clone(UiWebViewData *data) { 63 UiWebViewData *newdata = malloc(sizeof(UiWebViewData)); 64 memset(newdata, 0, sizeof(UiWebViewData)); 65 newdata->zoom = 1; 66 newdata->javascript = TRUE; 67 68 if(data) { 69 newdata->uri = data->uri ? strdup(data->uri) : NULL; 70 newdata->mimetype = data->mimetype ? strdup(data->mimetype) : NULL; 71 newdata->encoding = data->encoding ? strdup(data->encoding) : NULL; 72 newdata->type = data->type; 73 newdata->javascript = data->javascript; 74 newdata->zoom = data->zoom; 75 if(data->content && data->contentlength > 0) { 76 newdata->content = malloc(data->contentlength + 1); 77 memcpy(newdata->content, data->content, data->contentlength); 78 newdata->content[data->contentlength] = 0; 79 newdata->contentlength = data->contentlength; 80 } 81 } 82 83 return newdata; 84 } 85 86 void ui_webview_data_free(UiWebViewData *data) { 87 if(!data) { 88 return; 89 } 90 free(data->uri); 91 free(data->mimetype); 92 free(data->encoding); 93 free(data->content); 94 free(data); 95 } 96 97 void* ui_webview_get(UiGeneric *g) { 98 UiWebViewData *data = g->value; 99 WKWebView *webview = (__bridge WKWebView*)g->obj; 100 101 if(data->type == WEBVIEW_CONTENT_URL) { 102 (void)ui_webview_get_uri(g); // this updates data->uri 103 } 104 data->zoom = webview.pageZoom; 105 106 return ui_webview_data_clone(g->value); 107 } 108 109 const char* ui_webview_get_type(UiGeneric *g) { 110 return UI_WEBVIEW_OBJECT_TYPE; 111 } 112 113 int ui_webview_set(UiGeneric *g, void *data, const char *type) { 114 if(!data || !type) { 115 return 1; 116 } 117 if(strcmp(type, UI_WEBVIEW_OBJECT_TYPE)) { 118 return 1; 119 } 120 ui_webview_data_free(g->value); 121 g->value = ui_webview_data_clone(data); 122 123 WKWebView *webview = (__bridge WKWebView*)g->obj; 124 UiWebViewData *webd = data; 125 if(webd->type == WEBVIEW_CONTENT_URL) { 126 const char *uri = webd->uri ? webd->uri : "about:blank"; 127 NSURL *url = [NSURL URLWithString:[[NSString alloc] initWithUTF8String:uri]]; 128 if(url) { 129 NSURLRequest *req = [NSURLRequest requestWithURL:url]; 130 if(req) { 131 [webview loadRequest:req]; 132 } 133 } 134 } else { 135 NSString *mimetype = [[NSString alloc]initWithUTF8String: webd->mimetype ? webd->mimetype : "text/plain"]; 136 NSString *encoding = [[NSString alloc]initWithUTF8String: webd->encoding ? webd->encoding : "UTF-8"]; 137 NSString *urlStr = [[NSString alloc]initWithUTF8String: webd->uri ? webd->uri : "file:///"]; 138 NSURL *url = [NSURL URLWithString:urlStr]; 139 NSData *content = [NSData dataWithBytes:webd->content length:webd->contentlength]; 140 if(!url) { 141 url = [NSURL URLWithString:@"about:blank"]; 142 } 143 [webview loadData:content MIMEType:mimetype characterEncodingName:encoding baseURL:url]; 144 } 145 146 webview.pageZoom = webd->zoom; 147 148 return 1; 149 } 150 151 void ui_webview_destroy(UiGeneric *g) { 152 ui_webview_data_free(g->value); 153 g->value = NULL; 154 } 155 156 157 void ui_webview_load_url(UiGeneric *g, const char *url) { 158 WKWebView *webview = (__bridge WKWebView*)g->obj; 159 UiWebViewData *data = g->value; 160 data->type = WEBVIEW_CONTENT_URL; 161 162 if(!url) { 163 url = "about:blank"; 164 } 165 166 NSURL *nsurl = [NSURL URLWithString:[[NSString alloc] initWithUTF8String:url]]; 167 if(nsurl) { 168 NSURLRequest *req = [NSURLRequest requestWithURL:nsurl]; 169 if(req) { 170 [webview loadRequest:req]; 171 } 172 } 173 } 174 175 void ui_webview_load_content( 176 UiGeneric *g, 177 const char *uri, 178 const char *content, 179 size_t contentlength, 180 const char *mimetype, 181 const char *encoding) 182 { 183 UiWebViewData *data = g->value; 184 WKWebView *webview = (__bridge WKWebView*)g->obj; 185 186 data->type = WEBVIEW_CONTENT_CONTENT; 187 188 free(data->uri); 189 data->uri = NULL; 190 free(data->mimetype); 191 free(data->encoding); 192 free(data->content); 193 data->type = WEBVIEW_CONTENT_URL; 194 195 data->content = malloc(contentlength+1); 196 memcpy(data->content, content, contentlength); 197 data->content[contentlength] = 0; 198 199 if(!mimetype) { 200 mimetype = "text/plain"; 201 } 202 if(!encoding) { 203 encoding = "UTF-8"; 204 } 205 206 data->mimetype = strdup(mimetype); 207 data->encoding = strdup(encoding); 208 209 NSString *mtype = [[NSString alloc]initWithUTF8String:mimetype]; 210 NSString *enc = [[NSString alloc]initWithUTF8String:encoding]; 211 NSData *ct = [NSData dataWithBytes:content length:contentlength]; 212 NSURL *url; 213 if(uri) { 214 NSString *uriStr = [[NSString alloc]initWithUTF8String:uri]; 215 url = [NSURL URLWithString:uriStr]; 216 } else { 217 url = [NSURL URLWithString:@"file:///"]; 218 } 219 [webview loadData:ct MIMEType:mtype characterEncodingName:enc baseURL:url]; 220 } 221 222 223 void ui_webview_reload(UiGeneric *g) { 224 WKWebView *webview = (__bridge WKWebView*)g->obj; 225 [webview reload]; 226 } 227 228 UiBool ui_webview_can_go_back(UiGeneric *g) { 229 return FALSE; 230 } 231 232 UiBool ui_webview_can_go_forward(UiGeneric *g) { 233 return FALSE; 234 } 235 236 void ui_webview_go_back(UiGeneric *g) { 237 238 } 239 240 void ui_webview_go_forward(UiGeneric *g) { 241 242 } 243 244 const char * ui_webview_get_uri(UiGeneric *g) { 245 UiWebViewData *data = g->value; 246 WKWebView *webview = (__bridge WKWebView*)g->obj; 247 248 free(data->uri); 249 data->uri = NULL; 250 251 NSURL *url = webview.URL; 252 if(url) { 253 NSString *s = [url absoluteString]; 254 if(s) { 255 data->uri = strdup(s.UTF8String); 256 } 257 } 258 return data->uri; 259 } 260 261 void ui_webview_enable_javascript(UiGeneric *g, UiBool enable) { 262 // unsupported 263 } 264 265 void ui_webview_set_zoom(UiGeneric *g, double zoom) { 266 WKWebView *webview = (__bridge WKWebView*)g->obj; 267 webview.pageZoom = zoom; 268 } 269 270 double ui_webview_get_zoom(UiGeneric *g) { 271 WKWebView *webview = (__bridge WKWebView*)g->obj; 272 return webview.pageZoom; 273 } 274