summaryrefslogtreecommitdiff
path: root/src/fontpack.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fontpack.c')
-rw-r--r--src/fontpack.c120
1 files changed, 114 insertions, 6 deletions
diff --git a/src/fontpack.c b/src/fontpack.c
index a440234e..96006226 100644
--- a/src/fontpack.c
+++ b/src/fontpack.c
@@ -23,6 +23,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
23#include "fontpack.h" 23#include "fontpack.h"
24#include "resources.h" 24#include "resources.h"
25#include "ui/window.h" 25#include "ui/window.h"
26#include "gmrequest.h"
26#include "app.h" 27#include "app.h"
27 28
28#include <the_Foundation/archive.h> 29#include <the_Foundation/archive.h>
@@ -748,7 +749,7 @@ const iPtrArray *listSpecsByPriority_Fonts(void) {
748 return &fonts_.specOrder; 749 return &fonts_.specOrder;
749} 750}
750 751
751iString *infoText_FontPack(const iFontPack *d) { 752iString *infoText_FontPack(const iFontPack *d, iBool isFull) {
752 const iFontPack *installed = pack_Fonts(cstr_String(&d->id)); 753 const iFontPack *installed = pack_Fonts(cstr_String(&d->id));
753 const iBool isInstalled = (installed != NULL); 754 const iBool isInstalled = (installed != NULL);
754 const int installedVersion = installed ? installed->version : 0; 755 const int installedVersion = installed ? installed->version : 0;
@@ -757,9 +758,17 @@ iString *infoText_FontPack(const iFontPack *d) {
757 size_t sizeInBytes = 0; 758 size_t sizeInBytes = 0;
758 iPtrSet *uniqueFiles = new_PtrSet(); 759 iPtrSet *uniqueFiles = new_PtrSet();
759 iStringList *names = new_StringList(); 760 iStringList *names = new_StringList();
761 size_t numNames = 0;
762 iBool isAbbreviated = iFalse;
760 iConstForEach(PtrArray, i, listSpecs_FontPack(d)) { 763 iConstForEach(PtrArray, i, listSpecs_FontPack(d)) {
761 const iFontSpec *spec = i.ptr; 764 const iFontSpec *spec = i.ptr;
762 pushBack_StringList(names, &spec->name); 765 numNames++;
766 if (isFull || size_StringList(names) < 20) {
767 pushBack_StringList(names, &spec->name);
768 }
769 else {
770 isAbbreviated = iTrue;
771 }
763 iForIndices(j, spec->styles) { 772 iForIndices(j, spec->styles) {
764 insert_PtrSet(uniqueFiles, spec->styles[j]->sourceData.i); 773 insert_PtrSet(uniqueFiles, spec->styles[j]->sourceData.i);
765 } 774 }
@@ -777,11 +786,12 @@ iString *infoText_FontPack(const iFontPack *d) {
777 if (!endsWith_String(str, "(")) { 786 if (!endsWith_String(str, "(")) {
778 appendCStr_String(str, ", "); 787 appendCStr_String(str, ", ");
779 } 788 }
780 appendCStr_String(str, formatCStrs_Lang("num.fonts.n", size_StringList(names))); 789 appendCStr_String(str, formatCStrs_Lang("num.fonts.n", numNames));
781 } 790 }
782 appendFormat_String(str, ")"); 791 appendFormat_String(str, ")");
783 } 792 }
784 appendFormat_String(str, " \u2014 %s\n", cstrCollect_String(joinCStr_StringList(names, ", "))); 793 appendFormat_String(str, " \u2014 %s%s\n", cstrCollect_String(joinCStr_StringList(names, ", ")),
794 isAbbreviated ? ", ..." : "");
785 if (isInstalled && installedVersion != d->version) { 795 if (isInstalled && installedVersion != d->version) {
786 appendCStr_String(str, format_Lang("${fontpack.meta.version}\n", d->version)); 796 appendCStr_String(str, format_Lang("${fontpack.meta.version}\n", d->version));
787 } 797 }
@@ -945,7 +955,7 @@ const iString *infoPage_Fonts(iRangecc query) {
945 appendFormat_String(str, "### %s\n", 955 appendFormat_String(str, "### %s\n",
946 isEmpty_String(packId) ? "fonts.ini" : 956 isEmpty_String(packId) ? "fonts.ini" :
947 cstr_String(packId)); 957 cstr_String(packId));
948 append_String(str, collect_String(infoText_FontPack(pack))); 958 append_String(str, collect_String(infoText_FontPack(pack, iFalse)));
949 appendFormat_String(str, "=> %s ${fontpack.meta.viewfile}\n", 959 appendFormat_String(str, "=> %s ${fontpack.meta.viewfile}\n",
950 cstrCollect_String(makeFileUrl_String(&spec->sourcePath))); 960 cstrCollect_String(makeFileUrl_String(&spec->sourcePath)));
951 if (pack->isStandalone) { 961 if (pack->isStandalone) {
@@ -1018,6 +1028,7 @@ void install_Fonts(const iString *packId, const iBlock *data) {
1018 iRelease(f); 1028 iRelease(f);
1019 /* Newly installed fontpacks may have a higher priority that overrides other fonts. */ 1029 /* Newly installed fontpacks may have a higher priority that overrides other fonts. */
1020 reload_Fonts(); 1030 reload_Fonts();
1031 availableFontsChanged_App();
1021} 1032}
1022 1033
1023void installFontFile_Fonts(const iString *fileName, const iBlock *data) { 1034void installFontFile_Fonts(const iString *fileName, const iBlock *data) {
@@ -1028,6 +1039,7 @@ void installFontFile_Fonts(const iString *fileName, const iBlock *data) {
1028 } 1039 }
1029 iRelease(f); 1040 iRelease(f);
1030 reload_Fonts(); 1041 reload_Fonts();
1042 availableFontsChanged_App();
1031} 1043}
1032 1044
1033void enablePack_Fonts(const iString *packId, iBool enable) { 1045void enablePack_Fonts(const iString *packId, iBool enable) {
@@ -1040,6 +1052,7 @@ void enablePack_Fonts(const iString *packId, iBool enable) {
1040 } 1052 }
1041 updateActive_Fonts(); 1053 updateActive_Fonts();
1042 resetFonts_App(); 1054 resetFonts_App();
1055 availableFontsChanged_App();
1043 invalidate_Window(get_MainWindow()); 1056 invalidate_Window(get_MainWindow());
1044} 1057}
1045 1058
@@ -1047,5 +1060,100 @@ void updateActive_Fonts(void) {
1047 sortSpecs_Fonts_(&fonts_); 1060 sortSpecs_Fonts_(&fonts_);
1048} 1061}
1049 1062
1050iDefineClass(FontFile) 1063static void findCharactersInCMap_(iGmRequest *d, iGmRequest *req) {
1064 /* Note: Called in background thread. */
1065 iUnused(req);
1066 const iString *missingChars = userData_Object(d);
1067 if (isSuccess_GmStatusCode(status_GmRequest(d))) {
1068 iStringList *matchingPacks = new_StringList();
1069 iChar needed[20];
1070 iChar minChar = UINT32_MAX, maxChar = 0;
1071 size_t numNeeded = 0;
1072 iConstForEach(String, ch, missingChars) {
1073 needed[numNeeded++] = ch.value;
1074 minChar = iMin(minChar, ch.value);
1075 maxChar = iMax(maxChar, ch.value);
1076 if (numNeeded == iElemCount(needed)) {
1077 /* Shouldn't be that many. */
1078 break;
1079 }
1080 }
1081 iBlock *data = decompressGzip_Block(body_GmRequest(d));
1082 iRangecc line = iNullRange;
1083 while (nextSplit_Rangecc(range_Block(data), "\n", &line)) {
1084 iRangecc fontpackPath = iNullRange;
1085 for (const char *pos = line.start; pos < line.end; pos++) {
1086 if (*pos == ':') {
1087 fontpackPath.start = line.start;
1088 fontpackPath.end = pos;
1089 line.start = pos + 1;
1090 trimStart_Rangecc(&line);
1091 break;
1092 }
1093 }
1094 if (fontpackPath.start) {
1095 /* Parse the character ranges and see if any match what we need. */
1096 const char *pos = line.start;
1097 while (pos < line.end) {
1098 char *endp;
1099 uint32_t first = strtoul(pos, &endp, 10);
1100 uint32_t last = first;
1101 if (*endp == '-') {
1102 last = strtoul(endp + 1, &endp, 10);
1103 }
1104 if (maxChar < first) {
1105 break; /* The rest are even higher. */
1106 }
1107 if (minChar <= last) {
1108 for (size_t i = 0; i < numNeeded; i++) {
1109 if (needed[i] >= first && needed[i] <= last) {
1110 /* Got it. */
1111 pushBackRange_StringList(matchingPacks, fontpackPath);
1112 break;
1113 }
1114 }
1115 }
1116 pos = endp + 1;
1117 }
1118 }
1119 }
1120 delete_Block(data);
1121 iString result;
1122 init_String(&result);
1123 format_String(&result, "font.found chars:%s packs:", cstr_String(missingChars));
1124 iConstForEach(StringList, s, matchingPacks) {
1125 if (s.pos != 0) {
1126 appendCStr_String(&result, ",");
1127 }
1128 append_String(&result, s.value);
1129 }
1130 postCommandString_Root(NULL, &result);
1131 deinit_String(&result);
1132 iRelease(matchingPacks);
1133 }
1134 else {
1135 /* Report error. */
1136 postCommandf_Root(NULL,
1137 "font.found chars:%s error:%d msg:\x1b[1m%s\x1b[0m\n%s",
1138 cstr_String(missingChars),
1139 status_GmRequest(d),
1140 cstr_String(meta_GmRequest(d)),
1141 cstr_String(url_GmRequest(d)));
1142 }
1143// fflush(stdout);
1144 delete_String(userData_Object(d));
1145 /* We can't delete ourselves; threads must be joined from another thread. */
1146 SDL_PushEvent((SDL_Event *) &(SDL_UserEvent){
1147 .type = SDL_USEREVENT, .code = releaseObject_UserEventCode, .data1 = d });
1148}
1051 1149
1150void searchOnlineLibraryForCharacters_Fonts(const iString *chars) {
1151 /* Fetch the character map from skyjake.fi. */
1152 iGmRequest *req = new_GmRequest(certs_App());
1153 setUrl_GmRequest(req, collectNewCStr_String("gemini://skyjake.fi/fonts/cmap.txt.gz"));
1154 setUserData_Object(req, copy_String(chars));
1155 iConnect(GmRequest, req, finished, req, findCharactersInCMap_);
1156 submit_GmRequest(req);
1157}
1158
1159iDefineClass(FontFile)