/* * Class: com_sun_glass_ui_gtk_GtkSystemClipboard * Method: dispose * Signature: ()V */ JNIEXPORT void JNICALL Java_com_sun_glass_ui_gtk_GtkSystemClipboard_dispose (JNIEnv *env, jobject obj) { g_signal_handler_disconnect(G_OBJECT(get_clipboard()), owner_change_handler_id); env->DeleteGlobalRef(jclipboard); owner_change_handler_id = 0; jclipboard = NULL; }
static jobject get_data_text(JNIEnv *env) { gchar *data = gtk_clipboard_wait_for_text(get_clipboard()); if (data == NULL) { return NULL; } jstring jdata = env->NewStringUTF(data); g_free(data); return jdata; }
/* * Class: com_sun_glass_ui_gtk_GtkSystemClipboard * Method: init * Signature: ()V */ JNIEXPORT void JNICALL Java_com_sun_glass_ui_gtk_GtkSystemClipboard_init (JNIEnv *env, jobject obj) { if (jclipboard) { ERROR0("GtkSystemClipboard already initiated"); } jclipboard = env->NewGlobalRef(obj); owner_change_handler_id = g_signal_connect(G_OBJECT(get_clipboard()), "owner-change", G_CALLBACK(clipboard_owner_changed_callback), jclipboard); }
static void window_copy (GSimpleAction *action, GVariant *parameter, gpointer user_data) { GtkWindow *window = GTK_WINDOW (user_data); GtkTextView *text = g_object_get_data ((GObject*)window, "plugman-text"); gtk_text_buffer_copy_clipboard (gtk_text_view_get_buffer (text), get_clipboard ((GtkWidget*) text)); }
/* * Class: com_sun_glass_ui_gtk_GtkSystemClipboard * Method: pushToSystem * Signature: (Ljava/util/HashMap;I)V */ JNIEXPORT void JNICALL Java_com_sun_glass_ui_gtk_GtkSystemClipboard_pushToSystem (JNIEnv * env, jobject obj, jobject data, jint supported) { GtkTargetEntry* targets = NULL; gint ntargets; data = env->NewGlobalRef(data); init_atoms(); data_to_targets(env, data, &targets, &ntargets); CHECK_JNI_EXCEPTION(env) if (targets) { gtk_clipboard_set_with_data(get_clipboard(), targets, ntargets, set_data_func, clear_data_func, data); gtk_target_table_free(targets, ntargets); } else { // targets == NULL means that we want to clear clipboard. // Passing NULL as targets parameter to gtk_clipboard_set_with_data will produce Gtk-CRITICAL assertion // but passing 0 as n_targets parameter allows to set empty list of available mime types GtkTargetEntry dummy_targets = {(gchar*) "MIME_DUMMY_TARGET", 0, 0}; gtk_clipboard_set_with_data(get_clipboard(), &dummy_targets, 0, set_data_func, clear_data_func, data); } is_clipboard_updated_by_glass = TRUE; }
static void window_paste (GSimpleAction *action, GVariant *parameter, gpointer user_data) { GtkWindow *window = GTK_WINDOW (user_data); GtkTextView *text = g_object_get_data ((GObject*)window, "bloatpad-text"); gtk_text_buffer_paste_clipboard (gtk_text_view_get_buffer (text), get_clipboard ((GtkWidget*) text), NULL, TRUE); }
static jobject get_data_image(JNIEnv* env) { GdkPixbuf* pixbuf; guchar *data; jbyteArray data_array; jobject buffer, result; int w,h,stride; pixbuf = gtk_clipboard_wait_for_image(get_clipboard()); if (pixbuf == NULL) { return NULL; } if (!gdk_pixbuf_get_has_alpha(pixbuf)) { GdkPixbuf *tmp_buf = gdk_pixbuf_add_alpha(pixbuf, FALSE, 0, 0, 0); g_object_unref(pixbuf); pixbuf = tmp_buf; } w = gdk_pixbuf_get_width(pixbuf); h = gdk_pixbuf_get_height(pixbuf); stride = gdk_pixbuf_get_rowstride(pixbuf); data = gdk_pixbuf_get_pixels(pixbuf); //Actually, we are converting RGBA to BGRA, but that's the same operation data = (guchar*) convert_BGRA_to_RGBA((int*)data, stride, h); data_array = env->NewByteArray(stride*h); EXCEPTION_OCCURED(env); env->SetByteArrayRegion(data_array, 0, stride*h, (jbyte*)data); EXCEPTION_OCCURED(env); buffer = env->CallStaticObjectMethod(jByteBufferCls, jByteBufferWrap, data_array); result = env->NewObject(jGtkPixelsCls, jGtkPixelsInit, w, h, buffer); EXCEPTION_OCCURED(env); g_free(data); g_object_unref(pixbuf); return result; }
static jobject get_data_raw(JNIEnv *env, const char* mime, gboolean string_data) { GtkSelectionData *data; const guchar *raw_data; jsize length; jbyteArray array; jobject result = NULL; data = gtk_clipboard_wait_for_contents(get_clipboard(), gdk_atom_intern(mime, FALSE)); if (data != NULL) { raw_data = glass_gtk_selection_data_get_data_with_length(data, &length); if (string_data) { result = env->NewStringUTF((const char*)raw_data); } else { array = env->NewByteArray(length); env->SetByteArrayRegion(array, 0, length, (const jbyte*)raw_data); result = env->CallStaticObjectMethod(jByteBufferCls, jByteBufferWrap, array); } gtk_selection_data_free(data); } return result; }
/* * Class: com_sun_glass_ui_gtk_GtkSystemClipboard * Method: mimesFromSystem * Signature: ()[Ljava/lang/String; */ JNIEXPORT jobjectArray JNICALL Java_com_sun_glass_ui_gtk_GtkSystemClipboard_mimesFromSystem (JNIEnv * env, jobject obj) { GdkAtom *targets; gint ntargets; gint i; GdkAtom *convertible; GdkAtom *convertible_ptr; gchar *name; jobjectArray result; jstring tmpString; init_atoms(); gtk_clipboard_wait_for_targets(get_clipboard(), &targets, &ntargets); convertible = (GdkAtom*) glass_try_malloc0_n(ntargets * 2, sizeof(GdkAtom)); //theoretically, the number can double if (!convertible) { if (ntargets > 0) { glass_throw_oom(env, "Failed to allocate mimes"); } g_free(targets); return NULL; } convertible_ptr = convertible; bool uri_list_added = false; bool text_added = false; bool image_added = false; for (i = 0; i < ntargets; ++i) { //handle text targets //if (targets[i] == TEXT_TARGET || targets[i] == STRING_TARGET || targets[i] == UTF8_STRING_TARGET) { if (gtk_targets_include_text(targets + i, 1) && !text_added) { *(convertible_ptr++) = MIME_TEXT_PLAIN_TARGET; text_added = true; } else if (gtk_targets_include_image(targets + i, 1, TRUE) && !image_added) { *(convertible_ptr++) = MIME_JAVA_IMAGE; image_added = true; } //TODO text/x-moz-url ? RT-17802 if (targets[i] == MIME_TEXT_URI_LIST_TARGET) { if (uri_list_added) { continue; } gchar** uris = gtk_clipboard_wait_for_uris(get_clipboard()); if (uris) { guint size = g_strv_length(uris); guint files_cnt = get_files_count(uris); if (files_cnt) { *(convertible_ptr++) = MIME_FILES_TARGET; } if (size - files_cnt) { *(convertible_ptr++) = MIME_TEXT_URI_LIST_TARGET; } g_strfreev(uris); } uri_list_added = true; } else { *(convertible_ptr++) = targets[i]; } } result = env->NewObjectArray(convertible_ptr - convertible, jStringCls, NULL); for (i = 0; convertible + i < convertible_ptr; ++i) { name = gdk_atom_name(convertible[i]); tmpString = env->NewStringUTF(name); env->SetObjectArrayElement(result, (jsize)i, tmpString); g_free(name); } g_free(targets); g_free(convertible); return result; }
static jobject get_data_uri_list(JNIEnv *env, gboolean files) { return uris_to_java(env, gtk_clipboard_wait_for_uris(get_clipboard()), files); }
void cTextField::handleInput(cKey key) { changeMade = true; bool select = mod_contains(key.mod, mod_shift); bool haveSelection = insertionPoint != selectionPoint; key = divineFunction(key); TextStyle style; style.font = FONT_PLAIN; style.pointSize = 12; size_t new_ip; std::string contents = getText(); if(current_action && hist_timer.getElapsedTime().asSeconds() > 5.0f) history.add(current_action), current_action.reset(); hist_timer.restart(); if(!key.spec) { if(haveSelection) { cKey deleteKey = key; deleteKey.spec = true; deleteKey.k = key_bsp; handleInput(deleteKey); contents = getText(); } if(aTextInsert* ins = dynamic_cast<aTextInsert*>(current_action.get())) ins->append(key.c); else { if(current_action) history.add(current_action); aTextInsert* new_ins = new aTextInsert(*this, insertionPoint); new_ins->append(key.c); current_action.reset(new_ins); } contents.insert(contents.begin() + insertionPoint, char(key.c)); selectionPoint = ++insertionPoint; } else switch(key.k) { case key_enter: break; // Shouldn't be receiving this anyway // TODO: Implement all the other special keys case key_left: case key_word_left: if(current_action) history.add(current_action), current_action.reset(); if(haveSelection && !select) { selectionPoint = insertionPoint = std::min(selectionPoint,insertionPoint); break; } new_ip = select ? selectionPoint : insertionPoint; if(new_ip == 0) break; if(key.k == key_word_left) { new_ip--; while(new_ip > 0 && contents[new_ip - 1] != ' ') new_ip--; } else new_ip--; (select ? selectionPoint : insertionPoint) = new_ip; if(!select) selectionPoint = insertionPoint; break; case key_right: case key_word_right: if(current_action) history.add(current_action), current_action.reset(); if(haveSelection && !select) { selectionPoint = insertionPoint = std::max(selectionPoint,insertionPoint); break; } new_ip = select ? selectionPoint : insertionPoint; if(new_ip == contents.length()) break; if(key.k == key_word_right) { new_ip++; while(new_ip < contents.length() && contents[new_ip] != ' ') new_ip++; } else new_ip++; (select ? selectionPoint : insertionPoint) = new_ip; if(!select) selectionPoint = insertionPoint; break; case key_up: if(current_action) history.add(current_action), current_action.reset(); if(haveSelection && !select) selectionPoint = insertionPoint = std::min(selectionPoint,insertionPoint); if(snippets[ip_row].at.y == snippets[0].at.y) { key.k = key_top; if(select) key.mod += mod_shift; handleInput(key); } else { int x = snippets[ip_row].at.x + ip_col, y = snippets[ip_row].at.y - 10; set_ip(loc(x,y), select ? &cTextField::selectionPoint : &cTextField::insertionPoint); if(!select) selectionPoint = insertionPoint; } break; case key_down: if(current_action) history.add(current_action), current_action.reset(); if(haveSelection && !select) selectionPoint = insertionPoint = std::max(selectionPoint,insertionPoint); if(snippets[ip_row].at.y == snippets.back().at.y) { key.k = key_bottom; if(select) key.mod += mod_shift; handleInput(key); } else { int x = snippets[ip_row].at.x + ip_col, y = snippets[ip_row].at.y + 20; set_ip(loc(x,y), select ? &cTextField::selectionPoint : &cTextField::insertionPoint); if(!select) selectionPoint = insertionPoint; } break; case key_bsp: case key_word_bsp: case key_del: case key_word_del: if(haveSelection) { if(key.k == key_word_bsp) handleInput({true, key_word_left, mod_shift}); else if(key.k == key_word_del) handleInput({true, key_word_right, mod_shift}); auto begin = contents.begin() + std::min(selectionPoint, insertionPoint); auto end = contents.begin() + std::max(selectionPoint, insertionPoint); std::string removed(begin, end); auto result = contents.erase(begin, end); bool dir = insertionPoint < selectionPoint; selectionPoint = insertionPoint = result - contents.begin(); if(current_action) history.add(current_action), current_action.reset(); history.add(action_ptr(new aTextDelete(*this, std::min(selectionPoint, insertionPoint), removed, dir))); } else if(key.k == key_word_bsp) { cKey selectKey = key; selectKey.k = key_word_left; selectKey.mod = mod_shift; key.k = key_bsp; handleInput(selectKey); if(selectionPoint != insertionPoint) handleInput(key); return; } else if(key.k == key_bsp) { if(insertionPoint == 0) break; char c = contents[insertionPoint - 1]; contents.erase(insertionPoint - 1,1); selectionPoint = --insertionPoint; if(aTextDelete* del = dynamic_cast<aTextDelete*>(current_action.get())) del->append_front(c); else { if(current_action) history.add(current_action); aTextDelete* new_del = new aTextDelete(*this, insertionPoint + 1, insertionPoint + 1); new_del->append_front(c); current_action.reset(new_del); } } else if(key.k == key_word_del) { cKey selectKey = key; selectKey.k = key_word_right; selectKey.mod = mod_shift; key.k = key_del; handleInput(selectKey); if(selectionPoint != insertionPoint) handleInput(key); return; } else if(key.k == key_del) { if(insertionPoint == contents.length()) break; char c = contents[insertionPoint]; contents.erase(insertionPoint,1); if(aTextDelete* del = dynamic_cast<aTextDelete*>(current_action.get())) del->append_back(c); else { if(current_action) history.add(current_action); aTextDelete* new_del = new aTextDelete(*this, insertionPoint, insertionPoint); new_del->append_back(c); current_action.reset(new_del); } } break; case key_top: if(current_action) history.add(current_action), current_action.reset(); if(!select) insertionPoint = 0; selectionPoint = 0; break; case key_bottom: if(current_action) history.add(current_action), current_action.reset(); if(!select) insertionPoint = contents.length(); selectionPoint = contents.length(); break; case key_end: if(current_action) history.add(current_action), current_action.reset(); new_ip = snippets[ip_row].at.x + string_length(snippets[ip_row].text, style); set_ip(loc(new_ip, snippets[ip_row].at.y), select ? &cTextField::selectionPoint : &cTextField::insertionPoint); if(!select) selectionPoint = insertionPoint; break; case key_home: if(current_action) history.add(current_action), current_action.reset(); set_ip(snippets[ip_row].at, select ? &cTextField::selectionPoint : &cTextField::insertionPoint); if(!select) selectionPoint = insertionPoint; break; case key_pgup: if(current_action) history.add(current_action), current_action.reset(); if(snippets[ip_row].at.y != snippets[0].at.y) { int x = snippets[ip_row].at.x + ip_col, y = frame.top + 2; set_ip(loc(x,y), select ? &cTextField::selectionPoint : &cTextField::insertionPoint); if(!select) selectionPoint = insertionPoint; } break; case key_pgdn: if(current_action) history.add(current_action), current_action.reset(); if(snippets[ip_row].at.y != snippets.back().at.y) { int x = snippets[ip_row].at.x + ip_col, y = frame.bottom - 2; set_ip(loc(x,y), select ? &cTextField::selectionPoint : &cTextField::insertionPoint); if(!select) selectionPoint = insertionPoint; } break; case key_copy: case key_cut: if(current_action) history.add(current_action), current_action.reset(); set_clipboard(contents.substr(std::min(insertionPoint,selectionPoint), abs(insertionPoint - selectionPoint))); if(key.k == key_cut) { cKey deleteKey = key; deleteKey.k = key_bsp; handleInput(deleteKey); contents = getText(); } break; case key_paste: if(current_action) history.add(current_action), current_action.reset(); if(!get_clipboard().empty()) { if(haveSelection) { cKey deleteKey = {true, key_bsp, mod_none}; handleInput(deleteKey); } contents = getText(); std::string toInsert = get_clipboard(); contents.insert(insertionPoint, toInsert); history.add(action_ptr(new aTextInsert(*this, insertionPoint, toInsert))); insertionPoint += toInsert.length(); selectionPoint = insertionPoint; } break; case key_undo: if(current_action) history.add(current_action), current_action.reset(); history.undo(); return; case key_redo: if(current_action) history.add(current_action), current_action.reset(); history.redo(); return; case key_selectall: if(current_action) history.add(current_action), current_action.reset(); selectionPoint = 0; insertionPoint = contents.length(); break; // These keys have no function in this context. case key_esc: case key_tab: case key_help: case key_insert: break; } // Setting the text normally resets insertion/selection point, but we don't want that here. int ip = insertionPoint, sp = selectionPoint; setText(contents); insertionPoint = ip; selectionPoint = sp; }
void editor (char *filename, int startpos) { int stop = FALSE; // exit main loop? int fline = 0; // no. of first displayed line int cline = 0; // no. of line with cursor int shift = 0; // shift to the right int ccol = 0; // column of the cursor position in the file window int k, i, ndisp, rc, reply; char *p, buf[1024]; if (editor_open_file (filename) < 0) return; cline = min1 (startpos, nl-1); fline = max1 (0, cline - video_vsize()/2); // enter the loop while (1) { if (stop) { rc = 0; if (changed) { rc = -1; reply = fly_ask (0, " Save file `%s'? ", " Yes \n No \n Cancel ", filename); if (reply == 1) rc = editor_save_file (filename); if (reply == 2) rc = 0; if (reply == 3) stop = FALSE; } if (rc == 0) break; } ndisp = video_vsize()-1; // draw the screen for (i=0; i<ndisp; i++) { video_put_n_cell (' ', _BackWhite+_Black, video_hsize(), i, 0); if (i+fline < nl) editor_display_line (i, fline+i, shift); } video_put_n_cell (' ', _BackBlue+_White, video_hsize(), video_vsize()-1, 0); snprintf1 (buf, sizeof(buf), "L%d:C%d:S%d %c %s%s", cline, ccol, shift, fl_sym.v, changed ? "*" : "", filename); video_put (buf, video_vsize()-1, 0); video_set_cursor (cline-fline, ccol-shift); video_update (0); // get a keyboard/mouse event and process it k = getmessage (-1); if (IS_KEY(k)) { switch (k) { // Navigation keys case _Up: case _Down: case _PgUp: case _PgDn: fly_scroll_it (k, &fline, &cline, nl, video_vsize()-1); break; case _Right: ccol++; if (ccol-shift > video_hsize()-1) shift = ccol-video_hsize()+1; break; case _Left: ccol = max1 (ccol-1, 0); if (ccol < shift) shift = ccol; break; case _Home: ccol = 0; shift = 0; break; case _End: ccol = strlen(lines[cline]); if (ccol-shift > video_hsize()-1) shift = ccol-video_hsize()+1; break; case _CtrlHome: fline = 0; cline = 0; ccol = 0; shift = 0; break; case _CtrlEnd: fline = max1 (0, nl-video_vsize()+1); cline = min1 (fline+video_vsize()-1, nl-1); shift = 0; ccol = 0; break; // Action keys case _CtrlY: put_clipboard (lines[cline]); free (lines[cline]); for (i=cline; i<nl-1; i++) lines[i] = lines[i+1]; nl--; changed = TRUE; break; case _ShiftInsert: case _CtrlV: p = get_clipboard (); if (p == NULL || *p == '\0') break; if (nl == na) { na *= 2; lines = realloc (lines, sizeof(char *) * na); } for (i=nl-1; i>cline; i--) lines[i+1] = lines[i]; lines[cline+1] = p; ccol = 0; shift = 0; cline++; if (cline-fline == video_vsize()-1) fline++; nl++; changed = TRUE; break; case _BackSpace: if (ccol == 0) { // ccol == 0: glue this line to the previous if (cline == 0) break; p = malloc (strlen (lines[cline])+strlen(lines[cline-1])+1); strcpy (p, lines[cline-1]); strcat (p, lines[cline]); ccol = strlen (lines[cline-1]); if (ccol-shift > video_hsize()-1) shift = ccol-video_hsize()+1; free (lines[cline-1]); free (lines[cline]); lines[cline-1] = p; for (i=cline; i<nl-1; i++) lines[i] = lines[i+1]; cline--; nl--; } else { // ccol != 0: delete char at ccol-1, move cursor left str_delete (lines[cline], lines[cline]+ccol-1); ccol--; if (ccol < shift) shift = ccol; } changed = TRUE; break; case _Enter: if (nl == na) { na *= 2; lines = realloc (lines, sizeof(char *) * na); } for (i=nl-1; i>cline; i--) lines[i+1] = lines[i]; if (ccol < strlen (lines[cline])) { lines[cline+1] = strdup (lines[cline]+ccol); lines[cline][ccol] = '\0'; } else { lines[cline+1] = strdup (""); } ccol = 0; shift = 0; cline++; if (cline-fline == video_vsize()-1) fline++; nl++; changed = TRUE; break; case _Delete: if (ccol >= strlen (lines[cline])) { // glue previous line to this one if (cline == nl-1) break; p = malloc (ccol+strlen(lines[cline+1])+1); strcpy (p, lines[cline]); memset (p+strlen(lines[cline]), ' ', ccol-strlen(lines[cline])); strcpy (p+ccol, lines[cline+1]); free (lines[cline]); free (lines[cline+1]); lines[cline] = p; for (i=cline+1; i<nl-1; i++) lines[i] = lines[i+1]; nl--; } else { // ccol != 0: delete char at ccol-1, move cursor left str_delete (lines[cline], lines[cline]+ccol); } changed = TRUE; break; case _F2: rc = editor_save_file (filename); if (rc == 0) changed = FALSE; break; case _Esc: case _F10: stop = TRUE; break; // character keys default: if (k >= ' ' && k <= 255) { str_insert_at (cline, k, ccol); ccol++; changed = TRUE; } } } else if (IS_MOUSE(k)) { } else if (IS_SYSTEM(k)) { switch (SYS_TYPE(k)) { case SYSTEM_QUIT: stop = TRUE; break; } } } if (nl != 0 && lines != NULL) for (i=0; i<nl; i++) free (lines[i]); if (na != 0 && lines != NULL) free (lines); na = 0; lines = NULL; }