💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Vgmi › files › a6ed8e421da9e785845c643449afa… captured on 2024-02-05 at 10:03:57. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-12-28)

-=-=-=-=-=-=-

Go Back

0 /*

1 * ISC License

2 * Copyright (c) 2023 RMF <rawmonk@firemail.cc>

3 */

4 #include <stddef.h>

5 #include <stdlib.h>

6 #include <stdio.h>

7 #include <string.h>

8 #include <stdint.h>

9 #include <pthread.h>

10 #include "termbox.h"

11 #include "macro.h"

12 #include "config.h"

13 #include "client.h"

14 #include "gemini.h"

15 #include "page.h"

16 #include "request.h"

17 #include "tab.h"

18 #include "strnstr.h"

19 #include "error.h"

20 #include "parser.h"

21 #include "known_hosts.h"

22 #include "image.h"

23

24 void tab_clean_requests(struct tab *tab);

25

26 void tab_display_loading(struct tab *tab, struct rect rect) {

27 int off[][2] = {

28 {0, 0}, {1, 0}, {2, 0}, {2, 1}, {2, 2}, {1, 2}, {0, 2}, {0, 1}

29 };

30 int x = rect.x + rect.w - 4, y = rect.y + rect.h - 5, i;

31 struct timespec now;

32 tab->loading = (tab->loading + 1) % (sizeof(off) / sizeof(*off));

33

34 clock_gettime(CLOCK_MONOTONIC, &now);

35 tab->loading = (now.tv_sec * 10 + now.tv_nsec / 100000000) %

36 (sizeof(off) / sizeof(*off));

37

38 for (i = 0; i < (int)(sizeof(off) / sizeof(*off)); i++) {

39 tb_set_cell(x + off[i][0], y + off[i][1], ' ', TB_WHITE,

40 i != tab->loading ? TB_WHITE : TB_BLUE);

41 }

42 }

43

44 void tab_display_update(struct request *req, struct rect rect) {

45 int error = parse_page(NULL, req, rect.w - rect.x);

46 if (error) {

47 req->error = error;

48 return;

49 }

50 request_scroll(req, 0, rect); /* fix scroll */

51 return;

52 }

53

54 void tab_display_gemtext(struct request *req, struct rect rect) {

55

56 if (!req) return;

57

58 if (req->length > config.maximumDisplayLength) {

59 tb_printf(rect.x + 2, rect.y + 1, TB_RED, TB_DEFAULT,

60 "The response is too large to be displayed : "

61 "%d bytes", req->length);

62 return;

63 }

64

65 #ifdef ENABLE_IMAGE

66 if (image_process && config.enableImage &&

67 req->page.mime == MIME_IMAGE) {

68 if (!req->page.img && !req->page.img_tried) {

69 int offset = req->page.offset;

70 req->page.img = image_parse(

71 &req->data[offset], req->length - offset,

72 &req->page.img_w, &req->page.img_h);

73 req->page.img_tried = 1;

74 }

75 if (req->page.img) {

76 image_display(req->page.img,

77 req->page.img_w, req->page.img_h, rect.y);

78 } else {

79 tb_printf(2, rect.y + 1, TB_RED, TB_DEFAULT,

80 "Failed to load the image");

81 }

82 return;

83 }

84 #endif

85 if (!config.enableHexViewer && req->page.mime != MIME_GEMTEXT &&

86 req->page.mime != MIME_GEMTEXT) {

87 tb_printf(2, rect.y + 1, TB_RED, TB_DEFAULT,

88 "Unable to display binary data.");

89 return;

90 }

91 if (req->page.width != rect.w - rect.x) {

92 /* TODO: should be done in the background */

93 tab_display_update(req, rect);

94 }

95 page_display(req->page, req->scroll, rect, req->selected);

96 }

97

98 void tab_display_error(struct tab *tab) {

99 if (!tab) return;

100 tab->request->state = STATE_ENDED;

101 tb_refresh();

102 tab_clean_requests(tab);

103 }

104

105 void tab_display_request(struct request *req, struct rect rect) {

106 if (!req) return;

107 switch (req->status) {

108 case GMI_SUCCESS:

109 tab_display_gemtext(req, rect);

110 break;

111 case GMI_INPUT:

112 case GMI_SECRET:

113 break;

114 default:

115 break;

116 }

117 }

118

119 void tab_display(struct tab *tab, struct client *client) {

120

121 struct rect rect;

122 struct request *req;

123

124 if (!tab || !tab->request) return;

125

126 rect = client_display_rect(client);

127

128 req = tab_completed(tab);

129 if (req) tab_display_request(req, rect);

130

131 if (client->mode != MODE_CMDLINE && tab->failure) {

132 tab->failure = 0;

133 client->error = 1;

134 snprintf(V(client->cmd), "%s", tab->error);

135 }

136

137 switch (tab->request->state) {

138 case STATE_COMPLETED:

139 tab_display_request(tab->view ?

140 tab->view : tab->request, rect);

141 break;

142 case STATE_FAILED:

143 tab_display_error(tab);

144 break;

145 case STATE_ONGOING:

146 tab_display_loading(tab, rect);

147 break;

148 }

149

150 }

151