// widgetTextInput.c — TextInput and TextArea widgets #include "widgetInternal.h" // ============================================================ // wgtTextArea // ============================================================ WidgetT *wgtTextArea(WidgetT *parent, int32_t maxLen) { WidgetT *w = widgetAlloc(parent, WidgetTextAreaE); if (w) { int32_t bufSize = maxLen > 0 ? maxLen + 1 : 256; w->as.textArea.buf = (char *)malloc(bufSize); w->as.textArea.bufSize = bufSize; if (w->as.textArea.buf) { w->as.textArea.buf[0] = '\0'; } } return w; } // ============================================================ // wgtTextInput // ============================================================ WidgetT *wgtTextInput(WidgetT *parent, int32_t maxLen) { WidgetT *w = widgetAlloc(parent, WidgetTextInputE); if (w) { int32_t bufSize = maxLen > 0 ? maxLen + 1 : 256; w->as.textInput.buf = (char *)malloc(bufSize); w->as.textInput.bufSize = bufSize; if (w->as.textInput.buf) { w->as.textInput.buf[0] = '\0'; } w->weight = 100; // text inputs stretch by default } return w; } // ============================================================ // widgetTextInputCalcMinSize // ============================================================ void widgetTextInputCalcMinSize(WidgetT *w, const BitmapFontT *font) { w->calcMinW = font->charWidth * 8 + TEXT_INPUT_PAD * 2; w->calcMinH = font->charHeight + TEXT_INPUT_PAD * 2; } // ============================================================ // widgetTextInputOnMouse // ============================================================ void widgetTextInputOnMouse(WidgetT *hit, WidgetT *root, int32_t vx) { hit->focused = true; // Place cursor at click position AppContextT *ctx = (AppContextT *)root->userData; const BitmapFontT *font = &ctx->font; int32_t relX = vx - hit->x - TEXT_INPUT_PAD; int32_t charPos = relX / font->charWidth + hit->as.textInput.scrollOff; if (charPos < 0) { charPos = 0; } if (charPos > hit->as.textInput.len) { charPos = hit->as.textInput.len; } hit->as.textInput.cursorPos = charPos; } // ============================================================ // widgetTextInputPaint // ============================================================ void widgetTextInputPaint(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, const ColorSchemeT *colors) { uint32_t fg = w->fgColor ? w->fgColor : colors->contentFg; uint32_t bg = w->bgColor ? w->bgColor : colors->contentBg; // Sunken border BevelStyleT bevel; bevel.highlight = colors->windowShadow; bevel.shadow = colors->windowHighlight; bevel.face = bg; bevel.width = 2; drawBevel(d, ops, w->x, w->y, w->w, w->h, &bevel); // Draw text if (w->as.textInput.buf) { int32_t textX = w->x + TEXT_INPUT_PAD; int32_t textY = w->y + (w->h - font->charHeight) / 2; int32_t maxChars = (w->w - TEXT_INPUT_PAD * 2) / font->charWidth; int32_t off = w->as.textInput.scrollOff; int32_t len = w->as.textInput.len - off; if (len > maxChars) { len = maxChars; } for (int32_t i = 0; i < len; i++) { drawChar(d, ops, font, textX + i * font->charWidth, textY, w->as.textInput.buf[off + i], fg, bg, true); } // Draw cursor if (w->focused) { int32_t cursorX = textX + (w->as.textInput.cursorPos - off) * font->charWidth; if (cursorX >= w->x + TEXT_INPUT_PAD && cursorX < w->x + w->w - TEXT_INPUT_PAD) { drawVLine(d, ops, cursorX, textY, font->charHeight, fg); } } } }