📄 fserve.c
字号:
/* send the request */ req.reqType = FS_QueryXBitmaps16; req.fid = ((FSFontDataPtr) pfont->fpePrivate)->fontid; req.format = pfont->format; if (pfont->info.terminalFont) req.format = req.format & ~(BitmapFormatImageRectMask) | BitmapFormatImageRectMax; req.range = TRUE; /* each range takes up 4 bytes */ req.length = (SIZEOF(fsQueryXBitmaps16Req) >> 2) + nranges; req.num_ranges = nranges * 2; /* protocol wants count of fsChar2bs */ _fs_add_req_log(conn, FS_QueryXBitmaps16); _fs_write(conn, (char *) &req, SIZEOF(fsQueryXBitmaps16Req)); /* Send ranges to the server... pack into a char array by hand to avoid structure-packing portability problems and to handle swapping for version1 protocol */ if (nranges) {#define RANGE_BUFFER_SIZE 64#define RANGE_BUFFER_SIZE_MASK 63 int i; char range_buffer[RANGE_BUFFER_SIZE * 4]; char *range_buffer_p; range_buffer_p = range_buffer; for (i = 0; i < nranges;) { if (conn->fsMajorVersion > 1) { *range_buffer_p++ = ranges[i].min_char_high; *range_buffer_p++ = ranges[i].min_char_low; *range_buffer_p++ = ranges[i].max_char_high; *range_buffer_p++ = ranges[i].max_char_low; } else { *range_buffer_p++ = ranges[i].min_char_low; *range_buffer_p++ = ranges[i].min_char_high; *range_buffer_p++ = ranges[i].max_char_low; *range_buffer_p++ = ranges[i].max_char_high; } if (!(++i & RANGE_BUFFER_SIZE_MASK)) { _fs_write(conn, range_buffer, RANGE_BUFFER_SIZE * 4); range_buffer_p = range_buffer; } } if (i &= RANGE_BUFFER_SIZE_MASK) _fs_write(conn, range_buffer, i * 4); } return Suspended;}intfs_load_all_glyphs(pfont) FontPtr pfont;{ extern pointer serverClient; /* This could be any number that doesn't conflict with existing client values. */ int err; FSFpePtr conn = (FSFpePtr) pfont->fpe->private; /* * The purpose of this procedure is to load all glyphs in the event * that we're dealing with someone who doesn't understand the finer * points of glyph caching... it is called from _fs_get_glyphs() if * the latter is called to get glyphs that have not yet been loaded. * We assume that the caller will not know how to handle a return * value of Suspended (usually the case for a GetGlyphs() caller), * so this procedure hangs around, freezing the server, for the * request to complete. This is an unpleasant kluge called to * perform an unpleasant job that, we hope, will never be required. */ while ((err = _fs_load_glyphs(serverClient, pfont, TRUE, 0, 0, NULL)) == Suspended) { fd_set TempSelectMask; if (_fs_wait_for_readable(conn) == -1) { /* We lost our connection. Don't wait to reestablish it; just give up. */ _fs_connection_died(conn); /* Get rid of blockrec */ fs_client_died(serverClient, pfont->fpe); return BadCharRange; /* As good an error as any other */ } FD_SET(conn->fs_fd, &TempSelectMask); fs_wakeup(pfont->fpe, &TempSelectMask); } return err;}int_fs_load_glyphs(client, pfont, range_flag, nchars, item_size, data) pointer client; FontPtr pfont; Bool range_flag; unsigned int nchars; int item_size; unsigned char *data;{ int nranges = 0; fsRange *ranges = NULL; int res; FSBlockDataPtr blockrec; FSBlockedGlyphPtr blockedglyph; FSFpePtr conn = (FSFpePtr) pfont->fpe->private; FSClientsDependingPtr *clients_depending = NULL; /* see if the result is already there */ blockrec = (FSBlockDataPtr) conn->blocked_requests; while (blockrec) { if (blockrec->type == FS_LOAD_GLYPHS) { blockedglyph = (FSBlockedGlyphPtr) blockrec->data; if (blockedglyph->pfont == pfont) { if (blockrec->client == client) { if (blockedglyph->done) { int errcode = blockedglyph->errcode; signal_clients_depending(&blockedglyph-> clients_depending); _fs_remove_block_rec(conn, blockrec); return errcode; } else return Suspended; } /* We've found an existing LoadGlyphs blockrec for this font but for another client. Rather than build a blockrec for it now (which entails some complex maintenance), we'll add it to a queue of clients to be signalled when the existing LoadGlyphs is completed. */ clients_depending = &blockedglyph->clients_depending; break; } } else if (blockrec->type == FS_OPEN_FONT) { FSBlockedFontPtr bfont; bfont = (FSBlockedFontPtr) blockrec->data; if (bfont->pfont == pfont) { if (blockrec->client == client) { if (bfont->state == FS_DONE_REPLY) { int errcode = bfont->errcode; signal_clients_depending(&bfont->clients_depending); _fs_remove_block_rec(conn, blockrec); if (errcode == Successful) break; else return errcode; } else return Suspended; } /* We've found an existing OpenFont blockrec for this font but for another client. Rather than build a blockrec for it now (which entails some complex maintenance), we'll add it to a queue of clients to be signalled when the existing OpenFont is completed. */ if (bfont->state != FS_DONE_REPLY) { clients_depending = &bfont->clients_depending; break; } } } blockrec = blockrec->next; } /* * see if the desired glyphs already exist, and return Successful if they * do, otherwise build up character range/character string */ res = fs_build_range(pfont, range_flag, nchars, item_size, data, &nranges, &ranges); switch (res) { case AccessDone: return Successful; case Successful: break; default: return res; } /* * If clients_depending is not null, this request must wait for * some prior request(s) to complete. */ if (clients_depending) { /* Since we're not ready to send the load_glyphs request yet, clean up the damage (if any) caused by the fs_build_range() call. */ if (nranges) { _fs_clean_aborted_loadglyphs(pfont, nranges, ranges); xfree(ranges); } return add_clients_depending(clients_depending, client); } /* * If fsd->generation != conn->generation, the font has been closed * due to a lost connection. We will reopen it, which will result * in one of three things happening: * 1) The open will succeed and obtain the same font. Life * is wonderful. * 2) The open will fail. There is code above to recognize this * and flunk the LoadGlyphs request. The client might not be * thrilled. * 3) Worst case: the open will succeed but the font we open will * be different. The fs_read_query_info() procedure attempts * to detect this by comparing the existing metrics and * properties against those of the reopened font... if they * don't match, we flunk the reopen, which eventually results * in flunking the LoadGlyphs request. We could go a step * further and compare the extents, but this should be * sufficient. */ if (((FSFontDataPtr)pfont->fpePrivate)->generation != conn->generation) { /* Since we're not ready to send the load_glyphs request yet, clean up the damage caused by the fs_build_range() call. */ _fs_clean_aborted_loadglyphs(pfont, nranges, ranges); xfree(ranges); /* Now try to reopen the font. */ return fs_send_open_font(client, (FontPathElementPtr)0, (Mask)FontReopen, (char *)0, 0, (fsBitmapFormat)0, (fsBitmapFormatMask)0, (XID)0, &pfont); } return fs_send_load_glyphs(client, pfont, nranges, ranges);}static intfs_read_list(fpe, blockrec) FontPathElementPtr fpe; FSBlockDataPtr blockrec;{ FSBlockedListPtr blist = (FSBlockedListPtr) blockrec->data; FSFpePtr conn = (FSFpePtr) fpe->private; fsListFontsReply rep; char *data, *dp; int length, i; blist->done = TRUE; /* read reply header */ memcpy(&rep, &blockrec->header, SIZEOF(fsGenericReply)); if (rep.type == FS_Error) {/* XXX -- translate FS error */ _fs_eat_rest_of_error(conn, (fsError *) & rep); return AllocError; } if (_fs_read(conn, (char *) &rep + SIZEOF(fsGenericReply), SIZEOF(fsListFontsReply) - SIZEOF(fsGenericReply)) == -1) { /* nothing to free (i think) */ return StillWorking; } length = (rep.length << 2) - SIZEOF(fsListFontsReply); data = (char *) xalloc(length); if (!data) { _fs_drain_bytes_pad(conn, length); return AllocError; } /* read the list */ if (_fs_read_pad(conn, data, length) == -1) { /* nothing to free (i think) */ return StillWorking; } /* copy data into FontPathRecord */ dp = data; for (i = 0; i < rep.nFonts; i++) { length = *(unsigned char *)dp++; if (AddFontNamesName(blist->names, dp, length) != Successful) { blist->errcode = AllocError; break; } dp += length; } xfree(data); return Successful;}static intfs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames) pointer client; FontPathElementPtr fpe; char *pattern; int patlen; int maxnames; FontNamesPtr newnames;{ FSBlockDataPtr blockrec; FSBlockedListPtr blockedlist; FSFpePtr conn = (FSFpePtr) fpe->private; fsListFontsReq req; _fs_client_access (conn, client, FALSE); _fs_client_resolution(conn); /* make a new block record, and add it to the end of the list */ blockrec = fs_new_block_rec(fpe, client, FS_LIST_FONTS); if (!blockrec) return AllocError; blockedlist = (FSBlockedListPtr) blockrec->data; blockedlist->patlen = patlen; blockedlist->errcode = Successful; blockedlist->names = newnames; blockedlist->done = FALSE; /* send the request */ req.reqType = FS_ListFonts; req.maxNames = maxnames; req.nbytes = patlen; req.length = (SIZEOF(fsListFontsReq) + patlen + 3) >> 2; _fs_add_req_log(conn, FS_ListFonts); _fs_write(conn, (char *) &req, SIZEOF(fsListFontsReq)); _fs_write_pad(conn, (char *) pattern, patlen);#ifdef NCD if (configData.ExtendedFontDiags) { char buf[256]; memcpy(buf, pattern, MIN(256, patlen)); buf[MIN(256, patlen)] = '\0'; printf("Listing fonts on pattern \"%s\" from font server \"%s\"\n", buf, fpe->name); }#endif return Suspended;}static intfs_list_fonts(client, fpe, pattern, patlen, maxnames, newnames) pointer client; FontPathElementPtr fpe; char *pattern; int patlen; int maxnames; FontNamesPtr newnames;{ FSBlockDataPtr blockrec; FSBlockedListPtr blockedlist; FSFpePtr conn = (FSFpePtr) fpe->private; int err; /* see if the result is already there */ blockrec = (FSBlockDataPtr) conn->blocked_requests; while (blockrec) { if (blockrec->type == FS_LIST_FONTS && blockrec->client == client) { blockedlist = (FSBlockedListPtr) blockrec->data; if (blockedlist->patlen == patlen && blockedlist->done) { err = blockedlist->errcode; _fs_remove_block_rec(conn, blockrec); return err; } } blockrec = blockrec->next; } /* didn't find waiting record, so send a new one */ return fs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames);}static int padlength[4] = {0, 3, 2, 1};static intfs_read_list_info(fpe, blockrec) FontPathElementPtr fpe; FSBlockDataPtr blockrec;{ FSBlockedListInfoPtr binfo = (FSBlockedListInfoPtr) blockrec->data; fsListFontsWithXInfoReply rep; FSFpePtr conn = (FSFpePtr) fpe->private; fsPropInfo pi; fsPropOffset *po; char *name; pointer pd; int err; /* clean up anything from the last trip */ if (binfo->name) { xfree(binfo->name); binfo->name = NULL; } if (binfo->pfi) { xfree(binfo->pfi->isStringProp); xfree(binfo->pfi->props); xfree(binfo->pfi); binfo->pfi = NULL; } /* get reply header */ memcpy(&rep, &blockrec->header, SIZEOF(fsGenericReply)); if (rep.type == FS_Error) {/* XXX -- translate FS error */ _fs_eat_rest_of_error(conn, (fsError *) & rep); binfo->errcode = AllocError; return AllocError; } if (conn->fsMajorVersion > 1) if (rep.nameLength == 0) goto done; /* old protocol sent a full-length reply even for the last one */ if (_fs_read(conn, (char *) &rep + SIZEOF(fsGenericReply), SIZEOF(fsListFontsWithXInfoReply) - SIZEOF(fsGenericReply)) == -1) { goto done; } if (rep.nameLength == 0) goto done; /* read the data */ name = (char *) xalloc(rep.nameLength); binfo->pfi = (FontInfoPtr) xalloc(sizeof(FontInfoRec)); if (!name || !binfo->pfi) { xfree(name); xfree(binfo->pfi); binfo->pfi = NULL; _fs_drain_bytes(conn, rep.length - (SIZEOF(fsListFontsWithXInfoReply) - SIZEOF(fsGenericReply))); binfo->errcode = AllocError; return AllocError; } if (conn->fsMajorVersion == 1) if (_fs_read_pad(conn, name, rep.nameLength) == -1) goto done; if (_fs_read_pad(conn, (char *) &pi, SIZEOF(fsPropInfo)) == -1) goto done; po = (fsPropOffset *) xalloc(SIZEOF(fsPropOffset) * pi.num_offsets); pd = (pointer) xalloc(pi.data_len); if (!po || !pd) { xfree(name); xfree(po); xfree(pd); xfree (binfo->pfi); binfo->pfi = NULL; binfo->errcode = AllocError; return AllocError; } err = _fs_read_pad(conn, (char *) po, (pi.num_offsets * SIZEOF(fsPropOffset))); if (err != -1) { if (conn->fsMajorVersion > 1) err = _fs_read(conn, (char *) pd, pi.data_len); else err = _fs_read_pad(conn, (char *) pd, pi.data_len); } if (err != -1 && conn->fsMajorVersion != 1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -