Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/edit/edit.c

    r3c22438a r87822ce  
    11/*
    2  * Copyright (c) 2026 Jiri Svoboda
     2 * Copyright (c) 2009 Jiri Svoboda
    33 * Copyright (c) 2012 Martin Sucha
    44 * All rights reserved.
     
    3636 */
    3737
    38 #include <align.h>
    39 #include <clipboard.h>
    40 #include <errno.h>
    41 #include <gfx/color.h>
    42 #include <gfx/cursor.h>
    43 #include <gfx/font.h>
    44 #include <gfx/render.h>
    45 #include <gfx/text.h>
    46 #include <io/kbd_event.h>
    47 #include <io/keycode.h>
    48 #include <io/pos_event.h>
    49 #include <io/style.h>
    50 #include <macros.h>
    5138#include <stdio.h>
    5239#include <stdlib.h>
    5340#include <stddef.h>
    5441#include <stdbool.h>
     42#include <vfs/vfs.h>
     43#include <io/console.h>
     44#include <io/style.h>
     45#include <io/keycode.h>
     46#include <errno.h>
     47#include <align.h>
     48#include <macros.h>
     49#include <clipboard.h>
    5550#include <types/common.h>
    56 #include <ui/control.h>
    57 #include <ui/filedialog.h>
    58 #include <ui/fixed.h>
    59 #include <ui/label.h>
    60 #include <ui/menu.h>
    61 #include <ui/menubar.h>
    62 #include <ui/menudd.h>
    63 #include <ui/menuentry.h>
    64 #include <ui/promptdialog.h>
    65 #include <ui/resource.h>
    66 #include <ui/ui.h>
    67 #include <ui/window.h>
    68 #include <vfs/vfs.h>
    6951
    7052#include "sheet.h"
     
    8163 *
    8264 * A rectangular area of the screen used to edit a document. Different
    83  * panes can be possibly used to edit the same document. This is a custom
    84  * UI control.
     65 * panes can be possibly used to edit the same document.
    8566 */
    8667typedef struct {
    87         /** Base control object */
    88         struct ui_control *control;
    89 
    90         /** Containing window */
    91         ui_window_t *window;
    92 
    93         /** UI resource */
    94         struct ui_resource *res;
    95 
    96         /** Pane rectangle */
    97         gfx_rect_t rect;
    98 
    99         /** Pane color */
    100         gfx_color_t *color;
    101 
    102         /** Selection color */
    103         gfx_color_t *sel_color;
    104 
    10568        /* Pane dimensions */
    10669        int rows, columns;
     
    12790        int ideal_column;
    12891
    129         bool search_reverse;
    13092        char *previous_search;
    13193        bool previous_search_reverse;
    13294} pane_t;
    133 
    134 /** Text editor */
    135 typedef struct {
    136         /** User interface */
    137         ui_t *ui;
    138         /** Editor window */
    139         ui_window_t *window;
    140         /** UI resource */
    141         ui_resource_t *ui_res;
    142         /** Menu bar */
    143         ui_menu_bar_t *menubar;
    144         /** Status bar */
    145         ui_label_t *status;
    146 } edit_t;
    14795
    14896/** Document
     
    155103} doc_t;
    156104
    157 static edit_t edit;
     105static console_ctrl_t *con;
    158106static doc_t doc;
     107static bool done;
    159108static pane_t pane;
     109static bool cursor_visible;
     110
     111static sysarg_t scr_rows;
     112static sysarg_t scr_columns;
    160113
    161114#define ROW_BUF_SIZE 4096
     
    166119#define INFNAME_MAX_LEN 128
    167120
     121static void cursor_show(void);
     122static void cursor_hide(void);
    168123static void cursor_setvis(bool visible);
    169124
     
    177132static void pos_handle(pos_event_t *ev);
    178133
    179 static errno_t file_new(void);
    180 static void file_open(void);
    181 static errno_t file_open_file(const char *fname);
    182134static errno_t file_save(char const *fname);
    183135static void file_save_as(void);
    184 static errno_t file_insert(const char *fname);
     136static errno_t file_insert(char *fname);
    185137static errno_t file_save_range(char const *fname, spt_t const *spos,
    186138    spt_t const *epos);
    187139static char *range_get_str(spt_t const *spos, spt_t const *epos);
    188140
    189 static errno_t pane_init(ui_window_t *, pane_t *);
    190 static void pane_fini(pane_t *);
    191 static ui_control_t *pane_ctl(pane_t *);
    192 static errno_t pane_update(pane_t *);
    193 static errno_t pane_text_display(pane_t *);
     141static char *prompt(char const *prompt, char const *init_value);
     142
     143static void pane_text_display(void);
    194144static void pane_row_display(void);
    195 static errno_t pane_row_range_display(pane_t *, int r0, int r1);
    196 static void pane_status_display(pane_t *);
    197 static void pane_caret_display(pane_t *);
     145static void pane_row_range_display(int r0, int r1);
     146static void pane_status_display(void);
     147static void pane_caret_display(void);
    198148
    199149static void insert_char(char32_t c);
     
    214164static void selection_delete(void);
    215165static void selection_copy(void);
    216 static void edit_cut(void);
    217 static void edit_paste(void);
    218166static void insert_clipboard_data(void);
    219167
     
    237185
    238186static void status_display(char const *str);
    239 static errno_t edit_ui_create(edit_t *);
    240 static void edit_ui_destroy(edit_t *);
    241 
    242 static void edit_wnd_resize(ui_window_t *, void *);
    243 static void edit_wnd_close(ui_window_t *, void *);
    244 static void edit_wnd_focus(ui_window_t *, void *, unsigned);
    245 static void edit_wnd_kbd_event(ui_window_t *, void *, kbd_event_t *);
    246 static void edit_wnd_unfocus(ui_window_t *, void *, unsigned);
    247 
    248 static ui_window_cb_t edit_window_cb = {
    249         .resize = edit_wnd_resize,
    250         .close = edit_wnd_close,
    251         .focus = edit_wnd_focus,
    252         .kbd = edit_wnd_kbd_event,
    253         .unfocus = edit_wnd_unfocus
    254 };
    255 
    256 static void edit_menubar_activate(ui_menu_bar_t *, void *);
    257 static void edit_menubar_deactivate(ui_menu_bar_t *, void *);
    258 
    259 static ui_menu_bar_cb_t edit_menubar_cb = {
    260         .activate = edit_menubar_activate,
    261         .deactivate = edit_menubar_deactivate
    262 };
    263 
    264 static void edit_file_new(ui_menu_entry_t *, void *);
    265 static void edit_file_open(ui_menu_entry_t *, void *);
    266 static void edit_file_save(ui_menu_entry_t *, void *);
    267 static void edit_file_save_as(ui_menu_entry_t *, void *);
    268 static void edit_file_exit(ui_menu_entry_t *, void *);
    269 static void edit_edit_cut(ui_menu_entry_t *, void *);
    270 static void edit_edit_copy(ui_menu_entry_t *, void *);
    271 static void edit_edit_paste(ui_menu_entry_t *, void *);
    272 static void edit_edit_delete(ui_menu_entry_t *, void *);
    273 static void edit_edit_select_all(ui_menu_entry_t *, void *);
    274 static void edit_search_find(ui_menu_entry_t *, void *);
    275 static void edit_search_reverse_find(ui_menu_entry_t *, void *);
    276 static void edit_search_find_next(ui_menu_entry_t *, void *);
    277 static void edit_search_go_to_line(ui_menu_entry_t *, void *);
    278 
    279 static void pane_ctl_destroy(void *);
    280 static errno_t pane_ctl_paint(void *);
    281 static ui_evclaim_t pane_ctl_pos_event(void *, pos_event_t *);
    282 
    283 /** Pabe control ops */
    284 ui_control_ops_t pane_ctl_ops = {
    285         .destroy = pane_ctl_destroy,
    286         .paint = pane_ctl_paint,
    287         .pos_event = pane_ctl_pos_event
    288 };
    289 
    290 static void open_dialog_bok(ui_file_dialog_t *, void *, const char *);
    291 static void open_dialog_bcancel(ui_file_dialog_t *, void *);
    292 static void open_dialog_close(ui_file_dialog_t *, void *);
    293 
    294 static ui_file_dialog_cb_t open_dialog_cb = {
    295         .bok = open_dialog_bok,
    296         .bcancel = open_dialog_bcancel,
    297         .close = open_dialog_close
    298 };
    299 
    300 static void save_as_dialog_bok(ui_file_dialog_t *, void *, const char *);
    301 static void save_as_dialog_bcancel(ui_file_dialog_t *, void *);
    302 static void save_as_dialog_close(ui_file_dialog_t *, void *);
    303 
    304 static ui_file_dialog_cb_t save_as_dialog_cb = {
    305         .bok = save_as_dialog_bok,
    306         .bcancel = save_as_dialog_bcancel,
    307         .close = save_as_dialog_close
    308 };
    309 
    310 static void go_to_line_dialog_bok(ui_prompt_dialog_t *, void *, const char *);
    311 static void go_to_line_dialog_bcancel(ui_prompt_dialog_t *, void *);
    312 static void go_to_line_dialog_close(ui_prompt_dialog_t *, void *);
    313 
    314 static ui_prompt_dialog_cb_t go_to_line_dialog_cb = {
    315         .bok = go_to_line_dialog_bok,
    316         .bcancel = go_to_line_dialog_bcancel,
    317         .close =  go_to_line_dialog_close
    318 };
    319 
    320 static void search_dialog_bok(ui_prompt_dialog_t *, void *, const char *);
    321 static void search_dialog_bcancel(ui_prompt_dialog_t *, void *);
    322 static void search_dialog_close(ui_prompt_dialog_t *, void *);
    323 
    324 static ui_prompt_dialog_cb_t search_dialog_cb = {
    325         .bok = search_dialog_bok,
    326         .bcancel = search_dialog_bcancel,
    327         .close =  search_dialog_close
    328 };
    329187
    330188int main(int argc, char *argv[])
    331189{
     190        cons_event_t ev;
     191        bool new_file;
    332192        errno_t rc;
    333193
     194        con = console_init(stdin, stdout);
     195        console_clear(con);
     196
     197        console_get_size(con, &scr_columns, &scr_rows);
     198
     199        pane.rows = scr_rows - 1;
     200        pane.columns = scr_columns;
    334201        pane.sh_row = 1;
    335202        pane.sh_column = 1;
    336203
    337         /* Create UI */
    338         rc = edit_ui_create(&edit);
    339         if (rc != EOK)
    340                 return 1;
     204        /* Start with an empty sheet. */
     205        rc = sheet_create(&doc.sh);
     206        if (rc != EOK) {
     207                printf("Out of memory.\n");
     208                return -1;
     209        }
     210
     211        /* Place caret at the beginning of file. */
     212        spt_t sof;
     213        pt_get_sof(&sof);
     214        sheet_place_tag(doc.sh, &sof, &pane.caret_pos);
     215        pane.ideal_column = 1;
    341216
    342217        if (argc == 2) {
    343218                doc.file_name = str_dup(argv[1]);
    344                 rc = file_open_file(argv[1]);
    345                 if (rc != EOK) {
    346                         status_display("File not found. Starting empty file.");
    347                         rc = file_new();
    348                 }
    349219        } else if (argc > 1) {
    350220                printf("Invalid arguments.\n");
    351221                return -2;
    352222        } else {
    353                 rc = file_new();
    354         }
     223                doc.file_name = NULL;
     224        }
     225
     226        new_file = false;
     227
     228        if (doc.file_name == NULL || file_insert(doc.file_name) != EOK)
     229                new_file = true;
     230
     231        /* Place selection start tag. */
     232        sheet_place_tag(doc.sh, &sof, &pane.sel_start);
     233
     234        /* Move to beginning of file. */
     235        pt_get_sof(&sof);
     236        caret_move(sof, true, true);
    355237
    356238        /* Initial display */
    357         rc = ui_window_paint(edit.window);
    358         if (rc != EOK) {
    359                 printf("Error painting window.\n");
    360                 return rc;
    361         }
    362 
    363         ui_run(edit.ui);
    364 
    365         edit_ui_destroy(&edit);
     239        cursor_visible = true;
     240
     241        cursor_hide();
     242        console_clear(con);
     243        pane_text_display();
     244        pane_status_display();
     245        if (new_file && doc.file_name != NULL)
     246                status_display("File not found. Starting empty file.");
     247        pane_caret_display();
     248        cursor_show();
     249
     250        done = false;
     251
     252        while (!done) {
     253                rc = console_get_event(con, &ev);
     254                if (rc != EOK)
     255                        break;
     256
     257                pane.rflags = 0;
     258
     259                switch (ev.type) {
     260                case CEV_KEY:
     261                        pane.keymod = ev.ev.key.mods;
     262                        if (ev.ev.key.type == KEY_PRESS)
     263                                key_handle_press(&ev.ev.key);
     264                        break;
     265                case CEV_POS:
     266                        pos_handle(&ev.ev.pos);
     267                        break;
     268                }
     269
     270                /* Redraw as necessary. */
     271
     272                cursor_hide();
     273
     274                if (pane.rflags & REDRAW_TEXT)
     275                        pane_text_display();
     276                if (pane.rflags & REDRAW_ROW)
     277                        pane_row_display();
     278                if (pane.rflags & REDRAW_STATUS)
     279                        pane_status_display();
     280                if (pane.rflags & REDRAW_CARET)
     281                        pane_caret_display();
     282
     283                cursor_show();
     284        }
     285
     286        console_clear(con);
     287
    366288        return 0;
    367 }
    368 
    369 /** Set menu bar rectangle.
    370  *
    371  * Set the menu bar rectangle based on editor window dimensions.
    372  * Used when window is created or resized.
    373  *
    374  * @param edit Editor
    375  */
    376 static void edit_menubar_set_rect(edit_t *edit)
    377 {
    378         gfx_rect_t arect;
    379         gfx_rect_t rect;
    380 
    381         ui_window_get_app_rect(edit->window, &arect);
    382 
    383         rect.p0 = arect.p0;
    384         rect.p1.x = arect.p1.x;
    385         rect.p1.y = arect.p0.y + 1;
    386         ui_menu_bar_set_rect(edit->menubar, &rect);
    387 }
    388 
    389 /** Set status bar rectangle.
    390  *
    391  * Set the status bar rectangle based on editor window dimensions.
    392  * Used when window is created or resized.
    393  *
    394  * @param edit Editor
    395  */
    396 static void edit_status_set_rect(edit_t *edit)
    397 {
    398         gfx_rect_t arect;
    399         gfx_rect_t rect;
    400 
    401         ui_window_get_app_rect(edit->window, &arect);
    402         rect.p0.x = arect.p0.x;
    403         rect.p0.y = arect.p1.y - 1;
    404         rect.p1 = arect.p1;
    405         ui_label_set_rect(edit->status, &rect);
    406 }
    407 
    408 /** Create text editor UI.
    409  *
    410  * @param edit Editor
    411  * @return EOK on success or an error code
    412  */
    413 static errno_t edit_ui_create(edit_t *edit)
    414 {
    415         errno_t rc;
    416         ui_wnd_params_t params;
    417         ui_fixed_t *fixed = NULL;
    418         ui_menu_t *mfile = NULL;
    419         ui_menu_t *medit = NULL;
    420         ui_menu_entry_t *mnew = NULL;
    421         ui_menu_entry_t *mopen = NULL;
    422         ui_menu_entry_t *msave = NULL;
    423         ui_menu_entry_t *msaveas = NULL;
    424         ui_menu_entry_t *mfsep = NULL;
    425         ui_menu_entry_t *mexit = NULL;
    426         ui_menu_entry_t *mcut = NULL;
    427         ui_menu_entry_t *mcopy = NULL;
    428         ui_menu_entry_t *mpaste = NULL;
    429         ui_menu_entry_t *mdelete = NULL;
    430         ui_menu_entry_t *mesep = NULL;
    431         ui_menu_entry_t *mselall = NULL;
    432         ui_menu_t *msearch = NULL;
    433         ui_menu_entry_t *mfind = NULL;
    434         ui_menu_entry_t *mfindr = NULL;
    435         ui_menu_entry_t *mfindn = NULL;
    436         ui_menu_entry_t *mssep = NULL;
    437         ui_menu_entry_t *mgoto = NULL;
    438 
    439         rc = ui_create(UI_CONSOLE_DEFAULT, &edit->ui);
    440         if (rc != EOK) {
    441                 printf("Error creating UI on display %s.\n",
    442                     UI_CONSOLE_DEFAULT);
    443                 goto error;
    444         }
    445 
    446         ui_wnd_params_init(&params);
    447         params.caption = "Text Editor";
    448         params.style &= ~ui_wds_decorated;
    449         params.placement = ui_wnd_place_full_screen;
    450 
    451         rc = ui_window_create(edit->ui, &params, &edit->window);
    452         if (rc != EOK) {
    453                 printf("Error creating window.\n");
    454                 goto error;
    455         }
    456 
    457         ui_window_set_cb(edit->window, &edit_window_cb, (void *) edit);
    458 
    459         edit->ui_res = ui_window_get_res(edit->window);
    460 
    461         rc = ui_fixed_create(&fixed);
    462         if (rc != EOK) {
    463                 printf("Error creating fixed layout.\n");
    464                 return rc;
    465         }
    466 
    467         rc = ui_menu_bar_create(edit->ui, edit->window, &edit->menubar);
    468         if (rc != EOK) {
    469                 printf("Error creating menu bar.\n");
    470                 return rc;
    471         }
    472 
    473         ui_menu_bar_set_cb(edit->menubar, &edit_menubar_cb, (void *) edit);
    474 
    475         rc = ui_menu_dd_create(edit->menubar, "~F~ile", NULL, &mfile);
    476         if (rc != EOK) {
    477                 printf("Error creating menu.\n");
    478                 return rc;
    479         }
    480 
    481         rc = ui_menu_entry_create(mfile, "~N~ew", "Ctrl-N", &mnew);
    482         if (rc != EOK) {
    483                 printf("Error creating menu.\n");
    484                 return rc;
    485         }
    486 
    487         ui_menu_entry_set_cb(mnew, edit_file_new, (void *) edit);
    488 
    489         rc = ui_menu_entry_create(mfile, "~O~pen", "Ctrl-O", &mopen);
    490         if (rc != EOK) {
    491                 printf("Error creating menu.\n");
    492                 return rc;
    493         }
    494 
    495         ui_menu_entry_set_cb(mopen, edit_file_open, (void *) edit);
    496 
    497         rc = ui_menu_entry_create(mfile, "~S~ave", "Ctrl-S", &msave);
    498         if (rc != EOK) {
    499                 printf("Error creating menu.\n");
    500                 return rc;
    501         }
    502 
    503         ui_menu_entry_set_cb(msave, edit_file_save, (void *) edit);
    504 
    505         rc = ui_menu_entry_create(mfile, "Save ~A~s", "Ctrl-E", &msaveas);
    506         if (rc != EOK) {
    507                 printf("Error creating menu.\n");
    508                 return rc;
    509         }
    510 
    511         ui_menu_entry_set_cb(msaveas, edit_file_save_as, (void *) edit);
    512 
    513         rc = ui_menu_entry_sep_create(mfile, &mfsep);
    514         if (rc != EOK) {
    515                 printf("Error creating menu.\n");
    516                 return rc;
    517         }
    518 
    519         rc = ui_menu_entry_create(mfile, "E~x~it", "Ctrl-Q", &mexit);
    520         if (rc != EOK) {
    521                 printf("Error creating menu.\n");
    522                 return rc;
    523         }
    524 
    525         ui_menu_entry_set_cb(mexit, edit_file_exit, (void *) edit);
    526 
    527         rc = ui_menu_dd_create(edit->menubar, "~E~dit", NULL, &medit);
    528         if (rc != EOK) {
    529                 printf("Error creating menu.\n");
    530                 return rc;
    531         }
    532 
    533         rc = ui_menu_entry_create(medit, "Cu~t~", "Ctrl-X", &mcut);
    534         if (rc != EOK) {
    535                 printf("Error creating menu.\n");
    536                 return rc;
    537         }
    538 
    539         ui_menu_entry_set_cb(mcut, edit_edit_cut, (void *) edit);
    540 
    541         rc = ui_menu_entry_create(medit, "~C~opy", "Ctrl-C", &mcopy);
    542         if (rc != EOK) {
    543                 printf("Error creating menu.\n");
    544                 return rc;
    545         }
    546 
    547         ui_menu_entry_set_cb(mcopy, edit_edit_copy, (void *) edit);
    548 
    549         rc = ui_menu_entry_create(medit, "~P~aste", "Ctrl-V", &mpaste);
    550         if (rc != EOK) {
    551                 printf("Error creating menu.\n");
    552                 return rc;
    553         }
    554 
    555         ui_menu_entry_set_cb(mpaste, edit_edit_paste, (void *) edit);
    556 
    557         rc = ui_menu_entry_create(medit, "~D~elete", "Del", &mdelete);
    558         if (rc != EOK) {
    559                 printf("Error creating menu.\n");
    560                 return rc;
    561         }
    562 
    563         ui_menu_entry_set_cb(mdelete, edit_edit_delete, (void *) edit);
    564 
    565         rc = ui_menu_entry_sep_create(medit, &mesep);
    566         if (rc != EOK) {
    567                 printf("Error creating menu.\n");
    568                 return rc;
    569         }
    570 
    571         rc = ui_menu_entry_create(medit, "Select ~A~ll", "Ctrl-A", &mselall);
    572         if (rc != EOK) {
    573                 printf("Error creating menu.\n");
    574                 return rc;
    575         }
    576 
    577         ui_menu_entry_set_cb(mselall, edit_edit_select_all, (void *) edit);
    578 
    579         rc = ui_menu_dd_create(edit->menubar, "~S~earch", NULL, &msearch);
    580         if (rc != EOK) {
    581                 printf("Error creating menu.\n");
    582                 return rc;
    583         }
    584 
    585         rc = ui_menu_entry_create(msearch, "~F~ind", "Ctrl-F", &mfind);
    586         if (rc != EOK) {
    587                 printf("Error creating menu.\n");
    588                 return rc;
    589         }
    590 
    591         ui_menu_entry_set_cb(mfind, edit_search_find, (void *) edit);
    592 
    593         rc = ui_menu_entry_create(msearch, "~R~everse Find", "Ctrl-Shift-F", &mfindr);
    594         if (rc != EOK) {
    595                 printf("Error creating menu.\n");
    596                 return rc;
    597         }
    598 
    599         ui_menu_entry_set_cb(mfindr, edit_search_reverse_find, (void *) edit);
    600 
    601         rc = ui_menu_entry_create(msearch, "Find ~N~ext", "Ctrl-R", &mfindn);
    602         if (rc != EOK) {
    603                 printf("Error creating menu.\n");
    604                 return rc;
    605         }
    606 
    607         ui_menu_entry_set_cb(mfindn, edit_search_find_next, (void *) edit);
    608 
    609         rc = ui_menu_entry_sep_create(msearch, &mssep);
    610         if (rc != EOK) {
    611                 printf("Error creating menu.\n");
    612                 return rc;
    613         }
    614 
    615         rc = ui_menu_entry_create(msearch, "Go To ~L~ine", "Ctrl-L", &mgoto);
    616         if (rc != EOK) {
    617                 printf("Error creating menu.\n");
    618                 return rc;
    619         }
    620 
    621         ui_menu_entry_set_cb(mgoto, edit_search_go_to_line, (void *) edit);
    622 
    623         edit_menubar_set_rect(edit);
    624 
    625         rc = ui_fixed_add(fixed, ui_menu_bar_ctl(edit->menubar));
    626         if (rc != EOK) {
    627                 printf("Error adding control to layout.\n");
    628                 return rc;
    629         }
    630 
    631         rc = pane_init(edit->window, &pane);
    632         if (rc != EOK) {
    633                 printf("Error initializing pane.\n");
    634                 return rc;
    635         }
    636 
    637         rc = ui_fixed_add(fixed, pane_ctl(&pane));
    638         if (rc != EOK) {
    639                 printf("Error adding control to layout.\n");
    640                 return rc;
    641         }
    642 
    643         rc = ui_label_create(edit->ui_res, "", &edit->status);
    644         if (rc != EOK) {
    645                 printf("Error creating menu bar.\n");
    646                 return rc;
    647         }
    648 
    649         edit_status_set_rect(edit);
    650 
    651         rc = ui_fixed_add(fixed, ui_label_ctl(edit->status));
    652         if (rc != EOK) {
    653                 printf("Error adding control to layout.\n");
    654                 return rc;
    655         }
    656 
    657         ui_window_add(edit->window, ui_fixed_ctl(fixed));
    658         return EOK;
    659 error:
    660         if (edit->window != NULL)
    661                 ui_window_destroy(edit->window);
    662         if (edit->ui != NULL)
    663                 ui_destroy(edit->ui);
    664         return rc;
    665 }
    666 
    667 /** Destroy text editor UI.
    668  *
    669  * @param edit Editor
    670  */
    671 static void edit_ui_destroy(edit_t *edit)
    672 {
    673         ui_window_destroy(edit->window);
    674         ui_destroy(edit->ui);
    675289}
    676290
     
    695309}
    696310
     311static void cursor_show(void)
     312{
     313        cursor_setvis(true);
     314}
     315
     316static void cursor_hide(void)
     317{
     318        cursor_setvis(false);
     319}
     320
    697321static void cursor_setvis(bool visible)
    698322{
    699         gfx_context_t *gc = ui_window_get_gc(edit.window);
    700 
    701         (void) gfx_cursor_set_visible(gc, visible);
     323        if (cursor_visible != visible) {
     324                console_cursor_visibility(con, visible);
     325                cursor_visible = visible;
     326        }
    702327}
    703328
     
    775400        switch (ev->key) {
    776401        case KC_Q:
    777                 ui_quit(edit.ui);
    778                 break;
    779         case KC_N:
    780                 file_new();
    781                 break;
    782         case KC_O:
    783                 file_open();
     402                done = true;
    784403                break;
    785404        case KC_S:
     
    796415                break;
    797416        case KC_V:
    798                 edit_paste();
     417                selection_delete();
     418                insert_clipboard_data();
     419                pane.rflags |= REDRAW_TEXT;
     420                caret_update();
    799421                break;
    800422        case KC_X:
    801                 edit_cut();
     423                selection_copy();
     424                selection_delete();
     425                pane.rflags |= REDRAW_TEXT;
     426                caret_update();
    802427                break;
    803428        case KC_A:
     
    816441                search_prompt(false);
    817442                break;
    818         case KC_R:
     443        case KC_N:
    819444                search_repeat();
    820445                break;
     
    865490
    866491        if (ev->type == POS_PRESS && ev->vpos < (unsigned)pane.rows) {
    867                 bc.row = pane.sh_row + ev->vpos - pane.rect.p0.y;
    868                 bc.column = pane.sh_column + ev->hpos - pane.rect.p0.x;
     492                bc.row = pane.sh_row + ev->vpos;
     493                bc.column = pane.sh_column + ev->hpos;
    869494                sheet_get_cell_pt(doc.sh, &bc, dir_before, &pt);
    870495
     
    872497
    873498                caret_move(pt, select, true);
    874                 pane_update(&pane);
    875499        }
    876500}
     
    955579}
    956580
    957 /** Create new document. */
    958 static errno_t file_new(void)
    959 {
    960         errno_t rc;
    961         sheet_t *sh;
    962 
    963         /* Create empty sheet. */
    964         rc = sheet_create(&sh);
    965         if (rc != EOK) {
    966                 printf("Out of memory.\n");
    967                 return ENOMEM;
    968         }
    969 
    970         if (doc.sh != NULL)
    971                 sheet_destroy(doc.sh);
    972 
    973         doc.sh = sh;
    974 
    975         /* Place caret at the beginning of file. */
    976         spt_t sof;
    977         pt_get_sof(&sof);
    978         sheet_place_tag(doc.sh, &sof, &pane.caret_pos);
    979         pane.ideal_column = 1;
    980 
    981         doc.file_name = NULL;
    982 
    983         /* Place selection start tag. */
    984         sheet_place_tag(doc.sh, &sof, &pane.sel_start);
    985 
    986         /* Move to beginning of file. */
    987         pt_get_sof(&sof);
    988 
    989         caret_move(sof, true, true);
    990 
    991         pane_status_display(&pane);
    992         pane_caret_display(&pane);
    993         pane_text_display(&pane);
    994         cursor_setvis(true);
    995 
    996         return EOK;
    997 }
    998 
    999 /** Open Open File dialog. */
    1000 static void file_open(void)
    1001 {
    1002         const char *old_fname = (doc.file_name != NULL) ? doc.file_name : "";
    1003         ui_file_dialog_params_t fdparams;
    1004         ui_file_dialog_t *dialog;
    1005         errno_t rc;
    1006 
    1007         ui_file_dialog_params_init(&fdparams);
    1008         fdparams.caption = "Open File";
    1009         fdparams.ifname = old_fname;
    1010 
    1011         rc = ui_file_dialog_create(edit.ui, &fdparams, &dialog);
    1012         if (rc != EOK) {
    1013                 printf("Error creating message dialog.\n");
    1014                 return;
    1015         }
    1016 
    1017         ui_file_dialog_set_cb(dialog, &open_dialog_cb, &edit);
    1018 }
    1019 
    1020 /** Open exising document. */
    1021 static errno_t file_open_file(const char *fname)
    1022 {
    1023         errno_t rc;
    1024         sheet_t *sh;
    1025         char *fn;
    1026 
    1027         /* Create empty sheet. */
    1028         rc = sheet_create(&sh);
    1029         if (rc != EOK) {
    1030                 printf("Out of memory.\n");
    1031                 return ENOMEM;
    1032         }
    1033 
    1034         fn = str_dup(fname);
    1035         if (fn == NULL) {
    1036                 sheet_destroy(sh);
    1037                 return ENOMEM;
    1038         }
    1039 
    1040         if (doc.sh != NULL)
    1041                 sheet_destroy(doc.sh);
    1042 
    1043         doc.sh = sh;
    1044 
    1045         /* Place caret at the beginning of file. */
    1046         spt_t sof;
    1047         pt_get_sof(&sof);
    1048         sheet_place_tag(doc.sh, &sof, &pane.caret_pos);
    1049         pane.ideal_column = 1;
    1050 
    1051         rc = file_insert(fname);
    1052         if (rc != EOK)
    1053                 return rc;
    1054 
    1055         doc.file_name = fn;
    1056 
    1057         /* Place selection start tag. */
    1058         sheet_place_tag(doc.sh, &sof, &pane.sel_start);
    1059 
    1060         /* Move to beginning of file. */
    1061         pt_get_sof(&sof);
    1062 
    1063         caret_move(sof, true, true);
    1064 
    1065         pane_status_display(&pane);
    1066         pane_caret_display(&pane);
    1067         pane_text_display(&pane);
    1068         cursor_setvis(true);
    1069 
    1070         return EOK;
    1071 }
    1072 
    1073581/** Save the document. */
    1074582static errno_t file_save(char const *fname)
     
    1098606}
    1099607
    1100 /** Open Save As dialog. */
     608/** Change document name and save. */
    1101609static void file_save_as(void)
    1102610{
    1103611        const char *old_fname = (doc.file_name != NULL) ? doc.file_name : "";
    1104         ui_file_dialog_params_t fdparams;
    1105         ui_file_dialog_t *dialog;
     612        char *fname;
     613
     614        fname = prompt("Save As", old_fname);
     615        if (fname == NULL) {
     616                status_display("Save cancelled.");
     617                return;
     618        }
     619
     620        errno_t rc = file_save(fname);
     621        if (rc != EOK)
     622                return;
     623
     624        if (doc.file_name != NULL)
     625                free(doc.file_name);
     626        doc.file_name = fname;
     627}
     628
     629/** Ask for a string. */
     630static char *prompt(char const *prompt, char const *init_value)
     631{
     632        cons_event_t ev;
     633        kbd_event_t *kev;
     634        char *str;
     635        char32_t buffer[INFNAME_MAX_LEN + 1];
     636        int max_len;
     637        int nc;
     638        bool done;
    1106639        errno_t rc;
    1107640
    1108         ui_file_dialog_params_init(&fdparams);
    1109         fdparams.caption = "Save As";
    1110         fdparams.ifname = old_fname;
    1111 
    1112         rc = ui_file_dialog_create(edit.ui, &fdparams, &dialog);
    1113         if (rc != EOK) {
    1114                 printf("Error creating message dialog.\n");
    1115                 return;
    1116         }
    1117 
    1118         ui_file_dialog_set_cb(dialog, &save_as_dialog_cb, &edit);
     641        asprintf(&str, "%s: %s", prompt, init_value);
     642        status_display(str);
     643        console_set_pos(con, 1 + str_length(str), scr_rows - 1);
     644        free(str);
     645
     646        console_set_style(con, STYLE_INVERTED);
     647
     648        max_len = min(INFNAME_MAX_LEN, scr_columns - 4 - str_length(prompt));
     649        str_to_wstr(buffer, max_len + 1, init_value);
     650        nc = wstr_length(buffer);
     651        done = false;
     652
     653        while (!done) {
     654                rc = console_get_event(con, &ev);
     655                if (rc != EOK)
     656                        return NULL;
     657
     658                if (ev.type == CEV_KEY && ev.ev.key.type == KEY_PRESS) {
     659                        kev = &ev.ev.key;
     660
     661                        /* Handle key press. */
     662                        if ((kev->mods & (KM_CTRL | KM_ALT)) == 0) {
     663                                switch (kev->key) {
     664                                case KC_ESCAPE:
     665                                        return NULL;
     666                                case KC_BACKSPACE:
     667                                        if (nc > 0) {
     668                                                putchar('\b');
     669                                                console_flush(con);
     670                                                --nc;
     671                                        }
     672                                        break;
     673                                case KC_ENTER:
     674                                        done = true;
     675                                        break;
     676                                default:
     677                                        if (kev->c >= 32 && nc < max_len) {
     678                                                putuchar(kev->c);
     679                                                console_flush(con);
     680                                                buffer[nc++] = kev->c;
     681                                        }
     682                                        break;
     683                                }
     684                        }
     685                }
     686        }
     687
     688        buffer[nc] = '\0';
     689        str = wstr_to_astr(buffer);
     690
     691        console_set_style(con, STYLE_NORMAL);
     692
     693        return str;
    1119694}
    1120695
     
    1124699 * of the caret.
    1125700 */
    1126 static errno_t file_insert(const char *fname)
     701static errno_t file_insert(char *fname)
    1127702{
    1128703        FILE *f;
     
    1151726
    1152727                bcnt -= off;
    1153                 memmove(buf, buf + off, bcnt);
     728                memcpy(buf, buf + off, bcnt);
    1154729
    1155730                insert_char(c);
     
    1233808}
    1234809
    1235 static void pane_set_rect(pane_t *pane)
    1236 {
    1237         gfx_rect_t arect;
    1238 
    1239         ui_window_get_app_rect(pane->window, &arect);
    1240         pane->rect.p0.x = arect.p0.x;
    1241         pane->rect.p0.y = arect.p0.y + 1;
    1242         pane->rect.p1.x = arect.p1.x;
    1243         pane->rect.p1.y = arect.p1.y - 1;
    1244 
    1245         pane->columns = pane->rect.p1.x - pane->rect.p0.x;
    1246         pane->rows = pane->rect.p1.y - pane->rect.p0.y;
    1247 }
    1248 
    1249 /** Initialize pane.
    1250  *
    1251  * TODO: Replace with pane_create() that allocates the pane.
    1252  *
    1253  * @param window Editor window
    1254  * @param pane Pane
    1255  * @return EOK on success or an error code
    1256  */
    1257 static errno_t pane_init(ui_window_t *window, pane_t *pane)
    1258 {
    1259         errno_t rc;
    1260 
    1261         pane->control = NULL;
    1262         pane->color = NULL;
    1263         pane->sel_color = NULL;
    1264 
    1265         rc = ui_control_new(&pane_ctl_ops, (void *) pane, &pane->control);
    1266         if (rc != EOK)
    1267                 goto error;
    1268 
    1269         rc = gfx_color_new_ega(0x07, &pane->color);
    1270         if (rc != EOK)
    1271                 goto error;
    1272 
    1273         rc = gfx_color_new_ega(0x1e, &pane->sel_color);
    1274         if (rc != EOK)
    1275                 goto error;
    1276 
    1277         pane->res = ui_window_get_res(window);
    1278         pane->window = window;
    1279 
    1280         pane_set_rect(pane);
    1281         return EOK;
    1282 error:
    1283         if (pane->control != NULL) {
    1284                 ui_control_delete(pane->control);
    1285                 pane->control = NULL;
    1286         }
    1287 
    1288         if (pane->color != NULL) {
    1289                 gfx_color_delete(pane->color);
    1290                 pane->color = NULL;
    1291         }
    1292 
    1293         return rc;
    1294 }
    1295 
    1296 static void pane_resize(pane_t *pane)
    1297 {
    1298         pane_set_rect(pane);
    1299 
    1300         /* Scroll in case cursor is now outside of the editor pane. */
    1301         caret_move_relative(0, 0, dir_before, true);
    1302 
    1303         pane_caret_display(pane);
    1304 }
    1305 
    1306 /** Finalize pane.
    1307  *
    1308  * TODO: Replace with pane_destroy() that deallocates the pane.
    1309  *
    1310  * @param pane Pane
    1311  */
    1312 static void pane_fini(pane_t *pane)
    1313 {
    1314         gfx_color_delete(pane->color);
    1315         pane->color = NULL;
    1316         gfx_color_delete(pane->sel_color);
    1317         pane->sel_color = NULL;
    1318         ui_control_delete(pane->control);
    1319         pane->control = NULL;
    1320 }
    1321 
    1322 /** Return base control object for a pane.
    1323  *
    1324  * @param pane Pane
    1325  * @return Base UI cntrol
    1326  */
    1327 static ui_control_t *pane_ctl(pane_t *pane)
    1328 {
    1329         return pane->control;
    1330 }
    1331 
    1332 /** Repaint parts of pane that need updating.
    1333  *
    1334  * @param pane Pane
    1335  * @return EOK on succes or an error code
    1336  */
    1337 static errno_t pane_update(pane_t *pane)
    1338 {
    1339         errno_t rc;
    1340 
    1341         if (pane->rflags & REDRAW_TEXT) {
    1342                 rc = pane_text_display(pane);
    1343                 if (rc != EOK)
    1344                         return rc;
    1345         }
    1346 
    1347         if (pane->rflags & REDRAW_ROW)
    1348                 pane_row_display();
    1349 
    1350         if (pane->rflags & REDRAW_STATUS)
    1351                 pane_status_display(pane);
    1352 
    1353         if (pane->rflags & REDRAW_CARET)
    1354                 pane_caret_display(pane);
    1355 
    1356         pane->rflags &= ~(REDRAW_TEXT | REDRAW_ROW | REDRAW_STATUS |
    1357             REDRAW_CARET);
    1358         return EOK;
    1359 }
    1360 
    1361 /** Display pane text.
    1362  *
    1363  * @param pane Pane
    1364  * @return EOK on success or an error code
    1365  */
    1366 static errno_t pane_text_display(pane_t *pane)
    1367 {
    1368         gfx_rect_t rect;
    1369         gfx_context_t *gc;
    1370         errno_t rc;
     810static void pane_text_display(void)
     811{
    1371812        int sh_rows, rows;
    1372813
    1373814        sheet_get_num_rows(doc.sh, &sh_rows);
    1374         rows = min(sh_rows - pane->sh_row + 1, pane->rows);
     815        rows = min(sh_rows - pane.sh_row + 1, pane.rows);
    1375816
    1376817        /* Draw rows from the sheet. */
    1377818
    1378         rc = pane_row_range_display(pane, 0, rows);
    1379         if (rc != EOK)
    1380                 return rc;
     819        console_set_pos(con, 0, 0);
     820        pane_row_range_display(0, rows);
    1381821
    1382822        /* Clear the remaining rows if file is short. */
    1383823
    1384         gc = ui_window_get_gc(pane->window);
    1385 
    1386         rc = gfx_set_color(gc, pane->color);
    1387         if (rc != EOK)
    1388                 goto error;
    1389 
    1390         rect.p0.x = pane->rect.p0.x;
    1391         rect.p0.y = pane->rect.p0.y + rows;
    1392         rect.p1.x = pane->rect.p1.x;
    1393         rect.p1.y = pane->rect.p1.y;
    1394 
    1395         rc = gfx_fill_rect(gc, &rect);
    1396         if (rc != EOK)
    1397                 goto error;
    1398 
    1399         pane->rflags &= ~REDRAW_ROW;
    1400         return EOK;
    1401 error:
    1402         return rc;
     824        int i;
     825        sysarg_t j;
     826        for (i = rows; i < pane.rows; ++i) {
     827                console_set_pos(con, 0, i);
     828                for (j = 0; j < scr_columns; ++j)
     829                        putchar(' ');
     830                console_flush(con);
     831        }
     832
     833        pane.rflags |= (REDRAW_STATUS | REDRAW_CARET);
     834        pane.rflags &= ~REDRAW_ROW;
    1403835}
    1404836
     
    1414846
    1415847        ridx = coord.row - pane.sh_row;
    1416         (void) pane_row_range_display(&pane, ridx, ridx + 1);
     848        pane_row_range_display(ridx, ridx + 1);
    1417849        pane.rflags |= (REDRAW_STATUS | REDRAW_CARET);
    1418850}
    1419851
    1420 /** Display a range of rows of text.
    1421  *
    1422  * @param r0 Start row (inclusive)
    1423  * @param r1 End row (exclusive)
    1424  * @return EOk on success or an error code
    1425  */
    1426 static errno_t pane_row_range_display(pane_t *pane, int r0, int r1)
    1427 {
    1428         int i, fill;
     852static void pane_row_range_display(int r0, int r1)
     853{
     854        int i, j, fill;
    1429855        spt_t rb, re, dep, pt;
    1430856        coord_t rbc, rec;
    1431857        char row_buf[ROW_BUF_SIZE];
    1432         char cbuf[STR_BOUNDS(1) + 1];
    1433858        char32_t c;
    1434859        size_t pos, size;
    1435         size_t cpos;
    1436860        int s_column;
    1437861        coord_t csel_start, csel_end, ctmp;
    1438         gfx_font_t *font;
    1439         gfx_context_t *gc;
    1440         gfx_text_fmt_t fmt;
    1441         gfx_coord2_t tpos;
    1442         gfx_rect_t rect;
    1443         errno_t rc;
    1444 
    1445         font = ui_resource_get_font(edit.ui_res);
    1446         gc = ui_window_get_gc(edit.window);
    1447 
    1448         gfx_text_fmt_init(&fmt);
    1449         fmt.font = font;
    1450         fmt.color = pane->color;
    1451862
    1452863        /* Determine selection start and end. */
    1453864
    1454         tag_get_pt(&pane->sel_start, &pt);
     865        tag_get_pt(&pane.sel_start, &pt);
    1455866        spt_get_coord(&pt, &csel_start);
    1456867
    1457         tag_get_pt(&pane->caret_pos, &pt);
     868        tag_get_pt(&pane.caret_pos, &pt);
    1458869        spt_get_coord(&pt, &csel_end);
    1459870
     
    1466877        /* Draw rows from the sheet. */
    1467878
     879        console_set_pos(con, 0, 0);
    1468880        for (i = r0; i < r1; ++i) {
    1469                 tpos.x = pane->rect.p0.x;
    1470                 tpos.y = pane->rect.p0.y + i;
    1471 
    1472881                /* Starting point for row display */
    1473                 rbc.row = pane->sh_row + i;
    1474                 rbc.column = pane->sh_column;
     882                rbc.row = pane.sh_row + i;
     883                rbc.column = pane.sh_column;
    1475884                sheet_get_cell_pt(doc.sh, &rbc, dir_before, &rb);
    1476885
    1477886                /* Ending point for row display */
    1478                 rec.row = pane->sh_row + i;
    1479                 rec.column = pane->sh_column + pane->columns;
     887                rec.row = pane.sh_row + i;
     888                rec.column = pane.sh_column + pane.columns;
    1480889                sheet_get_cell_pt(doc.sh, &rec, dir_before, &re);
    1481890
     
    1487896                if (coord_cmp(&csel_start, &rbc) <= 0 &&
    1488897                    coord_cmp(&rbc, &csel_end) < 0) {
    1489                         fmt.color = pane->sel_color;
     898                        console_flush(con);
     899                        console_set_style(con, STYLE_SELECTED);
     900                        console_flush(con);
    1490901                }
    1491902
     903                console_set_pos(con, 0, i);
    1492904                size = str_size(row_buf);
    1493905                pos = 0;
    1494                 s_column = pane->sh_column;
     906                s_column = pane.sh_column;
    1495907                while (pos < size) {
    1496                         if ((csel_start.row == rbc.row) && (csel_start.column == s_column))
    1497                                 fmt.color = pane->sel_color;
    1498 
    1499                         if ((csel_end.row == rbc.row) && (csel_end.column == s_column))
    1500                                 fmt.color = pane->color;
     908                        if ((csel_start.row == rbc.row) && (csel_start.column == s_column)) {
     909                                console_flush(con);
     910                                console_set_style(con, STYLE_SELECTED);
     911                                console_flush(con);
     912                        }
     913
     914                        if ((csel_end.row == rbc.row) && (csel_end.column == s_column)) {
     915                                console_flush(con);
     916                                console_set_style(con, STYLE_NORMAL);
     917                                console_flush(con);
     918                        }
    1501919
    1502920                        c = str_decode(row_buf, &pos, size);
    1503921                        if (c != '\t') {
    1504                                 cpos = 0;
    1505                                 rc = chr_encode(c, cbuf, &cpos, sizeof(cbuf));
    1506                                 if (rc != EOK)
    1507                                         return rc;
    1508 
    1509                                 rc = gfx_puttext(&tpos, &fmt, cbuf);
    1510                                 if (rc != EOK)
    1511                                         return rc;
    1512 
     922                                printf("%lc", (wint_t) c);
    1513923                                s_column += 1;
    1514                                 tpos.x++;
    1515924                        } else {
    1516925                                fill = 1 + ALIGN_UP(s_column, TAB_WIDTH) -
    1517926                                    s_column;
    1518927
    1519                                 rc = gfx_set_color(gc, fmt.color);
    1520                                 if (rc != EOK)
    1521                                         return rc;
    1522 
    1523                                 rect.p0.x = tpos.x;
    1524                                 rect.p0.y = tpos.y;
    1525                                 rect.p1.x = tpos.x + fill;
    1526                                 rect.p1.y = tpos.y + 1;
    1527 
    1528                                 rc = gfx_fill_rect(gc, &rect);
    1529                                 if (rc != EOK)
    1530                                         return rc;
    1531 
     928                                for (j = 0; j < fill; ++j)
     929                                        putchar(' ');
    1532930                                s_column += fill;
    1533                                 tpos.x += fill;
    1534931                        }
    1535932                }
    1536933
    1537                 if ((csel_end.row == rbc.row) && (csel_end.column == s_column))
    1538                         fmt.color = pane->color;
     934                if ((csel_end.row == rbc.row) && (csel_end.column == s_column)) {
     935                        console_flush(con);
     936                        console_set_style(con, STYLE_NORMAL);
     937                        console_flush(con);
     938                }
    1539939
    1540940                /* Fill until the end of display area. */
    1541941
    1542                 rc = gfx_set_color(gc, fmt.color);
    1543                 if (rc != EOK)
    1544                         return rc;
    1545 
    1546                 rect.p0.x = tpos.x;
    1547                 rect.p0.y = tpos.y;
    1548                 rect.p1.x = pane->rect.p1.x;
    1549                 rect.p1.y = tpos.y + 1;
    1550 
    1551                 rc = gfx_fill_rect(gc, &rect);
    1552                 if (rc != EOK)
    1553                         return rc;
    1554         }
    1555 
    1556         return EOK;
    1557 }
    1558 
    1559 /** Display pane status in the status line.
    1560  *
    1561  * @param pane Pane
    1562  */
    1563 static void pane_status_display(pane_t *pane)
     942                if ((unsigned)s_column - 1 < scr_columns)
     943                        fill = scr_columns - (s_column - 1);
     944                else
     945                        fill = 0;
     946
     947                for (j = 0; j < fill; ++j)
     948                        putchar(' ');
     949                console_flush(con);
     950                console_set_style(con, STYLE_NORMAL);
     951        }
     952
     953        pane.rflags |= REDRAW_CARET;
     954}
     955
     956/** Display pane status in the status line. */
     957static void pane_status_display(void)
    1564958{
    1565959        spt_t caret_pt;
     
    1570964        char *text;
    1571965        size_t n;
     966        int pos;
    1572967        size_t nextra;
    1573968        size_t fnw;
    1574969
    1575         tag_get_pt(&pane->caret_pos, &caret_pt);
     970        tag_get_pt(&pane.caret_pos, &caret_pt);
    1576971        spt_get_coord(&caret_pt, &coord);
    1577972
     
    1592987                return;
    1593988
     989        console_set_pos(con, 0, scr_rows - 1);
     990        console_set_style(con, STYLE_INVERTED);
     991
    1594992        /*
    1595993         * Make sure the status fits on the screen. This loop should
     
    1597995         */
    1598996        while (true) {
    1599                 int rc = asprintf(&text, "%d, %d (%d): File '%s'. Ctrl-Q Quit  "
    1600                     "F10 Menu", coord.row, coord.column, last_row, fname);
     997                int rc = asprintf(&text, " %d, %d (%d): File '%s'. Ctrl-Q Quit  Ctrl-S Save  "
     998                    "Ctrl-E Save As", coord.row, coord.column, last_row, fname);
    1601999                if (rc < 0) {
    16021000                        n = 0;
     
    16061004                /* If it already fits, we're done */
    16071005                n = str_width(text);
    1608                 if ((int)n <= pane->columns - 2)
     1006                if (n <= scr_columns - 2)
    16091007                        break;
    16101008
    16111009                /* Compute number of excess characters */
    1612                 nextra = n - (pane->columns - 2);
     1010                nextra = n - (scr_columns - 2);
    16131011                /** With of the file name part */
    16141012                fnw = str_width(fname);
     
    16181016                 * just give up and print a blank status.
    16191017                 */
    1620                 if (nextra > fnw - 2) {
    1621                         text[0] = '\0';
     1018                if (nextra > fnw - 2)
    16221019                        goto finish;
    1623                 }
    16241020
    16251021                /* Compute position where we overwrite with '..\0' */
     
    16381034        }
    16391035
    1640 finish:
    1641         (void) ui_label_set_text(edit.status, text);
    1642         (void) ui_label_paint(edit.status);
     1036        printf("%s", text);
    16431037        free(text);
    16441038        free(fname);
    1645 }
    1646 
    1647 /** Set cursor to reflect position of the caret.
    1648  *
    1649  * @param pane Pane
    1650  */
    1651 static void pane_caret_display(pane_t *pane)
     1039finish:
     1040        /* Fill the rest of the line */
     1041        pos = scr_columns - 1 - n;
     1042        printf("%*s", pos, "");
     1043        console_flush(con);
     1044        console_set_style(con, STYLE_NORMAL);
     1045
     1046        pane.rflags |= REDRAW_CARET;
     1047}
     1048
     1049/** Set cursor to reflect position of the caret. */
     1050static void pane_caret_display(void)
    16521051{
    16531052        spt_t caret_pt;
    16541053        coord_t coord;
    1655         gfx_coord2_t pos;
    1656         gfx_context_t *gc;
    1657 
    1658         tag_get_pt(&pane->caret_pos, &caret_pt);
     1054
     1055        tag_get_pt(&pane.caret_pos, &caret_pt);
    16591056
    16601057        spt_get_coord(&caret_pt, &coord);
    1661 
    1662         gc = ui_window_get_gc(edit.window);
    1663         pos.x = pane->rect.p0.x + coord.column - pane->sh_column;
    1664         pos.y = pane->rect.p0.y + coord.row - pane->sh_row;
    1665 
    1666         (void) gfx_cursor_set_pos(gc, &pos);
    1667 }
    1668 
    1669 /** Destroy pane control.
    1670  *
    1671  * @param arg Argument (pane_t *)
    1672  */
    1673 static void pane_ctl_destroy(void *arg)
    1674 {
    1675         pane_t *pane = (pane_t *)arg;
    1676 
    1677         pane_fini(pane);
    1678 }
    1679 
    1680 /** Paint pane control.
    1681  *
    1682  * @param arg Argument (pane_t *)
    1683  */
    1684 static errno_t pane_ctl_paint(void *arg)
    1685 {
    1686         pane_t *pane = (pane_t *)arg;
    1687         gfx_context_t *gc;
    1688         errno_t rc;
    1689 
    1690         gc = ui_window_get_gc(pane->window);
    1691 
    1692         rc = pane_text_display(pane);
    1693         if (rc != EOK)
    1694                 goto error;
    1695 
    1696         rc = gfx_update(gc);
    1697         if (rc != EOK)
    1698                 goto error;
    1699 
    1700 error:
    1701         return rc;
    1702 }
    1703 
    1704 /** Handle pane control position event.
    1705  *
    1706  * @param arg Argument (pane_t *)
    1707  * @param event Position event
    1708  */
    1709 static ui_evclaim_t pane_ctl_pos_event(void *arg, pos_event_t *event)
    1710 {
    1711         gfx_coord2_t pos;
    1712 
    1713         pos.x = event->hpos;
    1714         pos.y = event->vpos;
    1715 
    1716         if (!gfx_pix_inside_rect(&pos, &pane.rect))
    1717                 return ui_unclaimed;
    1718 
    1719         pos_handle(event);
    1720         (void) gfx_update(ui_window_get_gc(edit.window));
    1721         return ui_claimed;
     1058        console_set_pos(con, coord.column - pane.sh_column,
     1059            coord.row - pane.sh_row);
    17221060}
    17231061
     
    19321270static void caret_go_to_line_ask(void)
    19331271{
    1934         ui_prompt_dialog_params_t pdparams;
    1935         ui_prompt_dialog_t *dialog;
    1936         errno_t rc;
    1937 
    1938         ui_prompt_dialog_params_init(&pdparams);
    1939         pdparams.caption = "Go To Line";
    1940         pdparams.prompt = "Line Number";
    1941 
    1942         rc = ui_prompt_dialog_create(edit.ui, &pdparams, &dialog);
    1943         if (rc != EOK) {
    1944                 printf("Error creating prompt dialog.\n");
     1272        char *sline;
     1273
     1274        sline = prompt("Go to line", "");
     1275        if (sline == NULL) {
     1276                status_display("Go to line cancelled.");
    19451277                return;
    19461278        }
    19471279
    1948         ui_prompt_dialog_set_cb(dialog, &go_to_line_dialog_cb, &edit);
     1280        char *endptr;
     1281        int line = strtol(sline, &endptr, 10);
     1282        if (*endptr != '\0') {
     1283                free(sline);
     1284                status_display("Invalid number entered.");
     1285                return;
     1286        }
     1287        free(sline);
     1288
     1289        caret_move_absolute(line, pane.ideal_column, dir_before, false);
    19491290}
    19501291
     
    20031344static void search_prompt(bool reverse)
    20041345{
    2005         ui_prompt_dialog_params_t pdparams;
    2006         ui_prompt_dialog_t *dialog;
    2007         errno_t rc;
    2008 
    2009         ui_prompt_dialog_params_init(&pdparams);
    2010         pdparams.caption = reverse ? "Reverse Search" : "Search";
    2011         pdparams.prompt = "Search text";
    2012         pdparams.itext = "";
    2013 
     1346        char *pattern;
     1347
     1348        const char *prompt_text = "Find next";
     1349        if (reverse)
     1350                prompt_text = "Find previous";
     1351
     1352        const char *default_value = "";
    20141353        if (pane.previous_search)
    2015                 pdparams.itext = pane.previous_search;
    2016 
    2017         rc = ui_prompt_dialog_create(edit.ui, &pdparams, &dialog);
    2018         if (rc != EOK) {
    2019                 printf("Error creating prompt dialog.\n");
     1354                default_value = pane.previous_search;
     1355
     1356        pattern = prompt(prompt_text, default_value);
     1357        if (pattern == NULL) {
     1358                status_display("Search cancelled.");
    20201359                return;
    20211360        }
    20221361
    2023         ui_prompt_dialog_set_cb(dialog, &search_dialog_cb, &edit);
    2024         pane.search_reverse = reverse;
     1362        if (pane.previous_search)
     1363                free(pane.previous_search);
     1364        pane.previous_search = pattern;
     1365        pane.previous_search_reverse = reverse;
     1366
     1367        search(pattern, reverse);
    20251368}
    20261369
     
    21701513        }
    21711514        free(str);
    2172 }
    2173 
    2174 static void edit_paste(void)
    2175 {
    2176         selection_delete();
    2177         insert_clipboard_data();
    2178         pane.rflags |= (REDRAW_TEXT | REDRAW_CARET);
    2179         pane_update(&pane);
    2180 }
    2181 
    2182 static void edit_cut(void)
    2183 {
    2184         selection_copy();
    2185         selection_delete();
    2186         pane.rflags |= (REDRAW_TEXT | REDRAW_CARET);
    2187         pane_update(&pane);
    21881515}
    21891516
     
    23921719static void status_display(char const *str)
    23931720{
    2394         (void) ui_label_set_text(edit.status, str);
    2395         (void) ui_label_paint(edit.status);
    2396 }
    2397 
    2398 /** Window was resized.
    2399  *
    2400  * @param window Window
    2401  * @param arg Argument (edit_t *)
    2402  */
    2403 static void edit_wnd_resize(ui_window_t *window, void *arg)
    2404 {
    2405         edit_t *edit = (edit_t *) arg;
    2406 
    2407         edit_menubar_set_rect(edit);
    2408         edit_status_set_rect(edit);
    2409         pane_resize(&pane);
    2410 }
    2411 
    2412 /** Window close request
    2413  *
    2414  * @param window Window
    2415  * @param arg Argument (edit_t *)
    2416  */
    2417 static void edit_wnd_close(ui_window_t *window, void *arg)
    2418 {
    2419         edit_t *edit = (edit_t *) arg;
    2420 
    2421         ui_quit(edit->ui);
    2422 }
    2423 
    2424 /** Window focus event
    2425  *
    2426  * @param window Window
    2427  * @param arg Argument (edit_t *)
    2428  * @param focus Focus number
    2429  */
    2430 static void edit_wnd_focus(ui_window_t *window, void *arg, unsigned focus)
    2431 {
    2432         edit_t *edit = (edit_t *)arg;
    2433 
    2434         (void)edit;
    2435         pane_caret_display(&pane);
    2436         cursor_setvis(true);
    2437 }
    2438 
    2439 /** Window keyboard event
    2440  *
    2441  * @param window Window
    2442  * @param arg Argument (edit_t *)
    2443  * @param event Keyboard event
    2444  */
    2445 static void edit_wnd_kbd_event(ui_window_t *window, void *arg,
    2446     kbd_event_t *event)
    2447 {
    2448         pane.keymod = event->mods;
    2449 
    2450         if (ui_window_def_kbd(window, event) == ui_claimed)
    2451                 return;
    2452 
    2453         if (event->type == KEY_PRESS) {
    2454                 key_handle_press(event);
    2455                 (void) pane_update(&pane);
    2456                 (void) gfx_update(ui_window_get_gc(window));
    2457         }
    2458 }
    2459 
    2460 /** Window unfocus event
    2461  *
    2462  * @param window Window
    2463  * @param arg Argument (edit_t *)
    2464  * @param focus Focus number
    2465  */
    2466 static void edit_wnd_unfocus(ui_window_t *window, void *arg, unsigned focus)
    2467 {
    2468         edit_t *edit = (edit_t *) arg;
    2469 
    2470         (void)edit;
    2471         cursor_setvis(false);
    2472 }
    2473 
    2474 /** Menu bar activate event
    2475  *
    2476  * @param mbar Menu bar
    2477  * @param arg Argument (edit_t *)
    2478  */
    2479 static void edit_menubar_activate(ui_menu_bar_t *mbar, void *arg)
    2480 {
    2481         edit_t *edit = (edit_t *)arg;
    2482 
    2483         (void)edit;
    2484         cursor_setvis(false);
    2485 }
    2486 
    2487 /** Menu bar deactivate event
    2488  *
    2489  * @param mbar Menu bar
    2490  * @param arg Argument (edit_t *)
    2491  */
    2492 static void edit_menubar_deactivate(ui_menu_bar_t *mbar, void *arg)
    2493 {
    2494         edit_t *edit = (edit_t *)arg;
    2495 
    2496         (void)edit;
    2497         pane_caret_display(&pane);
    2498         cursor_setvis(true);
    2499 }
    2500 
    2501 /** File / New menu entry selected.
    2502  *
    2503  * @param mentry Menu entry
    2504  * @param arg Argument (edit_t *)
    2505  */
    2506 static void edit_file_new(ui_menu_entry_t *mentry, void *arg)
    2507 {
    2508         edit_t *edit = (edit_t *) arg;
    2509 
    2510         (void)edit;
    2511         file_new();
    2512         (void) gfx_update(ui_window_get_gc(edit->window));
    2513 }
    2514 
    2515 /** File / Open menu entry selected.
    2516  *
    2517  * @param mentry Menu entry
    2518  * @param arg Argument (edit_t *)
    2519  */
    2520 static void edit_file_open(ui_menu_entry_t *mentry, void *arg)
    2521 {
    2522         edit_t *edit = (edit_t *) arg;
    2523 
    2524         (void)edit;
    2525         file_open();
    2526 }
    2527 
    2528 /** File / Save menu entry selected.
    2529  *
    2530  * @param mentry Menu entry
    2531  * @param arg Argument (edit_t *)
    2532  */
    2533 static void edit_file_save(ui_menu_entry_t *mentry, void *arg)
    2534 {
    2535         edit_t *edit = (edit_t *) arg;
    2536 
    2537         (void)edit;
    2538 
    2539         if (doc.file_name != NULL)
    2540                 file_save(doc.file_name);
    2541         else
    2542                 file_save_as();
    2543 }
    2544 
    2545 /** File / Save As menu entry selected.
    2546  *
    2547  * @param mentry Menu entry
    2548  * @param arg Argument (edit_t *)
    2549  */
    2550 static void edit_file_save_as(ui_menu_entry_t *mentry, void *arg)
    2551 {
    2552         edit_t *edit = (edit_t *) arg;
    2553 
    2554         (void)edit;
    2555         file_save_as();
    2556 }
    2557 
    2558 /** File / Exit menu entry selected.
    2559  *
    2560  * @param mentry Menu entry
    2561  * @param arg Argument (edit_t *)
    2562  */
    2563 static void edit_file_exit(ui_menu_entry_t *mentry, void *arg)
    2564 {
    2565         edit_t *edit = (edit_t *) arg;
    2566 
    2567         ui_quit(edit->ui);
    2568 }
    2569 
    2570 /** Edit / Cut menu entry selected.
    2571  *
    2572  * @param mentry Menu entry
    2573  * @param arg Argument (edit_t *)
    2574  */
    2575 static void edit_edit_cut(ui_menu_entry_t *mentry, void *arg)
    2576 {
    2577         (void) arg;
    2578         edit_cut();
    2579         (void) gfx_update(ui_window_get_gc(edit.window));
    2580 }
    2581 
    2582 /** Edit / Copy menu entry selected.
    2583  *
    2584  * @param mentry Menu entry
    2585  * @param arg Argument (edit_t *)
    2586  */
    2587 static void edit_edit_copy(ui_menu_entry_t *mentry, void *arg)
    2588 {
    2589         (void) arg;
    2590         selection_copy();
    2591 }
    2592 
    2593 /** Edit / Paste menu entry selected.
    2594  *
    2595  * @param mentry Menu entry
    2596  * @param arg Argument (edit_t *)
    2597  */
    2598 static void edit_edit_paste(ui_menu_entry_t *mentry, void *arg)
    2599 {
    2600         (void) arg;
    2601         edit_paste();
    2602         (void) gfx_update(ui_window_get_gc(edit.window));
    2603 }
    2604 
    2605 /** Edit / Delete menu entry selected.
    2606  *
    2607  * @param mentry Menu entry
    2608  * @param arg Argument (edit_t *)
    2609  */
    2610 static void edit_edit_delete(ui_menu_entry_t *mentry, void *arg)
    2611 {
    2612         (void) arg;
    2613 
    2614         if (selection_active())
    2615                 selection_delete();
     1721        console_set_pos(con, 0, scr_rows - 1);
     1722        console_set_style(con, STYLE_INVERTED);
     1723
     1724        int pos = -(scr_columns - 3);
     1725        printf(" %*s ", pos, str);
     1726        console_flush(con);
     1727        console_set_style(con, STYLE_NORMAL);
    26161728
    26171729        pane.rflags |= REDRAW_CARET;
    2618         (void) pane_update(&pane);
    2619         (void) gfx_update(ui_window_get_gc(edit.window));
    2620 }
    2621 
    2622 /** Edit / Select All menu entry selected.
    2623  *
    2624  * @param mentry Menu entry
    2625  * @param arg Argument (edit_t *)
    2626  */
    2627 static void edit_edit_select_all(ui_menu_entry_t *mentry, void *arg)
    2628 {
    2629         (void) arg;
    2630 
    2631         selection_sel_all();
    2632         pane.rflags |= (REDRAW_CARET | REDRAW_TEXT | REDRAW_STATUS);
    2633         pane_update(&pane);
    2634         (void) gfx_update(ui_window_get_gc(edit.window));
    2635 }
    2636 
    2637 /** Search / Find menu entry selected.
    2638  *
    2639  * @param mentry Menu entry
    2640  * @param arg Argument (edit_t *)
    2641  */
    2642 static void edit_search_find(ui_menu_entry_t *mentry, void *arg)
    2643 {
    2644         (void) arg;
    2645         search_prompt(false);
    2646 }
    2647 
    2648 /** Search / Reverse Find menu entry selected.
    2649  *
    2650  * @param mentry Menu entry
    2651  * @param arg Argument (edit_t *)
    2652  */
    2653 static void edit_search_reverse_find(ui_menu_entry_t *mentry, void *arg)
    2654 {
    2655         (void) arg;
    2656         search_prompt(true);
    2657 }
    2658 
    2659 /** Search / Find Next menu entry selected.
    2660  *
    2661  * @param mentry Menu entry
    2662  * @param arg Argument (edit_t *)
    2663  */
    2664 static void edit_search_find_next(ui_menu_entry_t *mentry, void *arg)
    2665 {
    2666         (void) arg;
    2667         search_repeat();
    2668         (void) pane_update(&pane);
    2669         (void) gfx_update(ui_window_get_gc(edit.window));
    2670 }
    2671 
    2672 /** Search / Go To Line menu entry selected.
    2673  *
    2674  * @param mentry Menu entry
    2675  * @param arg Argument (edit_t *)
    2676  */
    2677 static void edit_search_go_to_line(ui_menu_entry_t *mentry, void *arg)
    2678 {
    2679         (void) arg;
    2680         caret_go_to_line_ask();
    2681 }
    2682 
    2683 /** Open File dialog OK button press.
    2684  *
    2685  * @param dialog Open File dialog
    2686  * @param arg Argument (ui_demo_t *)
    2687  * @param fname File name
    2688  */
    2689 static void open_dialog_bok(ui_file_dialog_t *dialog, void *arg,
    2690     const char *fname)
    2691 {
    2692         edit_t *edit = (edit_t *)arg;
    2693         char *cname;
    2694         errno_t rc;
    2695 
    2696         (void)edit;
    2697         ui_file_dialog_destroy(dialog);
    2698 
    2699         cname = str_dup(fname);
    2700         if (cname == NULL) {
    2701                 printf("Out of memory.\n");
    2702                 return;
    2703         }
    2704 
    2705         rc = file_open_file(fname);
    2706         if (rc != EOK)
    2707                 return;
    2708 
    2709         if (doc.file_name != NULL)
    2710                 free(doc.file_name);
    2711         doc.file_name = cname;
    2712 
    2713         (void) gfx_update(ui_window_get_gc(edit->window));
    2714 }
    2715 
    2716 /** Open File dialog cancel button press.
    2717  *
    2718  * @param dialog File dialog
    2719  * @param arg Argument (ui_demo_t *)
    2720  */
    2721 static void open_dialog_bcancel(ui_file_dialog_t *dialog, void *arg)
    2722 {
    2723         edit_t *edit = (edit_t *)arg;
    2724 
    2725         (void)edit;
    2726         ui_file_dialog_destroy(dialog);
    2727 }
    2728 
    2729 /** Open File dialog close request.
    2730  *
    2731  * @param dialog File dialog
    2732  * @param arg Argument (ui_demo_t *)
    2733  */
    2734 static void open_dialog_close(ui_file_dialog_t *dialog, void *arg)
    2735 {
    2736         edit_t *edit = (edit_t *)arg;
    2737 
    2738         (void)edit;
    2739         ui_file_dialog_destroy(dialog);
    2740 }
    2741 
    2742 /** Save As dialog OK button press.
    2743  *
    2744  * @param dialog Save As dialog
    2745  * @param arg Argument (ui_demo_t *)
    2746  * @param fname File name
    2747  */
    2748 static void save_as_dialog_bok(ui_file_dialog_t *dialog, void *arg,
    2749     const char *fname)
    2750 {
    2751         edit_t *edit = (edit_t *)arg;
    2752         char *cname;
    2753         errno_t rc;
    2754 
    2755         (void)edit;
    2756         ui_file_dialog_destroy(dialog);
    2757 
    2758         cname = str_dup(fname);
    2759         if (cname == NULL) {
    2760                 printf("Out of memory.\n");
    2761                 return;
    2762         }
    2763 
    2764         rc = file_save(fname);
    2765         if (rc != EOK)
    2766                 return;
    2767 
    2768         if (doc.file_name != NULL)
    2769                 free(doc.file_name);
    2770         doc.file_name = cname;
    2771 
    2772 }
    2773 
    2774 /** Save As dialog cancel button press.
    2775  *
    2776  * @param dialog File dialog
    2777  * @param arg Argument (ui_demo_t *)
    2778  */
    2779 static void save_as_dialog_bcancel(ui_file_dialog_t *dialog, void *arg)
    2780 {
    2781         edit_t *edit = (edit_t *)arg;
    2782 
    2783         (void)edit;
    2784         ui_file_dialog_destroy(dialog);
    2785 }
    2786 
    2787 /** Save As dialog close request.
    2788  *
    2789  * @param dialog File dialog
    2790  * @param arg Argument (ui_demo_t *)
    2791  */
    2792 static void save_as_dialog_close(ui_file_dialog_t *dialog, void *arg)
    2793 {
    2794         edit_t *edit = (edit_t *)arg;
    2795 
    2796         (void)edit;
    2797         ui_file_dialog_destroy(dialog);
    2798 }
    2799 
    2800 /** Go To Line dialog OK button press.
    2801  *
    2802  * @param dialog Go To Line dialog
    2803  * @param arg Argument (ui_demo_t *)
    2804  * @param text Submitted text
    2805  */
    2806 static void go_to_line_dialog_bok(ui_prompt_dialog_t *dialog, void *arg,
    2807     const char *text)
    2808 {
    2809         edit_t *edit = (edit_t *) arg;
    2810         char *endptr;
    2811         int line;
    2812 
    2813         ui_prompt_dialog_destroy(dialog);
    2814         line = strtol(text, &endptr, 10);
    2815         if (*endptr != '\0') {
    2816                 status_display("Invalid number entered.");
    2817                 return;
    2818         }
    2819 
    2820         caret_move_absolute(line, pane.ideal_column, dir_before, false);
    2821         (void)edit;
    2822         (void) pane_update(&pane);
    2823 }
    2824 
    2825 /** Go To Line dialog cancel button press.
    2826  *
    2827  * @param dialog File dialog
    2828  * @param arg Argument (ui_demo_t *)
    2829  */
    2830 static void go_to_line_dialog_bcancel(ui_prompt_dialog_t *dialog, void *arg)
    2831 {
    2832         edit_t *edit = (edit_t *) arg;
    2833 
    2834         (void)edit;
    2835         ui_prompt_dialog_destroy(dialog);
    2836 }
    2837 
    2838 /** Go To Line dialog close request.
    2839  *
    2840  * @param dialog File dialog
    2841  * @param arg Argument (ui_demo_t *)
    2842  */
    2843 static void go_to_line_dialog_close(ui_prompt_dialog_t *dialog, void *arg)
    2844 {
    2845         edit_t *edit = (edit_t *) arg;
    2846 
    2847         (void)edit;
    2848         ui_prompt_dialog_destroy(dialog);
    2849 }
    2850 
    2851 /** Search dialog OK button press.
    2852  *
    2853  * @param dialog Search dialog
    2854  * @param arg Argument (ui_demo_t *)
    2855  * @param text Submitted text
    2856  */
    2857 static void search_dialog_bok(ui_prompt_dialog_t *dialog, void *arg,
    2858     const char *text)
    2859 {
    2860         edit_t *edit = (edit_t *) arg;
    2861         char *pattern;
    2862         bool reverse;
    2863 
    2864         (void)edit;
    2865         ui_prompt_dialog_destroy(dialog);
    2866 
    2867         /* Abort if search phrase is empty */
    2868         if (text[0] == '\0')
    2869                 return;
    2870 
    2871         pattern = str_dup(text);
    2872         reverse = pane.search_reverse;
    2873 
    2874         if (pane.previous_search)
    2875                 free(pane.previous_search);
    2876         pane.previous_search = pattern;
    2877         pane.previous_search_reverse = reverse;
    2878 
    2879         search(pattern, reverse);
    2880 
    2881         (void) pane_update(&pane);
    2882 }
    2883 
    2884 /** Search dialog cancel button press.
    2885  *
    2886  * @param dialog File dialog
    2887  * @param arg Argument (ui_demo_t *)
    2888  */
    2889 static void search_dialog_bcancel(ui_prompt_dialog_t *dialog, void *arg)
    2890 {
    2891         edit_t *edit = (edit_t *) arg;
    2892 
    2893         (void)edit;
    2894         ui_prompt_dialog_destroy(dialog);
    2895 }
    2896 
    2897 /** Search dialog close request.
    2898  *
    2899  * @param dialog File dialog
    2900  * @param arg Argument (ui_demo_t *)
    2901  */
    2902 static void search_dialog_close(ui_prompt_dialog_t *dialog, void *arg)
    2903 {
    2904         edit_t *edit = (edit_t *) arg;
    2905 
    2906         (void)edit;
    2907         ui_prompt_dialog_destroy(dialog);
    29081730}
    29091731
Note: See TracChangeset for help on using the changeset viewer.