FCITX_EXPORT_API char* FcitxUIMessagesToCString(FcitxMessages* messages) { int length = 0; int i = 0; for (i = 0; i < FcitxMessagesGetMessageCount(messages) ; i ++) length += strlen(FcitxMessagesGetMessageString(messages, i)); char* str = fcitx_utils_malloc0(sizeof(char) * (length + 1)); for (i = 0; i < FcitxMessagesGetMessageCount(messages) ; i ++) strcat(str, FcitxMessagesGetMessageString(messages, i)); return str; }
char* FcitxUIMessagesToCStringForCommit(FcitxMessages* messages) { int length = 0; int i = 0; int count = FcitxMessagesGetMessageCount(messages); char *message_strs[count]; int msg_count = 0; for (i = 0;i < count;i++) { if ((FcitxMessagesGetClientMessageType(messages, i) & MSG_DONOT_COMMIT_WHEN_UNFOCUS) == 0) { char *msg_str = FcitxMessagesGetMessageString(messages, i); message_strs[msg_count++] = msg_str; length += strlen(msg_str); } } char* str = fcitx_utils_malloc0(sizeof(char) * (length + 1)); for (i = 0;i < msg_count;i++) { strcat(str, message_strs[i]); } return str; }
FCITX_EXPORT_API int FcitxUINewMessageToOldStyleMessage(FcitxInstance* instance, FcitxMessages* msgUp, FcitxMessages* msgDown) { int i = 0; FcitxInputState* input = instance->input; int extraLength = input->iCursorPos; FcitxMessagesSetMessageCount(msgUp, 0); FcitxMessagesSetMessageCount(msgDown, 0); for (i = 0; i < FcitxMessagesGetMessageCount(input->msgAuxUp) ; i ++) { FcitxMessagesAddMessageAtLast(msgUp, FcitxMessagesGetMessageType(input->msgAuxUp, i), "%s", FcitxMessagesGetMessageString(input->msgAuxUp, i)); extraLength += strlen(FcitxMessagesGetMessageString(input->msgAuxUp, i)); } for (i = 0; i < FcitxMessagesGetMessageCount(input->msgPreedit) ; i ++) FcitxMessagesAddMessageAtLast(msgUp, FcitxMessagesGetMessageType(input->msgPreedit, i), "%s", FcitxMessagesGetMessageString(input->msgPreedit, i)); for (i = 0; i < FcitxMessagesGetMessageCount(input->msgAuxDown) ; i ++) FcitxMessagesAddMessageAtLast(msgDown, FcitxMessagesGetMessageType(input->msgAuxDown, i), "%s", FcitxMessagesGetMessageString(input->msgAuxDown, i)); FcitxCandidateWord* candWord = NULL; for (candWord = FcitxCandidateWordGetCurrentWindow(input->candList), i = 0; candWord != NULL; candWord = FcitxCandidateWordGetCurrentWindowNext(input->candList, candWord), i ++) { char strTemp[3] = { '\0', '\0', '\0' }; strTemp[0] = FcitxCandidateWordGetChoose(input->candList)[i]; if (instance->config->bPointAfterNumber) strTemp[1] = '.'; unsigned int mod = FcitxCandidateWordGetModifier(input->candList); FcitxMessagesAddMessageAtLast(msgDown, MSG_INDEX, "%s%s%s%s%s", (mod & FcitxKeyState_Super) ? "M-" : "", (mod & FcitxKeyState_Ctrl) ? "C-" : "", (mod & FcitxKeyState_Alt) ? "A-" : "", (mod & FcitxKeyState_Shift) ? "S-" : "", strTemp); FcitxMessageType type = candWord->wordType; if (i == 0 && FcitxCandidateWordGetCurrentPage(input->candList) == 0 && type == MSG_OTHER && !FcitxInstanceGetContextBoolean(instance, CONTEXT_DISABLE_AUTO_FIRST_CANDIDATE_HIGHTLIGHT) ) type = MSG_FIRSTCAND; FcitxMessagesAddMessageAtLast(msgDown, type, "%s", candWord->strWord); if (candWord->strExtra && strlen(candWord->strExtra) != 0) FcitxMessagesAddMessageAtLast(msgDown, candWord->extraType, "%s", candWord->strExtra); FcitxMessagesAddMessageAtLast(msgDown, MSG_OTHER, " "); } return extraLength; }
char* FcitxUIMessagesToCStringForCommit(FcitxMessages* messages) { int length = 0; int i = 0; for (i = 0; i < FcitxMessagesGetMessageCount(messages) ; i ++) { if ((FcitxMessagesGetClientMessageType(messages, i) & MSG_DONOT_COMMIT_WHEN_UNFOCUS) == 0) length += strlen(FcitxMessagesGetMessageString(messages, i)); } char* str = fcitx_utils_malloc0(sizeof(char) * (length + 1)); for (i = 0; i < FcitxMessagesGetMessageCount(messages) ; i ++) { if ((FcitxMessagesGetClientMessageType(messages, i) & MSG_DONOT_COMMIT_WHEN_UNFOCUS) == 0) strcat(str, FcitxMessagesGetMessageString(messages, i)); } return str; }
FCITX_EXPORT_API int FcitxUINewMessageToOldStyleMessage(FcitxInstance* instance, FcitxMessages* msgUp, FcitxMessages* msgDown) { int i = 0; FcitxInputState* input = instance->input; int extraLength = input->iCursorPos; FcitxMessagesSetMessageCount(msgUp, 0); FcitxMessagesSetMessageCount(msgDown, 0); for (i = 0; i < FcitxMessagesGetMessageCount(input->msgAuxUp) ; i ++) { FcitxMessagesAddMessageAtLast(msgUp, FcitxMessagesGetMessageType(input->msgAuxUp, i), "%s", FcitxMessagesGetMessageString(input->msgAuxUp, i)); extraLength += strlen(FcitxMessagesGetMessageString(input->msgAuxUp, i)); } for (i = 0; i < FcitxMessagesGetMessageCount(input->msgPreedit) ; i ++) FcitxMessagesAddMessageAtLast(msgUp, FcitxMessagesGetMessageType(input->msgPreedit, i), "%s", FcitxMessagesGetMessageString(input->msgPreedit, i)); for (i = 0; i < FcitxMessagesGetMessageCount(input->msgAuxDown) ; i ++) FcitxMessagesAddMessageAtLast(msgDown, FcitxMessagesGetMessageType(input->msgAuxDown, i), "%s", FcitxMessagesGetMessageString(input->msgAuxDown, i)); FcitxCandidateWord* candWord = NULL; for (candWord = FcitxCandidateWordGetCurrentWindow(input->candList), i = 0; candWord != NULL; candWord = FcitxCandidateWordGetCurrentWindowNext(input->candList, candWord), i ++) { char strTemp[3] = { '\0', '\0', '\0' }; strTemp[0] = FcitxCandidateWordGetChoose(input->candList)[i]; if (instance->config->bPointAfterNumber) strTemp[1] = '.'; FcitxMessagesAddMessageAtLast(msgDown, MSG_INDEX, "%s", strTemp); FcitxMessageType type = candWord->wordType; if (i == 0 && FcitxCandidateWordGetCurrentPage(input->candList) == 0 && type == MSG_OTHER) type = MSG_FIRSTCAND; FcitxMessagesAddMessageAtLast(msgDown, type, "%s", candWord->strWord); if (candWord->strExtra && strlen(candWord->strExtra) != 0) FcitxMessagesAddMessageAtLast(msgDown, candWord->extraType, "%s", candWord->strExtra); FcitxMessagesAddMessageAtLast(msgDown, MSG_OTHER, " "); } return extraLength; }
FCITX_EXPORT_API char* FcitxUIMessagesToCString(FcitxMessages* messages) { int length = 0; int i = 0; int count = FcitxMessagesGetMessageCount(messages); char *message_strs[count]; int msg_count = 0; for (i = 0;i < count;i++) { char *msg_str = FcitxMessagesGetMessageString(messages, i); message_strs[msg_count++] = msg_str; length += strlen(msg_str); } char *str = fcitx_utils_malloc0(sizeof(char) * (length + 1)); for (i = 0;i < msg_count;i++) { strcat(str, message_strs[i]); } return str; }
void DrawInputBar(FcitxSkin* sc, InputWindow* inputWindow, int iCursorPos, FcitxMessages * msgup, FcitxMessages *msgdown , unsigned int * iheight, unsigned int *iwidth) { int i; char *strUp[MAX_MESSAGE_COUNT]; char *strDown[MAX_MESSAGE_COUNT]; int posUpX[MAX_MESSAGE_COUNT], posUpY[MAX_MESSAGE_COUNT]; int posDownX[MAX_MESSAGE_COUNT], posDownY[MAX_MESSAGE_COUNT]; int oldHeight = *iheight, oldWidth = *iwidth; int newHeight = 0, newWidth = 0; int cursor_pos = 0; int inputWidth = 0, outputWidth = 0; int outputHeight = 0; cairo_t *c = NULL; FcitxInputState* input = FcitxInstanceGetInputState(inputWindow->owner->owner); FcitxInstance* instance = inputWindow->owner->owner; FcitxClassicUI* classicui = inputWindow->owner; int iChar = iCursorPos; int strWidth = 0, strHeight = 0; SkinImage *inputimg, *prev, *next; inputimg = LoadImage(sc, sc->skinInputBar.backImg, false); prev = LoadImage(sc, sc->skinInputBar.backArrow, false); next = LoadImage(sc, sc->skinInputBar.forwardArrow, false); if (!FcitxMessagesIsMessageChanged(msgup) && !FcitxMessagesIsMessageChanged(msgdown)) return; inputWidth = 0; int dpi = sc->skinFont.respectDPI? classicui->dpi : 0; FCITX_UNUSED(dpi); #ifdef _ENABLE_PANGO /* special case which only macro unable to handle */ SetFontContext(dummy, inputWindow->owner->font, inputWindow->owner->fontSize > 0 ? inputWindow->owner->fontSize : sc->skinFont.fontSize, dpi); #endif int fontHeight = FontHeightWithContext(inputWindow->c_font[0], dpi); for (i = 0; i < FcitxMessagesGetMessageCount(msgup) ; i++) { char *trans = FcitxInstanceProcessOutputFilter(instance, FcitxMessagesGetMessageString(msgup, i)); if (trans) strUp[i] = trans; else strUp[i] = FcitxMessagesGetMessageString(msgup, i); posUpX[i] = sc->skinInputBar.marginLeft + inputWidth; StringSizeWithContext(inputWindow->c_font[FcitxMessagesGetMessageType(msgup, i)], dpi, strUp[i], &strWidth, &strHeight); if (sc->skinFont.respectDPI) posUpY[i] = sc->skinInputBar.marginTop + sc->skinInputBar.iInputPos; else posUpY[i] = sc->skinInputBar.marginTop + sc->skinInputBar.iInputPos - strHeight; inputWidth += strWidth; if (FcitxInputStateGetShowCursor(input)) { int length = strlen(FcitxMessagesGetMessageString(msgup, i)); if (iChar >= 0) { if (iChar < length) { char strTemp[MESSAGE_MAX_LENGTH]; char *strGBKT = NULL; strncpy(strTemp, strUp[i], iChar); strTemp[iChar] = '\0'; strGBKT = strTemp; StringSizeWithContext(inputWindow->c_font[FcitxMessagesGetMessageType(msgup, i)], dpi, strGBKT, &strWidth, &strHeight); cursor_pos = posUpX[i] + strWidth + 2; } iChar -= length; } } } if (iChar >= 0) cursor_pos = inputWidth + sc->skinInputBar.marginLeft; outputWidth = 0; outputHeight = 0; int currentX = 0; int offsetY; if (sc->skinFont.respectDPI) offsetY = sc->skinInputBar.marginTop + sc->skinInputBar.iInputPos + fontHeight + (FcitxMessagesGetMessageCount(msgdown) ? sc->skinInputBar.iOutputPos : 0); else offsetY = sc->skinInputBar.marginTop + sc->skinInputBar.iOutputPos - fontHeight; for (i = 0; i < FcitxMessagesGetMessageCount(msgdown) ; i++) { char *trans = FcitxInstanceProcessOutputFilter(instance, FcitxMessagesGetMessageString(msgdown, i)); if (trans) strDown[i] = trans; else strDown[i] = FcitxMessagesGetMessageString(msgdown, i); if (inputWindow->owner->bVerticalList) { /* vertical */ if (FcitxMessagesGetMessageType(msgdown, i) == MSG_INDEX) { if (currentX > outputWidth) outputWidth = currentX; if (i != 0) { currentX = 0; } } posDownX[i] = sc->skinInputBar.marginLeft + currentX; StringSizeWithContext(inputWindow->c_font[FcitxMessagesGetMessageType(msgdown, i)], dpi, strDown[i], &strWidth, &strHeight); if (FcitxMessagesGetMessageType(msgdown, i) == MSG_INDEX && i != 0) outputHeight += fontHeight + 2; currentX += strWidth; } else { /* horizontal */ posDownX[i] = sc->skinInputBar.marginLeft + outputWidth; StringSizeWithContext(inputWindow->c_font[FcitxMessagesGetMessageType(msgdown, i)], dpi, strDown[i], &strWidth, &strHeight); outputWidth += strWidth; } posDownY[i] = offsetY + outputHeight; } if (inputWindow->owner->bVerticalList && currentX > outputWidth) outputWidth = currentX; newHeight = offsetY + outputHeight + sc->skinInputBar.marginBottom + (FcitxMessagesGetMessageCount(msgdown) || !sc->skinFont.respectDPI ? fontHeight : 0); newWidth = (inputWidth < outputWidth) ? outputWidth : inputWidth; newWidth += sc->skinInputBar.marginLeft + sc->skinInputBar.marginRight; /* round to ROUND_SIZE in order to decrease resize */ newWidth = (newWidth / ROUND_SIZE) * ROUND_SIZE + ROUND_SIZE; if (inputWindow->owner->bVerticalList) { /* vertical */ newWidth = (newWidth < INPUT_BAR_VMIN_WIDTH) ? INPUT_BAR_VMIN_WIDTH : newWidth; } else { newWidth = (newWidth < INPUT_BAR_HMIN_WIDTH) ? INPUT_BAR_HMIN_WIDTH : newWidth; } *iwidth = newWidth; *iheight = newHeight; EnlargeCairoSurface(&inputWindow->cs_input_back, newWidth, newHeight); if (EnlargeCairoSurface(&inputWindow->cs_input_bar, newWidth, newHeight)) { LoadInputMessage(&classicui->skin, classicui->inputWindow, classicui->font); } if (oldHeight != newHeight || oldWidth != newWidth) { c = cairo_create(inputWindow->cs_input_back); DrawResizableBackground(c, inputimg->image, newHeight, newWidth, sc->skinInputBar.marginLeft, sc->skinInputBar.marginTop, sc->skinInputBar.marginRight, sc->skinInputBar.marginBottom, sc->skinInputBar.fillV, sc->skinInputBar.fillH ); cairo_destroy(c); } c = cairo_create(inputWindow->cs_input_bar); cairo_set_source_surface(c, inputWindow->cs_input_back, 0, 0); cairo_save(c); cairo_rectangle(c, 0, 0, newWidth, newHeight); cairo_set_operator(c, CAIRO_OPERATOR_SOURCE); cairo_clip(c); cairo_paint(c); cairo_restore(c); cairo_set_operator(c, CAIRO_OPERATOR_OVER); if (FcitxInputStateGetShowCursor(input)) { //画向前向后箭头 if (prev && next) { cairo_set_source_surface(inputWindow->c_back, prev->image, newWidth - sc->skinInputBar.iBackArrowX , sc->skinInputBar.iBackArrowY); if (FcitxCandidateWordHasPrev(FcitxInputStateGetCandidateList(input))) cairo_paint(inputWindow->c_back); else cairo_paint_with_alpha(inputWindow->c_back, 0.5); //画向前箭头 cairo_set_source_surface(inputWindow->c_back, next->image, newWidth - sc->skinInputBar.iForwardArrowX , sc->skinInputBar.iForwardArrowY); if (FcitxCandidateWordHasNext(FcitxInputStateGetCandidateList(input))) cairo_paint(inputWindow->c_back); else cairo_paint_with_alpha(inputWindow->c_back, 0.5); } } for (i = 0; i < FcitxMessagesGetMessageCount(msgup) ; i++) { OutputStringWithContext(inputWindow->c_font[FcitxMessagesGetMessageType(msgup, i)], dpi, strUp[i], posUpX[i], posUpY[i]); if (strUp[i] != FcitxMessagesGetMessageString(msgup, i)) free(strUp[i]); } for (i = 0; i < FcitxMessagesGetMessageCount(msgdown) ; i++) { OutputStringWithContext(inputWindow->c_font[FcitxMessagesGetMessageType(msgdown, i)], dpi, strDown[i], posDownX[i], posDownY[i]); if (strDown[i] != FcitxMessagesGetMessageString(msgdown, i)) free(strDown[i]); } int cursorY1, cursorY2; if (sc->skinFont.respectDPI) { cursorY1 = sc->skinInputBar.marginTop + sc->skinInputBar.iInputPos; cursorY2 = sc->skinInputBar.marginTop + sc->skinInputBar.iInputPos + fontHeight; } else { cursorY1 = sc->skinInputBar.marginTop + sc->skinInputBar.iInputPos - fontHeight - 4; cursorY2 = sc->skinInputBar.marginTop + sc->skinInputBar.iInputPos; } //画光标 if (FcitxInputStateGetShowCursor(input)) { cairo_move_to(inputWindow->c_cursor, cursor_pos, cursorY1); cairo_line_to(inputWindow->c_cursor, cursor_pos, cursorY2); cairo_stroke(inputWindow->c_cursor); } ResetFontContext(); cairo_destroy(c); FcitxMessagesSetMessageChanged(msgup, false); FcitxMessagesSetMessageChanged(msgdown, false); }
void InputWindowCalculateContentSize(FcitxXlibWindow* window, unsigned int* width, unsigned int* height) { InputWindow* inputWindow = (InputWindow*) window; FcitxInstance* instance = window->owner->owner; FcitxInputState* input = FcitxInstanceGetInputState(instance); FcitxCandidateWordList* candList = FcitxInputStateGetCandidateList(input); FcitxCandidateLayoutHint layout = FcitxCandidateWordGetLayoutHint(candList); FcitxClassicUI* classicui = window->owner; inputWindow->cursorPos = FcitxUINewMessageToOldStyleMessage(instance, inputWindow->msgUp, inputWindow->msgDown); boolean vertical = window->owner->bVerticalList; if (layout == CLH_Vertical) vertical = true; else if (layout == CLH_Horizontal) vertical = false; inputWindow->vertical = vertical; /* begin evalulation */ FcitxMessages* msgup = inputWindow->msgUp; FcitxMessages* msgdown = inputWindow->msgDown; FcitxSkin* sc = &classicui->skin; int i; FcitxRect* candRect = inputWindow->candRect; char **strUp = inputWindow->strUp; char **strDown = inputWindow->strDown; int *posUpX = inputWindow->posUpX, *posUpY = inputWindow->posUpY; int *posDownX = inputWindow->posDownX, *posDownY = inputWindow->posDownY; int newHeight = 0, newWidth = 0; int pixelCursorPos = 0; int inputWidth = 0, outputWidth = 0; int outputHeight = 0; int iChar = inputWindow->cursorPos; int strWidth = 0, strHeight = 0; inputWidth = 0; int dpi = sc->skinFont.respectDPI? classicui->dpi : 0; FCITX_UNUSED(dpi); FcitxCairoTextContext* ctc = FcitxCairoTextContextCreate(NULL); FcitxCairoTextContextSet(ctc, window->owner->font, window->owner->fontSize > 0 ? window->owner->fontSize : sc->skinFont.fontSize, dpi); int fontHeight = FcitxCairoTextContextFontHeight(ctc); inputWindow->fontHeight = fontHeight; for (i = 0; i < FcitxMessagesGetMessageCount(msgup) ; i++) { char *trans = FcitxInstanceProcessOutputFilter(instance, FcitxMessagesGetMessageString(msgup, i)); if (trans) strUp[i] = trans; else strUp[i] = FcitxMessagesGetMessageString(msgup, i); posUpX[i] = inputWidth; FcitxCairoTextContextStringSize(ctc, strUp[i], &strWidth, &strHeight); if (sc->skinFont.respectDPI) posUpY[i] = sc->skinInputBar.iInputPos + fontHeight - strHeight; else posUpY[i] = sc->skinInputBar.iInputPos - strHeight; inputWidth += strWidth; if (FcitxInputStateGetShowCursor(input)) { int length = strlen(FcitxMessagesGetMessageString(msgup, i)); if (iChar >= 0) { if (iChar < length) { char strTemp[MESSAGE_MAX_LENGTH]; char *strGBKT = NULL; strncpy(strTemp, strUp[i], iChar); strTemp[iChar] = '\0'; strGBKT = strTemp; FcitxCairoTextContextStringSize(ctc, strGBKT, &strWidth, &strHeight); // if the cursor is between two part, add extra pixel for pretty output pixelCursorPos = posUpX[i] + strWidth; } iChar -= length; } } } if (iChar >= 0) pixelCursorPos = inputWidth; inputWindow->pixelCursorPos = pixelCursorPos; outputWidth = 0; outputHeight = 0; int currentX = 0; int offsetY; if (sc->skinFont.respectDPI) offsetY = (FcitxMessagesGetMessageCount(msgup) ? (sc->skinInputBar.iInputPos + fontHeight) : 0) + (FcitxMessagesGetMessageCount(msgdown) ? sc->skinInputBar.iOutputPos : 0); else offsetY = sc->skinInputBar.iOutputPos - fontHeight; int candidateIndex = -1; int lastRightBottomX = 0, lastRightBottomY = 0; for (i = 0; i < FcitxMessagesGetMessageCount(msgdown) ; i++) { char *trans = FcitxInstanceProcessOutputFilter(instance, FcitxMessagesGetMessageString(msgdown, i)); if (trans) strDown[i] = trans; else strDown[i] = FcitxMessagesGetMessageString(msgdown, i); if (vertical) { /* vertical */ if (FcitxMessagesGetMessageType(msgdown, i) == MSG_INDEX) { if (currentX > outputWidth) outputWidth = currentX; if (i != 0) { currentX = 0; } } posDownX[i] = currentX; FcitxCairoTextContextStringSize(ctc, strDown[i], &strWidth, &strHeight); if (FcitxMessagesGetMessageType(msgdown, i) == MSG_INDEX && i != 0) outputHeight += fontHeight + 2; currentX += strWidth; } else { /* horizontal */ posDownX[i] = outputWidth; FcitxCairoTextContextStringSize(ctc, strDown[i], &strWidth, &strHeight); outputWidth += strWidth; } posDownY[i] = offsetY + outputHeight; if (FcitxMessagesGetMessageType(msgdown, i) == MSG_INDEX) { candidateIndex ++; if (candidateIndex > 0 && candidateIndex - 1 < 10) { candRect[candidateIndex - 1].x2 = lastRightBottomX; candRect[candidateIndex - 1].y2 = lastRightBottomY; } if (candidateIndex < 10) { candRect[candidateIndex].x1 = posDownX[i]; candRect[candidateIndex].y1 = posDownY[i]; } } lastRightBottomX = posDownX[i] + strWidth; lastRightBottomY = posDownY[i] + strHeight; } if (candidateIndex >= 0 && candidateIndex < 10) { candRect[candidateIndex].x2 = lastRightBottomX; candRect[candidateIndex].y2 = lastRightBottomY; } if (vertical && currentX > outputWidth) outputWidth = currentX; newHeight = offsetY + outputHeight + (FcitxMessagesGetMessageCount(msgdown) || !sc->skinFont.respectDPI ? fontHeight : 0); newWidth = (inputWidth < outputWidth) ? outputWidth : inputWidth; /* round to ROUND_SIZE in order to decrease resize */ newWidth = (newWidth / ROUND_SIZE) * ROUND_SIZE + ROUND_SIZE; if (vertical) { /* vertical */ newWidth = (newWidth < INPUT_BAR_VMIN_WIDTH) ? INPUT_BAR_VMIN_WIDTH : newWidth; } else { newWidth = (newWidth < INPUT_BAR_HMIN_WIDTH) ? INPUT_BAR_HMIN_WIDTH : newWidth; } FcitxCairoTextContextFree(ctc); *width = newWidth; *height = newHeight; }
void InputWindowPaint(FcitxXlibWindow* window, cairo_t* c) { InputWindow* inputWindow = (InputWindow*) window; FcitxClassicUI* classicui = window->owner; FcitxInstance* instance = classicui->owner; FcitxInputState* input = FcitxInstanceGetInputState(instance); FcitxCandidateWordList* candList = FcitxInputStateGetCandidateList(input); FcitxSkin* sc = &window->owner->skin; FcitxMessages* msgup = inputWindow->msgUp; FcitxMessages* msgdown = inputWindow->msgDown; char **strUp = inputWindow->strUp; char **strDown = inputWindow->strDown; int *posUpX = inputWindow->posUpX, *posUpY = inputWindow->posUpY; int *posDownX = inputWindow->posDownX, *posDownY = inputWindow->posDownY; cairo_save(c); cairo_set_operator(c, CAIRO_OPERATOR_OVER); SkinImage* prev = LoadImage(sc, sc->skinInputBar.backArrow, false); SkinImage* next = LoadImage(sc, sc->skinInputBar.forwardArrow, false); inputWindow->prevRect.x1 = inputWindow->prevRect.y1 = inputWindow->prevRect.x2 = inputWindow->prevRect.y2 = 0; inputWindow->nextRect.x1 = inputWindow->nextRect.y1 = inputWindow->nextRect.x2 = inputWindow->nextRect.y2 = 0; if (FcitxCandidateWordHasPrev(candList) || FcitxCandidateWordHasNext(candList) ) { if (prev && next) { int x, y; x = window->contentWidth - sc->skinInputBar.iBackArrowX + window->background->marginRight - window->background->marginLeft; y = sc->skinInputBar.iBackArrowY - window->background->marginTop; cairo_set_source_surface(c, prev->image, x, y); if (FcitxCandidateWordHasPrev(candList)) { inputWindow->prevRect.x1 = x; inputWindow->prevRect.y1 = y; inputWindow->prevRect.x2 = x + cairo_image_surface_get_width(prev->image); inputWindow->prevRect.y2 = y + cairo_image_surface_get_height(prev->image); if (inputWindow->highlight == PREVNEXT_HIGHLIGHT(true)) { cairo_paint_with_alpha(c, 0.7); } else { cairo_paint(c); } } else { cairo_paint_with_alpha(c, 0.3); } x = window->contentWidth - sc->skinInputBar.iForwardArrowX + window->background->marginRight - window->background->marginLeft; y = sc->skinInputBar.iForwardArrowY - window->background->marginTop; cairo_set_source_surface(c, next->image, x, y); if (FcitxCandidateWordHasNext(candList)) { inputWindow->nextRect.x1 = x; inputWindow->nextRect.y1 = y; inputWindow->nextRect.x2 = x + cairo_image_surface_get_width(prev->image); inputWindow->nextRect.y2 = y + cairo_image_surface_get_height(prev->image); if (inputWindow->highlight == PREVNEXT_HIGHLIGHT(false)) { cairo_paint_with_alpha(c, 0.7); } else { cairo_paint(c); } } else { cairo_paint_with_alpha(c, 0.3); } } } cairo_restore(c); cairo_save(c); /* draw text */ FcitxCairoTextContext* ctc = FcitxCairoTextContextCreate(c); int dpi = sc->skinFont.respectDPI? classicui->dpi : 0; FcitxCairoTextContextSet(ctc, window->owner->font, window->owner->fontSize > 0 ? window->owner->fontSize : sc->skinFont.fontSize, dpi); int i; for (i = 0; i < FcitxMessagesGetMessageCount(msgup) ; i++) { FcitxCairoTextContextOutputString(ctc, strUp[i], posUpX[i], posUpY[i], &sc->skinFont.fontColor[FcitxMessagesGetMessageType(msgup, i) % 7]); if (strUp[i] != FcitxMessagesGetMessageString(msgup, i)) free(strUp[i]); } int candidateIndex = -1; for (i = 0; i < FcitxMessagesGetMessageCount(msgdown) ; i++) { if (FcitxMessagesGetMessageType(msgdown, i) == MSG_INDEX) { candidateIndex ++; } FcitxConfigColor color = sc->skinFont.fontColor[FcitxMessagesGetMessageType(msgdown, i) % 7]; double alpha = 1.0; if (CANDIDATE_HIGHLIGHT(candidateIndex) == inputWindow->highlight) { /* cal highlight color */ color.r = (color.r + 0.5) / 2; color.g = (color.g + 0.5) / 2; color.b = (color.b + 0.5) / 2; alpha = 0.8; } cairo_set_source_rgba(c, color.r, color.g, color.b, alpha); FcitxCairoTextContextOutputString(ctc, strDown[i], posDownX[i], posDownY[i], NULL); if (strDown[i] != FcitxMessagesGetMessageString(msgdown, i)) free(strDown[i]); } FcitxCairoTextContextFree(ctc); cairo_restore(c); // draw cursor if (FcitxMessagesGetMessageCount(msgup) && FcitxInputStateGetShowCursor(input)) { cairo_save(c); int cursorY1, cursorY2; if (sc->skinFont.respectDPI) { cursorY1 = sc->skinInputBar.iInputPos; cursorY2 = sc->skinInputBar.iInputPos + inputWindow->fontHeight; } else { cursorY1 = sc->skinInputBar.iInputPos - inputWindow->fontHeight; cursorY2 = sc->skinInputBar.iInputPos; } fcitx_cairo_set_color(c, &sc->skinInputBar.cursorColor); cairo_set_line_width(c, 1); cairo_move_to(c, inputWindow->pixelCursorPos + 0.5, cursorY1); cairo_line_to(c, inputWindow->pixelCursorPos + 0.5, cursorY2); cairo_stroke(c); cairo_restore(c); } FcitxMessagesSetMessageChanged(msgup, false); FcitxMessagesSetMessageChanged(msgdown, false); }
void XimPreeditCallbackDraw(FcitxXimFrontend* xim, FcitxXimIC* ic, const char* preedit_string, int cursorPos) { XTextProperty tp; uint i, len; if (preedit_string == NULL) return; len = fcitx_utf8_strlen(preedit_string); if (len + 1 > xim->feedback_len) { xim->feedback_len = len + 1; if (xim->feedback) { xim->feedback = realloc(xim->feedback, sizeof(XIMFeedback) * xim->feedback_len); } else { xim->feedback = fcitx_utils_malloc0(sizeof(XIMFeedback) * xim->feedback_len); } } FcitxInputState* input = FcitxInstanceGetInputState(xim->owner); FcitxMessages* clientPreedit = FcitxInputStateGetClientPreedit(input); int offset = 0; for (i = 0; i < FcitxMessagesGetMessageCount(clientPreedit) ; i ++) { int type = FcitxMessagesGetClientMessageType(clientPreedit, i); char* str = FcitxMessagesGetMessageString(clientPreedit, i); int j = 0; XIMFeedback fb = 0; if ((type & MSG_NOUNDERLINE) == 0) fb |= XIMUnderline; if (type & MSG_HIGHLIGHT) fb |= XIMReverse; for (; j < fcitx_utf8_strlen(str); j++) { xim->feedback[offset] = fb; offset ++; } } xim->feedback[len] = 0; IMPreeditCBStruct* pcb = fcitx_utils_new(IMPreeditCBStruct); XIMText* text = fcitx_utils_new(XIMText); pcb->major_code = XIM_PREEDIT_DRAW; pcb->connect_id = ic->connect_id; pcb->icid = ic->id; pcb->todo.draw.caret = fcitx_utf8_strnlen(preedit_string, cursorPos); pcb->todo.draw.chg_first = 0; pcb->todo.draw.chg_length = ic->onspot_preedit_length; pcb->todo.draw.text = text; text->feedback = xim->feedback; Xutf8TextListToTextProperty(xim->display, (char **)&preedit_string, 1, XCompoundTextStyle, &tp); text->encoding_is_wchar = 0; text->length = strlen((char*)tp.value); text->string.multi_byte = (char*)tp.value; XimPendingCall(xim, XCT_CALLCALLBACK, (XPointer) pcb); ic->onspot_preedit_length = len; }