void guac_terminal_select_end(guac_terminal* terminal) { guac_client* client = terminal->client; guac_socket* socket = client->socket; /* If no text is selected, nothing to do */ if (!terminal->text_selected) return; /* Selection is now committed */ terminal->selection_committed = true; /* Reset current clipboard contents */ guac_common_clipboard_reset(terminal->clipboard, "text/plain"); int start_row, start_col; int end_row, end_col; /* Ensure proper ordering of start and end coords */ guac_terminal_select_normalized_range(terminal, &start_row, &start_col, &end_row, &end_col); /* If only one row, simply copy */ if (end_row == start_row) guac_terminal_clipboard_append_row(terminal, start_row, start_col, end_col); /* Otherwise, copy multiple rows */ else { /* Store first row */ guac_terminal_clipboard_append_row(terminal, start_row, start_col, -1); /* Store all middle rows */ for (int row = start_row + 1; row < end_row; row++) { guac_common_clipboard_append(terminal->clipboard, "\n", 1); guac_terminal_clipboard_append_row(terminal, row, 0, -1); } /* Store last row */ guac_common_clipboard_append(terminal->clipboard, "\n", 1); guac_terminal_clipboard_append_row(terminal, end_row, 0, end_col); } /* Send data */ if (!terminal->disable_copy) { guac_common_clipboard_send(terminal->clipboard, client); guac_socket_flush(socket); } guac_terminal_notify(terminal); }
void guac_vnc_cut_text(rfbClient* client, const char* text, int textlen) { guac_client* gc = rfbClientGetClientData(client, GUAC_VNC_CLIENT_KEY); guac_vnc_client* vnc_client = (guac_vnc_client*) gc->data; /* Ignore received text if outbound clipboard transfer is disabled */ if (vnc_client->settings->disable_copy) return; char received_data[GUAC_VNC_CLIPBOARD_MAX_LENGTH]; const char* input = text; char* output = received_data; guac_iconv_read* reader = vnc_client->clipboard_reader; /* Convert clipboard contents */ guac_iconv(reader, &input, textlen, GUAC_WRITE_UTF8, &output, sizeof(received_data)); /* Send converted data */ guac_common_clipboard_reset(vnc_client->clipboard, "text/plain"); guac_common_clipboard_append(vnc_client->clipboard, received_data, output - received_data); guac_common_clipboard_send(vnc_client->clipboard, gc); }
int guac_rdp_clipboard_blob_handler(guac_client* client, guac_stream* stream, void* data, int length) { rdp_guac_client_data* client_data = (rdp_guac_client_data*) client->data; guac_common_clipboard_append(client_data->clipboard, (char*) data, length); return 0; }
int guac_vnc_clipboard_blob_handler(guac_user* user, guac_stream* stream, void* data, int length) { /* Append new data */ guac_vnc_client* vnc_client = (guac_vnc_client*) user->client->data; guac_common_clipboard_append(vnc_client->clipboard, (char*) data, length); return 0; }
int guac_telnet_clipboard_blob_handler(guac_user* user, guac_stream* stream, void* data, int length) { /* Append new data */ guac_client* client = user->client; guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_common_clipboard_append(telnet_client->clipboard, data, length); return 0; }
/** * Appends the text within the given subsection of a terminal row to the * clipboard. The provided coordinates are considered inclusiveley (the * characters at the start and end column are included in the copied * text). Any out-of-bounds coordinates will be automatically clipped within * the bounds of the given row. * * @param terminal * The guac_terminal instance associated with the buffer containing the * text being copied and the clipboard receiving the copied text. * * @param row * The row number of the text within the terminal to be copied into the * clipboard, where the first (top-most) row in the terminal is row 0. Rows * within the scrollback buffer (above the top-most row of the terminal) * will be negative. * * @param start * The first column of the text to be copied from the given row into the * clipboard associated with the given terminal, where 0 is the first * (left-most) column within the row. * * @param end * The last column of the text to be copied from the given row into the * clipboard associated with the given terminal, where 0 is the first * (left-most) column within the row, or a negative value to denote that * the last column in the row should be used. */ static void guac_terminal_clipboard_append_row(guac_terminal* terminal, int row, int start, int end) { char buffer[1024]; int i = start; guac_terminal_buffer_row* buffer_row = guac_terminal_buffer_get_row(terminal->buffer, row, 0); /* If selection is entirely outside the bounds of the row, then there is * nothing to append */ if (start < 0 || start > buffer_row->length - 1) return; /* Clip given range to actual bounds of row */ if (end < 0 || end > buffer_row->length - 1) end = buffer_row->length - 1; /* Repeatedly convert chunks of terminal buffer rows until entire specified * region has been appended to clipboard */ while (i <= end) { int remaining = sizeof(buffer); char* current = buffer; /* Convert as many codepoints within the given range as possible */ for (i = start; i <= end; i++) { int codepoint = buffer_row->characters[i].value; /* Ignore null (blank) characters */ if (codepoint == 0 || codepoint == GUAC_CHAR_CONTINUATION) continue; /* Encode current codepoint as UTF-8 */ int bytes = guac_utf8_write(codepoint, current, remaining); if (bytes == 0) break; current += bytes; remaining -= bytes; } /* Append converted buffer to clipboard */ guac_common_clipboard_append(terminal->clipboard, buffer, current - buffer); } }
int guac_rdp_clipboard_end_handler(guac_client* client, guac_stream* stream) { rdp_guac_client_data* client_data = (rdp_guac_client_data*) client->data; rdpChannels* channels = client_data->rdp_inst->context->channels; RDP_CB_FORMAT_LIST_EVENT* format_list = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new( CliprdrChannel_Class, CliprdrChannel_FormatList, NULL, NULL); /* Terminate clipboard data with NULL */ guac_common_clipboard_append(client_data->clipboard, "", 1); /* Notify server that text data is now available */ format_list->formats = (UINT32*) malloc(sizeof(UINT32)); format_list->formats[0] = CB_FORMAT_TEXT; format_list->formats[1] = CB_FORMAT_UNICODETEXT; format_list->num_formats = 2; freerdp_channels_send_event(channels, (wMessage*) format_list); return 0; }
int ssh_guac_client_mouse_handler(guac_client* client, int x, int y, int mask) { ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data; guac_terminal* term = client_data->term; /* Determine which buttons were just released and pressed */ int released_mask = client_data->mouse_mask & ~mask; int pressed_mask = ~client_data->mouse_mask & mask; client_data->mouse_mask = mask; /* Show mouse cursor if not already shown */ if (client_data->current_cursor != client_data->ibar_cursor) { pthread_mutex_lock(&(term->lock)); client_data->current_cursor = client_data->ibar_cursor; guac_ssh_set_cursor(client, client_data->ibar_cursor); guac_socket_flush(client->socket); pthread_mutex_unlock(&(term->lock)); } /* Paste contents of clipboard on right or middle mouse button up */ if ((released_mask & GUAC_CLIENT_MOUSE_RIGHT) || (released_mask & GUAC_CLIENT_MOUSE_MIDDLE)) return guac_terminal_send_data(term, client_data->clipboard->buffer, client_data->clipboard->length); /* If text selected, change state based on left mouse mouse button */ if (term->text_selected) { pthread_mutex_lock(&(term->lock)); /* If mouse button released, stop selection */ if (released_mask & GUAC_CLIENT_MOUSE_LEFT) { int selected_length; /* End selection and get selected text */ int selectable_size = term->term_width * term->term_height * sizeof(char); char* string = malloc(selectable_size); guac_terminal_select_end(term, string); selected_length = strnlen(string, selectable_size); /* Store new data */ guac_common_clipboard_reset(client_data->clipboard, "text/plain"); guac_common_clipboard_append(client_data->clipboard, string, selected_length); free(string); /* Send data */ guac_common_clipboard_send(client_data->clipboard, client); guac_socket_flush(client->socket); } /* Otherwise, just update */ else guac_terminal_select_update(term, y / term->display->char_height - term->scroll_offset, x / term->display->char_width); pthread_mutex_unlock(&(term->lock)); } /* Otherwise, if mouse button pressed AND moved, start selection */ else if (!(pressed_mask & GUAC_CLIENT_MOUSE_LEFT) && mask & GUAC_CLIENT_MOUSE_LEFT) { pthread_mutex_lock(&(term->lock)); guac_terminal_select_start(term, y / term->display->char_height - term->scroll_offset, x / term->display->char_width); pthread_mutex_unlock(&(term->lock)); } /* Scroll up if wheel moved up */ if (released_mask & GUAC_CLIENT_MOUSE_SCROLL_UP) { pthread_mutex_lock(&(term->lock)); guac_terminal_scroll_display_up(term, GUAC_SSH_WHEEL_SCROLL_AMOUNT); pthread_mutex_unlock(&(term->lock)); } /* Scroll down if wheel moved down */ if (released_mask & GUAC_CLIENT_MOUSE_SCROLL_DOWN) { pthread_mutex_lock(&(term->lock)); guac_terminal_scroll_display_down(term, GUAC_SSH_WHEEL_SCROLL_AMOUNT); pthread_mutex_unlock(&(term->lock)); } return 0; }