_Bool edit_mmove(EDIT *edit, int px, int py, int width, int height, int x, int y, int dx, int dy) { if(utox_window_baseline && py > utox_window_baseline - font_small_lineheight - 4 * SCALE) { y += py - (utox_window_baseline - font_small_lineheight - 4 * SCALE); py = utox_window_baseline - font_small_lineheight - 4 * SCALE; } _Bool need_redraw = 0; _Bool mouseover = inrect(x, y, 0, 0, width - (edit->multiline ? SCROLL_WIDTH : 0), height); if(mouseover) { cursor = CURSOR_TEXT; } if(mouseover != edit->mouseover) { edit->mouseover = mouseover; if(edit != active_edit) { need_redraw = 1; } } if(edit->multiline) { need_redraw |= scroll_mmove(edit->scroll, px, py, width, height, x, y, dx, dy); y += scroll_gety(edit->scroll, height); } if(edit == active_edit && edit_select) { if (edit->select_completely) { edit_setfocus(edit); need_redraw = 1; return need_redraw; } setfont(FONT_TEXT); edit_sel.p2 = hittextmultiline(x - 2 * SCALE, width - 4 * SCALE - (edit->multiline ? SCROLL_WIDTH : 0), y - 2 * SCALE, INT_MAX, font_small_lineheight, edit->data, edit->length, edit->multiline); STRING_IDX start, length; if(edit_sel.p2 > edit_sel.p1) { start = edit_sel.p1; length = edit_sel.p2 - edit_sel.p1; } else { start = edit_sel.p2; length = edit_sel.p1 - edit_sel.p2; } if(start != edit_sel.start || length != edit_sel.length) { edit_sel.start = start; edit_sel.length = length; need_redraw = 1; } } else if(mouseover) { setfont(FONT_TEXT); edit->mouseover_char = hittextmultiline(x - 2 * SCALE, width - 4 * SCALE - (edit->multiline ? SCROLL_WIDTH : 0), y - 2 * SCALE, INT_MAX, font_small_lineheight, edit->data, edit->length, edit->multiline); } return need_redraw; }
uint16_t text_linedown(int width, int height, uint16_t p, uint16_t lineheight, char_t *str, uint16_t length, SCROLLABLE *scroll) { //lazy int x, y; textxy(width, p, lineheight, str, length, &x, &y); y += lineheight; if(scroll->content_height > height) { double d1 = (double)y / (double)(scroll->content_height - height); double d2 = (double)(y - height + lineheight) / (double)(scroll->content_height - height); if(d2 > scroll->d) { scroll->d = d2 > 1.0 ? 1.0 : d2; } else if(d1 < scroll->d) { scroll->d = d1; } } return hittextmultiline(x, width, y, INT_MAX, lineheight, str, length, 1); }
_Bool messages_mmove(MESSAGES *m, int UNUSED(px), int UNUSED(py), int width, int UNUSED(height), int mx, int my, int dx, int UNUSED(dy)) { if(m->idown < m->data->n) { int maxwidth = width - MESSAGES_X - TIME_WIDTH; MSG_IMG *img_down = m->data->data[m->idown]; if((img_down->msg_type == MSG_TYPE_IMAGE) && (img_down->w > maxwidth)) { img_down->position -= (double)dx / (double)(img_down->w - maxwidth); if(img_down->position > 1.0) { img_down->position = 1.0; } else if(img_down->position < 0.0) { img_down->position = 0.0; } cursor = CURSOR_ZOOM_OUT; return 1; } } if(mx < 0 || my < 0 || (uint32_t) my > m->data->height) { if(m->iover != MSG_IDX_MAX) { m->iover = MSG_IDX_MAX; return 1; } return 0; } setfont(FONT_TEXT); void **p = m->data->data; MSG_IDX i = 0, n = m->data->n; _Bool need_redraw = 0; while(i != n) { MESSAGE *msg = *p++; int dy = msg->height; if(my >= 0 && my < dy) { switch(msg->msg_type) { case MSG_TYPE_TEXT: case MSG_TYPE_ACTION_TEXT: { /* normal message */ m->over = hittextmultiline(mx - MESSAGES_X, width - MESSAGES_X - TIME_WIDTH, my < 0 ? 0 : my, msg->height, font_small_lineheight, msg->msg, msg->length, 1); _Bool prev_urlmdown = m->urlmdown; if (m->urlover != STRING_IDX_MAX) { m->urlmdown = 0; m->urlover = STRING_IDX_MAX; } if(my < 0 || my >= dy || mx < MESSAGES_X || m->over == msg->length) { break; } cursor = CURSOR_TEXT; char_t *str = msg->msg + m->over; while(str != msg->msg) { str--; if(*str == ' ' || *str == '\n') { str++; break; } } char_t *end = msg->msg + msg->length; while(str != end && *str != ' ' && *str != '\n') { if(( str == msg->msg || *(str - 1) == '\n' || *(str - 1) == ' ') && (m->urlover == STRING_IDX_MAX && end - str >= 7 && strcmp2(str, "http://") == 0)) { cursor = CURSOR_HAND; m->urlover = str - msg->msg; } if(( str == msg->msg || *(str - 1) == '\n' || *(str - 1) == ' ') && (m->urlover == STRING_IDX_MAX && end - str >= 8 && strcmp2(str, "https://") == 0)) { cursor = CURSOR_HAND; m->urlover = str - msg->msg; } str++; } if(m->urlover != STRING_IDX_MAX) { m->urllen = (str - msg->msg) - m->urlover; m->urlmdown = prev_urlmdown; } break; } case MSG_TYPE_IMAGE: { m->over = 0; MSG_IMG *img = (void*)msg; int maxwidth = width - MESSAGES_X - TIME_WIDTH; if(img->w > maxwidth) { mx -= MESSAGES_X; int w = img->w > maxwidth ? maxwidth : img->w; int h = (img->zoom || img->w <= maxwidth) ? img->h : img->h * maxwidth / img->w; if(mx >= 0 && my >= 0 && mx < w && my < h) { m->over = 1; cursor = CURSOR_ZOOM_IN + img->zoom; } } break; } case MSG_TYPE_FILE: { uint8_t over = 0; MSG_FILE *file = (void*)msg; mx -= MESSAGES_X; if(mx >= 0 && mx < BM_FT_WIDTH && my >= 0 && my < BM_FT_HEIGHT) { over = 3; mx -= BM_FTM_WIDTH + SCALE; if(mx >= 0) { if(my < BM_FTB_HEIGHT + SCALE) { // mouse is over the upper button (cancel) over = 1; } else if(my >= BM_FTB_HEIGHT + SCALE * 2) { // mouse is over the lower button (pause / accept) over = 2; } } } static const uint8_t f[16] = { 0b011, 0b001, 0b011, 0b011, 0b011, 0b011, 0b001, 0b001, 0b001, 0b001, 0b001, 0b001, 0b000, 0b000, 0b111, 0b111, }; if(over && f[file->status * 2 + file->author] & (1 << (over - 1))) { cursor = CURSOR_HAND; } if(over != m->over) { need_redraw = 1; m->over = over; } break; } } if((i != m->iover) && (m->iover != MSG_IDX_MAX) && ((msg->msg_type == MSG_TYPE_FILE) || (((MESSAGE*)(m->data->data[m->iover]))->msg_type == MSG_TYPE_FILE))) { need_redraw = 1; // Redraw file on hover-in/out. } m->iover = i; if(m->select) { MSG_IDX istart, iend; STRING_IDX start, end; if(i > m->idown) { istart = m->idown; iend = i; start = m->down; end = m->over; } else if(i < m->idown) { iend = m->idown; istart = i; end = m->down; start = m->over; } else { istart = iend = i; if(m->over >= m->down) { start = m->down; end = m->over; } else { end = m->down; start = m->over; } } if(start != m->data->start || istart != m->data->istart || end != m->data->end || iend != m->data->iend) { m->data->start = start; m->data->end = end; m->data->istart = istart; m->data->iend = iend; need_redraw = 1; } } return need_redraw; } my -= dy; i++; } return 0; }