SC_FUNC int scan_utf8(FILE *fp,const char *filename) { #if defined NO_UTF8 return 0; #else void *resetpos=sc_getpossrc(fp); int utf8=TRUE; int firstchar=TRUE,bom_found=FALSE; const unsigned char *ptr; while (utf8 && sc_readsrc(fp,pline,sLINEMAX)!=NULL) { ptr=pline; if (firstchar) { /* check whether the very first character on the very first line * starts with a BYTE order mark */ cell c=get_utf8_char(ptr,&ptr); bom_found= (c==0xfeff); utf8= (c>=0); firstchar=FALSE; } /* if */ while (utf8 && *ptr!='\0') utf8= (get_utf8_char(ptr,&ptr)>=0); } /* while */ sc_resetsrc(fp,resetpos); if (bom_found) { unsigned char bom[3]; if (!utf8) error(77,filename); /* malformed UTF-8 encoding */ sc_readsrc(fp,bom,3); assert(bom[0]==0xef && bom[1]==0xbb && bom[2]==0xbf); } /* if */ return utf8; #endif /* NO_UTF8 */ }
SC_FUNC int scan_utf8(FILE *fp,const char *filename) { static void *resetpos=NULL; int utf8=TRUE; int firstchar=TRUE,bom_found=FALSE; const unsigned char *ptr; resetpos=pc_getpossrc(fp,resetpos); while (utf8 && pc_readsrc(fp,srcline,sLINEMAX)!=NULL) { ptr=srcline; // if (firstchar) { // /* check whether the very first character on the very first line // * starts with a byte order mark (BOM) // */ // cell c=get_utf8_char(ptr,&ptr); // bom_found= (c==0xfeff); // utf8= (c>=0); // firstchar=FALSE; // } /* if */ while (utf8 && *ptr!='\0') utf8= (get_utf8_char(ptr,&ptr)>=0); } /* while */ pc_resetsrc(fp,resetpos); if (bom_found) { unsigned char bom[3]; pc_readsrc(fp,bom,3); /* read the BOM again to strip it from the file */ assert(bom[0]==0xef && bom[1]==0xbb && bom[2]==0xbf); if (!utf8) error(77,filename); /* malformed UTF-8 encoding */ } /* if */ return utf8; }
void TtfFont::printText(const std::string &text, int32_t x, int32_t y, float Red, float Green, float Blue, float Alpha, uint32_t fontSize) { SDL_assert_release(g_ft); if(text.empty()) return; uint32_t offsetX = 0; uint32_t offsetY = 0; const char *strIt = text.c_str(); const char *strEnd = strIt + text.size(); for(; strIt < strEnd; strIt++) { const char &cx = *strIt; UTF8 ucx = static_cast<unsigned char>(cx); switch(cx) { case '\n': offsetX = 0; offsetY += (fontSize * 1.5); continue; case '\t': //Fake tabulation offsetX += offsetX + offsetX % uint32_t(fontSize * 1.5); continue; // case ' ': // offsetX += m_spaceWidth + m_interLetterSpace / 2; // continue; } TheGlyph &glyph = getGlyph(fontSize, get_utf8_char(&cx)); GlRenderer::setTextureColor(Red, Green, Blue, Alpha); int32_t glyph_x = x + static_cast<int32_t>(offsetX); int32_t glyph_y = y + static_cast<int32_t>(offsetY + fontSize); GlRenderer::renderTexture(glyph.tx, static_cast<float>(glyph_x + glyph.left), static_cast<float>(glyph_y - glyph.top), glyph.width, glyph.height ); offsetX += uint32_t(glyph.advance>>6); strIt += static_cast<size_t>(trailingBytesForUTF8[ucx]); } }
static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line, int subline, int ypos, int max) { INDENT_FUNC indent_func; LINE_CACHE_REC *cache; const unsigned char *text, *end, *text_newline; unsigned char *tmp; int xpos, color, drawcount, first, need_move, need_clrtoeol, char_width; if (view->dirty) /* don't bother drawing anything - redraw is coming */ return 0; cache = textbuffer_view_get_line_cache(view, line); if (subline >= cache->count) return 0; color = ATTR_RESET; need_move = TRUE; need_clrtoeol = FALSE; xpos = drawcount = 0; first = TRUE; text_newline = text = subline == 0 ? line->text : cache->lines[subline-1].start; for (;;) { if (text == text_newline) { if (need_clrtoeol && xpos < term_width) { term_set_color(view->window, ATTR_RESET); term_clrtoeol(view->window); } if (first) first = FALSE; else { ypos++; if (--max == 0) break; } if (subline > 0) { /* continuing previous line - indent it */ indent_func = cache->lines[subline-1].indent_func; if (indent_func == NULL) xpos = cache->lines[subline-1].indent; color = cache->lines[subline-1].color; } else { indent_func = NULL; } if (xpos == 0 && indent_func == NULL) need_clrtoeol = TRUE; else { /* line was indented - need to clear the indented area first */ term_set_color(view->window, ATTR_RESET); term_move(view->window, 0, ypos); term_clrtoeol(view->window); if (indent_func != NULL) xpos = indent_func(view, line, ypos); } if (need_move || xpos > 0) term_move(view->window, xpos, ypos); term_set_color(view->window, color); if (subline == cache->count-1) { text_newline = NULL; need_move = FALSE; } else { /* get the beginning of the next subline */ text_newline = cache->lines[subline].start; need_move = !cache->lines[subline].continues; } drawcount++; subline++; } if (*text == '\0') { /* command */ text++; if (*text == LINE_CMD_EOL || *text == LINE_CMD_FORMAT) break; if (*text == LINE_CMD_CONTINUE) { /* jump to next block */ memcpy(&tmp, text+1, sizeof(unsigned char *)); text = tmp; continue; } else if (*text == LINE_CMD_INDENT_FUNC) { text += sizeof(INDENT_FUNC); } else { update_cmd_color(*text, &color); term_set_color(view->window, color); } text++; continue; } end = text; if (view->utf8) { unichar chr; if (get_utf8_char(&end, 6, &chr)<0) char_width = 1; else char_width = utf8_width(chr); } else { if (term_type == TERM_TYPE_BIG5 && is_big5(end[0], end[1])) char_width = 2; else char_width = 1; end += char_width-1; } xpos += char_width; if (xpos <= term_width) { if (*text >= 32 && (end != text || (*text & 127) >= 32)) { for (; text < end; text++) term_addch(view->window, *text); term_addch(view->window, *text); } else { /* low-ascii */ term_set_color(view->window, ATTR_RESET|ATTR_REVERSE); term_addch(view->window, (*text & 127)+'A'-1); term_set_color(view->window, color); } } text++; } if (need_clrtoeol && xpos < term_width) { term_set_color(view->window, ATTR_RESET); term_clrtoeol(view->window); } return drawcount; }
static LINE_CACHE_REC * view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line) { INDENT_FUNC indent_func; LINE_CACHE_REC *rec; LINE_CACHE_SUB_REC *sub; GSList *lines; unsigned char cmd; const unsigned char *ptr, *next_ptr, *last_space_ptr; int xpos, pos, indent_pos, last_space, last_color, color, linecount; int char_len; unichar chr; g_return_val_if_fail(line->text != NULL, NULL); color = ATTR_RESETFG | ATTR_RESETBG; xpos = 0; indent_pos = view->default_indent; last_space = last_color = 0; last_space_ptr = NULL; sub = NULL; indent_func = view->default_indent_func; linecount = 1; lines = NULL; for (ptr = line->text;;) { if (*ptr == '\0') { /* command */ ptr++; cmd = *ptr; ptr++; if (cmd == LINE_CMD_EOL || cmd == LINE_CMD_FORMAT) break; if (cmd == LINE_CMD_CONTINUE) { unsigned char *tmp; memcpy(&tmp, ptr, sizeof(char *)); ptr = tmp; continue; } if (cmd == LINE_CMD_INDENT) { /* set indentation position here - don't do it if we're too close to right border */ if (xpos < view->width-5) indent_pos = xpos; } else if (cmd == LINE_CMD_INDENT_FUNC) { memcpy(&indent_func, ptr, sizeof(INDENT_FUNC)); ptr += sizeof(INDENT_FUNC); if (indent_func == NULL) indent_func = view->default_indent_func; } else update_cmd_color(cmd, &color); continue; } if (!view->utf8) { /* MH */ if (term_type != TERM_TYPE_BIG5 || ptr[1] == '\0' || !is_big5(ptr[0], ptr[1])) char_len = 1; else char_len = 2; next_ptr = ptr+char_len; } else { char_len = 1; while (ptr[char_len] != '\0' && char_len < 6) char_len++; next_ptr = ptr; if (get_utf8_char(&next_ptr, char_len, &chr) < 0) char_len = 1; else char_len = utf8_width(chr); next_ptr++; } if (xpos + char_len > view->width && sub != NULL && (last_space <= indent_pos || last_space <= 10) && view->longword_noindent) { /* long word, remove the indentation from this line */ xpos -= sub->indent; sub->indent = 0; } if (xpos + char_len > view->width) { xpos = indent_func == NULL ? indent_pos : indent_func(view, line, -1); sub = g_new0(LINE_CACHE_SUB_REC, 1); if (last_space > indent_pos && last_space > 10) { /* go back to last space */ color = last_color; ptr = last_space_ptr; while (*ptr == ' ') ptr++; } else if (view->longword_noindent) { /* long word, no indentation in next line */ xpos = 0; sub->continues = TRUE; } sub->start = ptr; sub->indent = xpos; sub->indent_func = indent_func; sub->color = color; lines = g_slist_append(lines, sub); linecount++; last_space = 0; continue; } if (!view->utf8 && char_len > 1) { last_space = xpos; last_space_ptr = next_ptr; last_color = color; } else if (*ptr == ' ') { last_space = xpos; last_space_ptr = ptr; last_color = color; } xpos += char_len; ptr = next_ptr; } rec = g_malloc(sizeof(LINE_CACHE_REC)-sizeof(LINE_CACHE_SUB_REC) + sizeof(LINE_CACHE_SUB_REC) * (linecount-1)); rec->last_access = time(NULL); rec->count = linecount; if (rec->count > 1) { for (pos = 0; lines != NULL; pos++) { void *data = lines->data; memcpy(&rec->lines[pos], data, sizeof(LINE_CACHE_SUB_REC)); lines = g_slist_remove(lines, data); g_free(data); } } g_hash_table_insert(view->cache->line_cache, line, rec); return rec; }
PGE_Size TtfFont::textSize(std::string &text, uint32_t max_line_lenght, bool cut, uint32_t fontSize) { SDL_assert_release(g_ft); if(text.empty()) return PGE_Size(0, 0); size_t lastspace = 0; //!< index of last found space character size_t count = 1; //!< Count of lines uint32_t maxWidth = 0; //!< detected maximal width of message uint32_t widthSumm = 0; uint32_t widthSummMax = 0; if(cut) { std::string::size_type i = text.find('\n'); if(i != std::string::npos) text.erase(i, text.size() - i); } /****************Word wrap*********************/ uint32_t x = 0; for(size_t i = 0; i < text.size(); i++, x++) { char &cx = text[i]; UTF8 uch = static_cast<unsigned char>(cx); switch(cx) { case '\r': break; case '\t': { //Fake tabulation size_t space = (4 * fontSize); widthSumm += (space - ((widthSumm / space) % 4)); if(widthSumm > widthSummMax) widthSummMax = widthSumm; break; } case '\n': { lastspace = 0; if((maxWidth < x) && (maxWidth < max_line_lenght)) maxWidth = x; x = 0; widthSumm = 0; count++; break; } default: { if(' ' == cx) lastspace = x; TheGlyph &glyph = getGlyph(fontSize, get_utf8_char(&cx)); widthSumm += uint32_t(glyph.advance>>6); if(widthSumm > widthSummMax) widthSummMax = widthSumm; break; } }//Switch if((max_line_lenght > 0) && (x >= max_line_lenght)) //If lenght more than allowed { maxWidth = x; if(lastspace > 0) { text[lastspace] = '\n'; i = lastspace - 1; lastspace = 0; } else { text.insert(i, 1, '\n'); x = 0; count++; } } i += static_cast<size_t>(trailingBytesForUTF8[uch]); } if(count == 1) maxWidth = static_cast<uint32_t>(text.length()); /****************Word wrap*end*****************/ return PGE_Size(static_cast<int32_t>(widthSummMax), static_cast<int32_t>((fontSize * 1.5) * count)); }