コード例 #1
0
/*
 * 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;
}
コード例 #2
0
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;
}
コード例 #3
0
/*
 * 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);
}
コード例 #4
0
ファイル: plugman.c プロジェクト: Davletvm/gtk
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));
}
コード例 #5
0
/*
 * 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;
}
コード例 #6
0
ファイル: bloatpad.c プロジェクト: Pfiver/gtk
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);

}
コード例 #7
0
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;

}
コード例 #8
0
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;
}
コード例 #9
0
/*
 * 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;
}
コード例 #10
0
static jobject get_data_uri_list(JNIEnv *env, gboolean files)
{
    return uris_to_java(env, gtk_clipboard_wait_for_uris(get_clipboard()), files);
}
コード例 #11
0
ファイル: field.cpp プロジェクト: Ircher/CBoE
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;
}
コード例 #12
0
ファイル: ef.c プロジェクト: OS2World/LIB-libfly
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;
}