Changes in uspace/app/edit/edit.c [87822ce:994f87b] in mainline


Ignore:
File:
1 edited

Legend:

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

    r87822ce r994f87b  
    11/*
    2  * Copyright (c) 2009 Jiri Svoboda
     2 * Copyright (c) 2024 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>
    3851#include <stdio.h>
    3952#include <stdlib.h>
    4053#include <stddef.h>
    4154#include <stdbool.h>
     55#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>
    4268#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>
    50 #include <types/common.h>
    5169
    5270#include "sheet.h"
     
    6381 *
    6482 * A rectangular area of the screen used to edit a document. Different
    65  * panes can be possibly used to edit the same document.
     83 * panes can be possibly used to edit the same document. This is a custom
     84 * UI control.
    6685 */
    6786typedef 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
    68105        /* Pane dimensions */
    69106        int rows, columns;
     
    90127        int ideal_column;
    91128
     129        bool search_reverse;
    92130        char *previous_search;
    93131        bool previous_search_reverse;
    94132} pane_t;
     133
     134/** Text editor */
     135typedef 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;
    95147
    96148/** Document
     
    103155} doc_t;
    104156
    105 static console_ctrl_t *con;
     157static edit_t edit;
    106158static doc_t doc;
    107 static bool done;
    108159static pane_t pane;
    109 static bool cursor_visible;
    110 
    111 static sysarg_t scr_rows;
    112 static sysarg_t scr_columns;
    113160
    114161#define ROW_BUF_SIZE 4096
     
    119166#define INFNAME_MAX_LEN 128
    120167
    121 static void cursor_show(void);
    122 static void cursor_hide(void);
    123168static void cursor_setvis(bool visible);
    124169
     
    132177static void pos_handle(pos_event_t *ev);
    133178
     179static errno_t file_new(void);
     180static void file_open(void);
     181static errno_t file_open_file(const char *fname);
    134182static errno_t file_save(char const *fname);
    135183static void file_save_as(void);
    136 static errno_t file_insert(char *fname);
     184static errno_t file_insert(const char *fname);
    137185static errno_t file_save_range(char const *fname, spt_t const *spos,
    138186    spt_t const *epos);
    139187static char *range_get_str(spt_t const *spos, spt_t const *epos);
    140188
    141 static char *prompt(char const *prompt, char const *init_value);
    142 
    143 static void pane_text_display(void);
     189static errno_t pane_init(ui_window_t *, pane_t *);
     190static void pane_fini(pane_t *);
     191static ui_control_t *pane_ctl(pane_t *);
     192static errno_t pane_update(pane_t *);
     193static errno_t pane_text_display(pane_t *);
    144194static void pane_row_display(void);
    145 static void pane_row_range_display(int r0, int r1);
    146 static void pane_status_display(void);
    147 static void pane_caret_display(void);
     195static errno_t pane_row_range_display(pane_t *, int r0, int r1);
     196static void pane_status_display(pane_t *);
     197static void pane_caret_display(pane_t *);
    148198
    149199static void insert_char(char32_t c);
     
    164214static void selection_delete(void);
    165215static void selection_copy(void);
     216static void edit_cut(void);
     217static void edit_paste(void);
    166218static void insert_clipboard_data(void);
    167219
     
    185237
    186238static void status_display(char const *str);
     239static errno_t edit_ui_create(edit_t *);
     240static void edit_ui_destroy(edit_t *);
     241
     242static void edit_wnd_close(ui_window_t *, void *);
     243static void edit_wnd_focus(ui_window_t *, void *, unsigned);
     244static void edit_wnd_kbd_event(ui_window_t *, void *, kbd_event_t *);
     245static void edit_wnd_unfocus(ui_window_t *, void *, unsigned);
     246
     247static ui_window_cb_t edit_window_cb = {
     248        .close = edit_wnd_close,
     249        .focus = edit_wnd_focus,
     250        .kbd = edit_wnd_kbd_event,
     251        .unfocus = edit_wnd_unfocus
     252};
     253
     254static void edit_menubar_activate(ui_menu_bar_t *, void *);
     255static void edit_menubar_deactivate(ui_menu_bar_t *, void *);
     256
     257static ui_menu_bar_cb_t edit_menubar_cb = {
     258        .activate = edit_menubar_activate,
     259        .deactivate = edit_menubar_deactivate
     260};
     261
     262static void edit_file_new(ui_menu_entry_t *, void *);
     263static void edit_file_open(ui_menu_entry_t *, void *);
     264static void edit_file_save(ui_menu_entry_t *, void *);
     265static void edit_file_save_as(ui_menu_entry_t *, void *);
     266static void edit_file_exit(ui_menu_entry_t *, void *);
     267static void edit_edit_cut(ui_menu_entry_t *, void *);
     268static void edit_edit_copy(ui_menu_entry_t *, void *);
     269static void edit_edit_paste(ui_menu_entry_t *, void *);
     270static void edit_edit_delete(ui_menu_entry_t *, void *);
     271static void edit_edit_select_all(ui_menu_entry_t *, void *);
     272static void edit_search_find(ui_menu_entry_t *, void *);
     273static void edit_search_reverse_find(ui_menu_entry_t *, void *);
     274static void edit_search_find_next(ui_menu_entry_t *, void *);
     275static void edit_search_go_to_line(ui_menu_entry_t *, void *);
     276
     277static void pane_ctl_destroy(void *);
     278static errno_t pane_ctl_paint(void *);
     279static ui_evclaim_t pane_ctl_pos_event(void *, pos_event_t *);
     280
     281/** Pabe control ops */
     282ui_control_ops_t pane_ctl_ops = {
     283        .destroy = pane_ctl_destroy,
     284        .paint = pane_ctl_paint,
     285        .pos_event = pane_ctl_pos_event
     286};
     287
     288static void open_dialog_bok(ui_file_dialog_t *, void *, const char *);
     289static void open_dialog_bcancel(ui_file_dialog_t *, void *);
     290static void open_dialog_close(ui_file_dialog_t *, void *);
     291
     292static ui_file_dialog_cb_t open_dialog_cb = {
     293        .bok = open_dialog_bok,
     294        .bcancel = open_dialog_bcancel,
     295        .close = open_dialog_close
     296};
     297
     298static void save_as_dialog_bok(ui_file_dialog_t *, void *, const char *);
     299static void save_as_dialog_bcancel(ui_file_dialog_t *, void *);
     300static void save_as_dialog_close(ui_file_dialog_t *, void *);
     301
     302static ui_file_dialog_cb_t save_as_dialog_cb = {
     303        .bok = save_as_dialog_bok,
     304        .bcancel = save_as_dialog_bcancel,
     305        .close = save_as_dialog_close
     306};
     307
     308static void go_to_line_dialog_bok(ui_prompt_dialog_t *, void *, const char *);
     309static void go_to_line_dialog_bcancel(ui_prompt_dialog_t *, void *);
     310static void go_to_line_dialog_close(ui_prompt_dialog_t *, void *);
     311
     312static ui_prompt_dialog_cb_t go_to_line_dialog_cb = {
     313        .bok = go_to_line_dialog_bok,
     314        .bcancel = go_to_line_dialog_bcancel,
     315        .close =  go_to_line_dialog_close
     316};
     317
     318static void search_dialog_bok(ui_prompt_dialog_t *, void *, const char *);
     319static void search_dialog_bcancel(ui_prompt_dialog_t *, void *);
     320static void search_dialog_close(ui_prompt_dialog_t *, void *);
     321
     322static ui_prompt_dialog_cb_t search_dialog_cb = {
     323        .bok = search_dialog_bok,
     324        .bcancel = search_dialog_bcancel,
     325        .close =  search_dialog_close
     326};
    187327
    188328int main(int argc, char *argv[])
    189329{
    190         cons_event_t ev;
    191         bool new_file;
    192330        errno_t rc;
    193331
    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;
    201332        pane.sh_row = 1;
    202333        pane.sh_column = 1;
    203334
    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;
     335        /* Create UI */
     336        rc = edit_ui_create(&edit);
     337        if (rc != EOK)
     338                return 1;
    216339
    217340        if (argc == 2) {
    218341                doc.file_name = str_dup(argv[1]);
     342                rc = file_open_file(argv[1]);
     343                if (rc != EOK) {
     344                        status_display("File not found. Starting empty file.");
     345                        rc = file_new();
     346                }
    219347        } else if (argc > 1) {
    220348                printf("Invalid arguments.\n");
    221349                return -2;
    222350        } else {
    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);
     351                rc = file_new();
     352        }
    237353
    238354        /* Initial display */
    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 
     355        rc = ui_window_paint(edit.window);
     356        if (rc != EOK) {
     357                printf("Error painting window.\n");
     358                return rc;
     359        }
     360
     361        ui_run(edit.ui);
     362
     363        edit_ui_destroy(&edit);
    288364        return 0;
     365}
     366
     367/** Create text editor UI.
     368 *
     369 * @param edit Editor
     370 * @return EOK on success or an error code
     371 */
     372static errno_t edit_ui_create(edit_t *edit)
     373{
     374        errno_t rc;
     375        ui_wnd_params_t params;
     376        ui_fixed_t *fixed = NULL;
     377        ui_menu_t *mfile = NULL;
     378        ui_menu_t *medit = NULL;
     379        ui_menu_entry_t *mnew = NULL;
     380        ui_menu_entry_t *mopen = NULL;
     381        ui_menu_entry_t *msave = NULL;
     382        ui_menu_entry_t *msaveas = NULL;
     383        ui_menu_entry_t *mfsep = NULL;
     384        ui_menu_entry_t *mexit = NULL;
     385        ui_menu_entry_t *mcut = NULL;
     386        ui_menu_entry_t *mcopy = NULL;
     387        ui_menu_entry_t *mpaste = NULL;
     388        ui_menu_entry_t *mdelete = NULL;
     389        ui_menu_entry_t *mesep = NULL;
     390        ui_menu_entry_t *mselall = NULL;
     391        ui_menu_t *msearch = NULL;
     392        ui_menu_entry_t *mfind = NULL;
     393        ui_menu_entry_t *mfindr = NULL;
     394        ui_menu_entry_t *mfindn = NULL;
     395        ui_menu_entry_t *mssep = NULL;
     396        ui_menu_entry_t *mgoto = NULL;
     397        gfx_rect_t arect;
     398        gfx_rect_t rect;
     399
     400        rc = ui_create(UI_CONSOLE_DEFAULT, &edit->ui);
     401        if (rc != EOK) {
     402                printf("Error creating UI on display %s.\n",
     403                    UI_CONSOLE_DEFAULT);
     404                goto error;
     405        }
     406
     407        ui_wnd_params_init(&params);
     408        params.caption = "Text Editor";
     409        params.style &= ~ui_wds_decorated;
     410        params.placement = ui_wnd_place_full_screen;
     411
     412        rc = ui_window_create(edit->ui, &params, &edit->window);
     413        if (rc != EOK) {
     414                printf("Error creating window.\n");
     415                goto error;
     416        }
     417
     418        ui_window_set_cb(edit->window, &edit_window_cb, (void *) edit);
     419
     420        edit->ui_res = ui_window_get_res(edit->window);
     421
     422        rc = ui_fixed_create(&fixed);
     423        if (rc != EOK) {
     424                printf("Error creating fixed layout.\n");
     425                return rc;
     426        }
     427
     428        rc = ui_menu_bar_create(edit->ui, edit->window, &edit->menubar);
     429        if (rc != EOK) {
     430                printf("Error creating menu bar.\n");
     431                return rc;
     432        }
     433
     434        ui_menu_bar_set_cb(edit->menubar, &edit_menubar_cb, (void *) edit);
     435
     436        rc = ui_menu_dd_create(edit->menubar, "~F~ile", NULL, &mfile);
     437        if (rc != EOK) {
     438                printf("Error creating menu.\n");
     439                return rc;
     440        }
     441
     442        rc = ui_menu_entry_create(mfile, "~N~ew", "Ctrl-N", &mnew);
     443        if (rc != EOK) {
     444                printf("Error creating menu.\n");
     445                return rc;
     446        }
     447
     448        ui_menu_entry_set_cb(mnew, edit_file_new, (void *) edit);
     449
     450        rc = ui_menu_entry_create(mfile, "~O~pen", "Ctrl-O", &mopen);
     451        if (rc != EOK) {
     452                printf("Error creating menu.\n");
     453                return rc;
     454        }
     455
     456        ui_menu_entry_set_cb(mopen, edit_file_open, (void *) edit);
     457
     458        rc = ui_menu_entry_create(mfile, "~S~ave", "Ctrl-S", &msave);
     459        if (rc != EOK) {
     460                printf("Error creating menu.\n");
     461                return rc;
     462        }
     463
     464        ui_menu_entry_set_cb(msave, edit_file_save, (void *) edit);
     465
     466        rc = ui_menu_entry_create(mfile, "Save ~A~s", "Ctrl-E", &msaveas);
     467        if (rc != EOK) {
     468                printf("Error creating menu.\n");
     469                return rc;
     470        }
     471
     472        ui_menu_entry_set_cb(msaveas, edit_file_save_as, (void *) edit);
     473
     474        rc = ui_menu_entry_sep_create(mfile, &mfsep);
     475        if (rc != EOK) {
     476                printf("Error creating menu.\n");
     477                return rc;
     478        }
     479
     480        rc = ui_menu_entry_create(mfile, "E~x~it", "Ctrl-Q", &mexit);
     481        if (rc != EOK) {
     482                printf("Error creating menu.\n");
     483                return rc;
     484        }
     485
     486        ui_menu_entry_set_cb(mexit, edit_file_exit, (void *) edit);
     487
     488        rc = ui_menu_dd_create(edit->menubar, "~E~dit", NULL, &medit);
     489        if (rc != EOK) {
     490                printf("Error creating menu.\n");
     491                return rc;
     492        }
     493
     494        rc = ui_menu_entry_create(medit, "Cu~t~", "Ctrl-X", &mcut);
     495        if (rc != EOK) {
     496                printf("Error creating menu.\n");
     497                return rc;
     498        }
     499
     500        ui_menu_entry_set_cb(mcut, edit_edit_cut, (void *) edit);
     501
     502        rc = ui_menu_entry_create(medit, "~C~opy", "Ctrl-C", &mcopy);
     503        if (rc != EOK) {
     504                printf("Error creating menu.\n");
     505                return rc;
     506        }
     507
     508        ui_menu_entry_set_cb(mcopy, edit_edit_copy, (void *) edit);
     509
     510        rc = ui_menu_entry_create(medit, "~P~aste", "Ctrl-V", &mpaste);
     511        if (rc != EOK) {
     512                printf("Error creating menu.\n");
     513                return rc;
     514        }
     515
     516        ui_menu_entry_set_cb(mpaste, edit_edit_paste, (void *) edit);
     517
     518        rc = ui_menu_entry_create(medit, "~D~elete", "Del", &mdelete);
     519        if (rc != EOK) {
     520                printf("Error creating menu.\n");
     521                return rc;
     522        }
     523
     524        ui_menu_entry_set_cb(mdelete, edit_edit_delete, (void *) edit);
     525
     526        rc = ui_menu_entry_sep_create(medit, &mesep);
     527        if (rc != EOK) {
     528                printf("Error creating menu.\n");
     529                return rc;
     530        }
     531
     532        rc = ui_menu_entry_create(medit, "Select ~A~ll", "Ctrl-A", &mselall);
     533        if (rc != EOK) {
     534                printf("Error creating menu.\n");
     535                return rc;
     536        }
     537
     538        ui_menu_entry_set_cb(mselall, edit_edit_select_all, (void *) edit);
     539
     540        rc = ui_menu_dd_create(edit->menubar, "~S~earch", NULL, &msearch);
     541        if (rc != EOK) {
     542                printf("Error creating menu.\n");
     543                return rc;
     544        }
     545
     546        rc = ui_menu_entry_create(msearch, "~F~ind", "Ctrl-F", &mfind);
     547        if (rc != EOK) {
     548                printf("Error creating menu.\n");
     549                return rc;
     550        }
     551
     552        ui_menu_entry_set_cb(mfind, edit_search_find, (void *) edit);
     553
     554        rc = ui_menu_entry_create(msearch, "~R~everse Find", "Ctrl-Shift-F", &mfindr);
     555        if (rc != EOK) {
     556                printf("Error creating menu.\n");
     557                return rc;
     558        }
     559
     560        ui_menu_entry_set_cb(mfindr, edit_search_reverse_find, (void *) edit);
     561
     562        rc = ui_menu_entry_create(msearch, "Find ~N~ext", "Ctrl-R", &mfindn);
     563        if (rc != EOK) {
     564                printf("Error creating menu.\n");
     565                return rc;
     566        }
     567
     568        ui_menu_entry_set_cb(mfindn, edit_search_find_next, (void *) edit);
     569
     570        rc = ui_menu_entry_sep_create(msearch, &mssep);
     571        if (rc != EOK) {
     572                printf("Error creating menu.\n");
     573                return rc;
     574        }
     575
     576        rc = ui_menu_entry_create(msearch, "Go To ~L~ine", "Ctrl-L", &mgoto);
     577        if (rc != EOK) {
     578                printf("Error creating menu.\n");
     579                return rc;
     580        }
     581
     582        ui_menu_entry_set_cb(mgoto, edit_search_go_to_line, (void *) edit);
     583
     584        ui_window_get_app_rect(edit->window, &arect);
     585
     586        rect.p0 = arect.p0;
     587        rect.p1.x = arect.p1.x;
     588        rect.p1.y = arect.p0.y + 1;
     589        ui_menu_bar_set_rect(edit->menubar, &rect);
     590
     591        rc = ui_fixed_add(fixed, ui_menu_bar_ctl(edit->menubar));
     592        if (rc != EOK) {
     593                printf("Error adding control to layout.\n");
     594                return rc;
     595        }
     596
     597        rc = pane_init(edit->window, &pane);
     598        if (rc != EOK) {
     599                printf("Error initializing pane.\n");
     600                return rc;
     601        }
     602
     603        rc = ui_fixed_add(fixed, pane_ctl(&pane));
     604        if (rc != EOK) {
     605                printf("Error adding control to layout.\n");
     606                return rc;
     607        }
     608
     609        rc = ui_label_create(edit->ui_res, "", &edit->status);
     610        if (rc != EOK) {
     611                printf("Error creating menu bar.\n");
     612                return rc;
     613        }
     614
     615        rect.p0.x = arect.p0.x;
     616        rect.p0.y = arect.p1.y - 1;
     617        rect.p1 = arect.p1;
     618        ui_label_set_rect(edit->status, &rect);
     619
     620        rc = ui_fixed_add(fixed, ui_label_ctl(edit->status));
     621        if (rc != EOK) {
     622                printf("Error adding control to layout.\n");
     623                return rc;
     624        }
     625
     626        ui_window_add(edit->window, ui_fixed_ctl(fixed));
     627        return EOK;
     628error:
     629        if (edit->window != NULL)
     630                ui_window_destroy(edit->window);
     631        if (edit->ui != NULL)
     632                ui_destroy(edit->ui);
     633        return rc;
     634}
     635
     636/** Destroy text editor UI.
     637 *
     638 * @param edit Editor
     639 */
     640static void edit_ui_destroy(edit_t *edit)
     641{
     642        ui_window_destroy(edit->window);
     643        ui_destroy(edit->ui);
    289644}
    290645
     
    309664}
    310665
    311 static void cursor_show(void)
    312 {
    313         cursor_setvis(true);
    314 }
    315 
    316 static void cursor_hide(void)
    317 {
    318         cursor_setvis(false);
    319 }
    320 
    321666static void cursor_setvis(bool visible)
    322667{
    323         if (cursor_visible != visible) {
    324                 console_cursor_visibility(con, visible);
    325                 cursor_visible = visible;
    326         }
     668        gfx_context_t *gc = ui_window_get_gc(edit.window);
     669
     670        (void) gfx_cursor_set_visible(gc, visible);
    327671}
    328672
     
    400744        switch (ev->key) {
    401745        case KC_Q:
    402                 done = true;
     746                ui_quit(edit.ui);
     747                break;
     748        case KC_N:
     749                file_new();
     750                break;
     751        case KC_O:
     752                file_open();
    403753                break;
    404754        case KC_S:
     
    415765                break;
    416766        case KC_V:
    417                 selection_delete();
    418                 insert_clipboard_data();
    419                 pane.rflags |= REDRAW_TEXT;
    420                 caret_update();
     767                edit_paste();
    421768                break;
    422769        case KC_X:
    423                 selection_copy();
    424                 selection_delete();
    425                 pane.rflags |= REDRAW_TEXT;
    426                 caret_update();
     770                edit_cut();
    427771                break;
    428772        case KC_A:
     
    441785                search_prompt(false);
    442786                break;
    443         case KC_N:
     787        case KC_R:
    444788                search_repeat();
    445789                break;
     
    490834
    491835        if (ev->type == POS_PRESS && ev->vpos < (unsigned)pane.rows) {
    492                 bc.row = pane.sh_row + ev->vpos;
    493                 bc.column = pane.sh_column + ev->hpos;
     836                bc.row = pane.sh_row + ev->vpos - pane.rect.p0.y;
     837                bc.column = pane.sh_column + ev->hpos - pane.rect.p0.x;
    494838                sheet_get_cell_pt(doc.sh, &bc, dir_before, &pt);
    495839
     
    497841
    498842                caret_move(pt, select, true);
     843                pane_update(&pane);
    499844        }
    500845}
     
    579924}
    580925
     926/** Create new document. */
     927static errno_t file_new(void)
     928{
     929        errno_t rc;
     930        sheet_t *sh;
     931
     932        /* Create empty sheet. */
     933        rc = sheet_create(&sh);
     934        if (rc != EOK) {
     935                printf("Out of memory.\n");
     936                return ENOMEM;
     937        }
     938
     939        if (doc.sh != NULL)
     940                sheet_destroy(doc.sh);
     941
     942        doc.sh = sh;
     943
     944        /* Place caret at the beginning of file. */
     945        spt_t sof;
     946        pt_get_sof(&sof);
     947        sheet_place_tag(doc.sh, &sof, &pane.caret_pos);
     948        pane.ideal_column = 1;
     949
     950        doc.file_name = NULL;
     951
     952        /* Place selection start tag. */
     953        sheet_place_tag(doc.sh, &sof, &pane.sel_start);
     954
     955        /* Move to beginning of file. */
     956        pt_get_sof(&sof);
     957
     958        caret_move(sof, true, true);
     959
     960        pane_status_display(&pane);
     961        pane_caret_display(&pane);
     962        pane_text_display(&pane);
     963        cursor_setvis(true);
     964
     965        return EOK;
     966}
     967
     968/** Open Open File dialog. */
     969static void file_open(void)
     970{
     971        const char *old_fname = (doc.file_name != NULL) ? doc.file_name : "";
     972        ui_file_dialog_params_t fdparams;
     973        ui_file_dialog_t *dialog;
     974        errno_t rc;
     975
     976        ui_file_dialog_params_init(&fdparams);
     977        fdparams.caption = "Open File";
     978        fdparams.ifname = old_fname;
     979
     980        rc = ui_file_dialog_create(edit.ui, &fdparams, &dialog);
     981        if (rc != EOK) {
     982                printf("Error creating message dialog.\n");
     983                return;
     984        }
     985
     986        ui_file_dialog_set_cb(dialog, &open_dialog_cb, &edit);
     987}
     988
     989/** Open exising document. */
     990static errno_t file_open_file(const char *fname)
     991{
     992        errno_t rc;
     993        sheet_t *sh;
     994        char *fn;
     995
     996        /* Create empty sheet. */
     997        rc = sheet_create(&sh);
     998        if (rc != EOK) {
     999                printf("Out of memory.\n");
     1000                return ENOMEM;
     1001        }
     1002
     1003        fn = str_dup(fname);
     1004        if (fn == NULL) {
     1005                sheet_destroy(sh);
     1006                return ENOMEM;
     1007        }
     1008
     1009        if (doc.sh != NULL)
     1010                sheet_destroy(doc.sh);
     1011
     1012        doc.sh = sh;
     1013
     1014        /* Place caret at the beginning of file. */
     1015        spt_t sof;
     1016        pt_get_sof(&sof);
     1017        sheet_place_tag(doc.sh, &sof, &pane.caret_pos);
     1018        pane.ideal_column = 1;
     1019
     1020        rc = file_insert(fname);
     1021        if (rc != EOK)
     1022                return rc;
     1023
     1024        doc.file_name = fn;
     1025
     1026        /* Place selection start tag. */
     1027        sheet_place_tag(doc.sh, &sof, &pane.sel_start);
     1028
     1029        /* Move to beginning of file. */
     1030        pt_get_sof(&sof);
     1031
     1032        caret_move(sof, true, true);
     1033
     1034        pane_status_display(&pane);
     1035        pane_caret_display(&pane);
     1036        pane_text_display(&pane);
     1037        cursor_setvis(true);
     1038
     1039        return EOK;
     1040}
     1041
    5811042/** Save the document. */
    5821043static errno_t file_save(char const *fname)
     
    6061067}
    6071068
    608 /** Change document name and save. */
     1069/** Open Save As dialog. */
    6091070static void file_save_as(void)
    6101071{
    6111072        const char *old_fname = (doc.file_name != NULL) ? doc.file_name : "";
    612         char *fname;
    613 
    614         fname = prompt("Save As", old_fname);
    615         if (fname == NULL) {
    616                 status_display("Save cancelled.");
     1073        ui_file_dialog_params_t fdparams;
     1074        ui_file_dialog_t *dialog;
     1075        errno_t rc;
     1076
     1077        ui_file_dialog_params_init(&fdparams);
     1078        fdparams.caption = "Save As";
     1079        fdparams.ifname = old_fname;
     1080
     1081        rc = ui_file_dialog_create(edit.ui, &fdparams, &dialog);
     1082        if (rc != EOK) {
     1083                printf("Error creating message dialog.\n");
    6171084                return;
    6181085        }
    6191086
    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. */
    630 static 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;
    639         errno_t rc;
    640 
    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;
     1087        ui_file_dialog_set_cb(dialog, &save_as_dialog_cb, &edit);
    6941088}
    6951089
     
    6991093 * of the caret.
    7001094 */
    701 static errno_t file_insert(char *fname)
     1095static errno_t file_insert(const char *fname)
    7021096{
    7031097        FILE *f;
     
    7261120
    7271121                bcnt -= off;
    728                 memcpy(buf, buf + off, bcnt);
     1122                memmove(buf, buf + off, bcnt);
    7291123
    7301124                insert_char(c);
     
    8081202}
    8091203
    810 static void pane_text_display(void)
    811 {
     1204/** Initialize pane.
     1205 *
     1206 * TODO: Replace with pane_create() that allocates the pane.
     1207 *
     1208 * @param window Editor window
     1209 * @param pane Pane
     1210 * @return EOK on success or an error code
     1211 */
     1212static errno_t pane_init(ui_window_t *window, pane_t *pane)
     1213{
     1214        errno_t rc;
     1215        gfx_rect_t arect;
     1216
     1217        pane->control = NULL;
     1218        pane->color = NULL;
     1219        pane->sel_color = NULL;
     1220
     1221        rc = ui_control_new(&pane_ctl_ops, (void *) pane, &pane->control);
     1222        if (rc != EOK)
     1223                goto error;
     1224
     1225        rc = gfx_color_new_ega(0x07, &pane->color);
     1226        if (rc != EOK)
     1227                goto error;
     1228
     1229        rc = gfx_color_new_ega(0x1e, &pane->sel_color);
     1230        if (rc != EOK)
     1231                goto error;
     1232
     1233        pane->res = ui_window_get_res(window);
     1234        pane->window = window;
     1235
     1236        ui_window_get_app_rect(window, &arect);
     1237        pane->rect.p0.x = arect.p0.x;
     1238        pane->rect.p0.y = arect.p0.y + 1;
     1239        pane->rect.p1.x = arect.p1.x;
     1240        pane->rect.p1.y = arect.p1.y - 1;
     1241
     1242        pane->columns = pane->rect.p1.x - pane->rect.p0.x;
     1243        pane->rows = pane->rect.p1.y - pane->rect.p0.y;
     1244
     1245        return EOK;
     1246error:
     1247        if (pane->control != NULL) {
     1248                ui_control_delete(pane->control);
     1249                pane->control = NULL;
     1250        }
     1251
     1252        if (pane->color != NULL) {
     1253                gfx_color_delete(pane->color);
     1254                pane->color = NULL;
     1255        }
     1256
     1257        return rc;
     1258}
     1259
     1260/** Finalize pane.
     1261 *
     1262 * TODO: Replace with pane_destroy() that deallocates the pane.
     1263 *
     1264 * @param pane Pane
     1265 */
     1266static void pane_fini(pane_t *pane)
     1267{
     1268        gfx_color_delete(pane->color);
     1269        pane->color = NULL;
     1270        gfx_color_delete(pane->sel_color);
     1271        pane->sel_color = NULL;
     1272        ui_control_delete(pane->control);
     1273        pane->control = NULL;
     1274}
     1275
     1276/** Return base control object for a pane.
     1277 *
     1278 * @param pane Pane
     1279 * @return Base UI cntrol
     1280 */
     1281static ui_control_t *pane_ctl(pane_t *pane)
     1282{
     1283        return pane->control;
     1284}
     1285
     1286/** Repaint parts of pane that need updating.
     1287 *
     1288 * @param pane Pane
     1289 * @return EOK on succes or an error code
     1290 */
     1291static errno_t pane_update(pane_t *pane)
     1292{
     1293        errno_t rc;
     1294
     1295        if (pane->rflags & REDRAW_TEXT) {
     1296                rc = pane_text_display(pane);
     1297                if (rc != EOK)
     1298                        return rc;
     1299        }
     1300
     1301        if (pane->rflags & REDRAW_ROW)
     1302                pane_row_display();
     1303
     1304        if (pane->rflags & REDRAW_STATUS)
     1305                pane_status_display(pane);
     1306
     1307        if (pane->rflags & REDRAW_CARET)
     1308                pane_caret_display(pane);
     1309
     1310        pane->rflags &= ~(REDRAW_TEXT | REDRAW_ROW | REDRAW_STATUS |
     1311            REDRAW_CARET);
     1312        return EOK;
     1313}
     1314
     1315/** Display pane text.
     1316 *
     1317 * @param pane Pane
     1318 * @return EOK on success or an error code
     1319 */
     1320static errno_t pane_text_display(pane_t *pane)
     1321{
     1322        gfx_rect_t rect;
     1323        gfx_context_t *gc;
     1324        errno_t rc;
    8121325        int sh_rows, rows;
    8131326
    8141327        sheet_get_num_rows(doc.sh, &sh_rows);
    815         rows = min(sh_rows - pane.sh_row + 1, pane.rows);
     1328        rows = min(sh_rows - pane->sh_row + 1, pane->rows);
    8161329
    8171330        /* Draw rows from the sheet. */
    8181331
    819         console_set_pos(con, 0, 0);
    820         pane_row_range_display(0, rows);
     1332        rc = pane_row_range_display(pane, 0, rows);
     1333        if (rc != EOK)
     1334                return rc;
    8211335
    8221336        /* Clear the remaining rows if file is short. */
    8231337
    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;
     1338        gc = ui_window_get_gc(pane->window);
     1339
     1340        rc = gfx_set_color(gc, pane->color);
     1341        if (rc != EOK)
     1342                goto error;
     1343
     1344        rect.p0.x = pane->rect.p0.x;
     1345        rect.p0.y = pane->rect.p0.y + rows;
     1346        rect.p1.x = pane->rect.p1.x;
     1347        rect.p1.y = pane->rect.p1.y;
     1348
     1349        rc = gfx_fill_rect(gc, &rect);
     1350        if (rc != EOK)
     1351                goto error;
     1352
     1353        pane->rflags &= ~REDRAW_ROW;
     1354        return EOK;
     1355error:
     1356        return rc;
    8351357}
    8361358
     
    8461368
    8471369        ridx = coord.row - pane.sh_row;
    848         pane_row_range_display(ridx, ridx + 1);
     1370        (void) pane_row_range_display(&pane, ridx, ridx + 1);
    8491371        pane.rflags |= (REDRAW_STATUS | REDRAW_CARET);
    8501372}
    8511373
    852 static void pane_row_range_display(int r0, int r1)
    853 {
    854         int i, j, fill;
     1374/** Display a range of rows of text.
     1375 *
     1376 * @param r0 Start row (inclusive)
     1377 * @param r1 End row (exclusive)
     1378 * @return EOk on success or an error code
     1379 */
     1380static errno_t pane_row_range_display(pane_t *pane, int r0, int r1)
     1381{
     1382        int i, fill;
    8551383        spt_t rb, re, dep, pt;
    8561384        coord_t rbc, rec;
    8571385        char row_buf[ROW_BUF_SIZE];
     1386        char cbuf[STR_BOUNDS(1) + 1];
    8581387        char32_t c;
    8591388        size_t pos, size;
     1389        size_t cpos;
    8601390        int s_column;
    8611391        coord_t csel_start, csel_end, ctmp;
     1392        gfx_font_t *font;
     1393        gfx_context_t *gc;
     1394        gfx_text_fmt_t fmt;
     1395        gfx_coord2_t tpos;
     1396        gfx_rect_t rect;
     1397        errno_t rc;
     1398
     1399        font = ui_resource_get_font(edit.ui_res);
     1400        gc = ui_window_get_gc(edit.window);
     1401
     1402        gfx_text_fmt_init(&fmt);
     1403        fmt.font = font;
     1404        fmt.color = pane->color;
    8621405
    8631406        /* Determine selection start and end. */
    8641407
    865         tag_get_pt(&pane.sel_start, &pt);
     1408        tag_get_pt(&pane->sel_start, &pt);
    8661409        spt_get_coord(&pt, &csel_start);
    8671410
    868         tag_get_pt(&pane.caret_pos, &pt);
     1411        tag_get_pt(&pane->caret_pos, &pt);
    8691412        spt_get_coord(&pt, &csel_end);
    8701413
     
    8771420        /* Draw rows from the sheet. */
    8781421
    879         console_set_pos(con, 0, 0);
    8801422        for (i = r0; i < r1; ++i) {
     1423                tpos.x = pane->rect.p0.x;
     1424                tpos.y = pane->rect.p0.y + i;
     1425
    8811426                /* Starting point for row display */
    882                 rbc.row = pane.sh_row + i;
    883                 rbc.column = pane.sh_column;
     1427                rbc.row = pane->sh_row + i;
     1428                rbc.column = pane->sh_column;
    8841429                sheet_get_cell_pt(doc.sh, &rbc, dir_before, &rb);
    8851430
    8861431                /* Ending point for row display */
    887                 rec.row = pane.sh_row + i;
    888                 rec.column = pane.sh_column + pane.columns;
     1432                rec.row = pane->sh_row + i;
     1433                rec.column = pane->sh_column + pane->columns;
    8891434                sheet_get_cell_pt(doc.sh, &rec, dir_before, &re);
    8901435
     
    8961441                if (coord_cmp(&csel_start, &rbc) <= 0 &&
    8971442                    coord_cmp(&rbc, &csel_end) < 0) {
    898                         console_flush(con);
    899                         console_set_style(con, STYLE_SELECTED);
    900                         console_flush(con);
     1443                        fmt.color = pane->sel_color;
    9011444                }
    9021445
    903                 console_set_pos(con, 0, i);
    9041446                size = str_size(row_buf);
    9051447                pos = 0;
    906                 s_column = pane.sh_column;
     1448                s_column = pane->sh_column;
    9071449                while (pos < size) {
    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                         }
     1450                        if ((csel_start.row == rbc.row) && (csel_start.column == s_column))
     1451                                fmt.color = pane->sel_color;
     1452
     1453                        if ((csel_end.row == rbc.row) && (csel_end.column == s_column))
     1454                                fmt.color = pane->color;
    9191455
    9201456                        c = str_decode(row_buf, &pos, size);
    9211457                        if (c != '\t') {
    922                                 printf("%lc", (wint_t) c);
     1458                                cpos = 0;
     1459                                rc = chr_encode(c, cbuf, &cpos, sizeof(cbuf));
     1460                                if (rc != EOK)
     1461                                        return rc;
     1462
     1463                                rc = gfx_puttext(&tpos, &fmt, cbuf);
     1464                                if (rc != EOK)
     1465                                        return rc;
     1466
    9231467                                s_column += 1;
     1468                                tpos.x++;
    9241469                        } else {
    9251470                                fill = 1 + ALIGN_UP(s_column, TAB_WIDTH) -
    9261471                                    s_column;
    9271472
    928                                 for (j = 0; j < fill; ++j)
    929                                         putchar(' ');
     1473                                rc = gfx_set_color(gc, fmt.color);
     1474                                if (rc != EOK)
     1475                                        return rc;
     1476
     1477                                rect.p0.x = tpos.x;
     1478                                rect.p0.y = tpos.y;
     1479                                rect.p1.x = tpos.x + fill;
     1480                                rect.p1.y = tpos.y + 1;
     1481
     1482                                rc = gfx_fill_rect(gc, &rect);
     1483                                if (rc != EOK)
     1484                                        return rc;
     1485
    9301486                                s_column += fill;
     1487                                tpos.x += fill;
    9311488                        }
    9321489                }
    9331490
    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                 }
     1491                if ((csel_end.row == rbc.row) && (csel_end.column == s_column))
     1492                        fmt.color = pane->color;
    9391493
    9401494                /* Fill until the end of display area. */
    9411495
    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. */
    957 static void pane_status_display(void)
     1496                rc = gfx_set_color(gc, fmt.color);
     1497                if (rc != EOK)
     1498                        return rc;
     1499
     1500                rect.p0.x = tpos.x;
     1501                rect.p0.y = tpos.y;
     1502                rect.p1.x = pane->rect.p1.x;
     1503                rect.p1.y = tpos.y + 1;
     1504
     1505                rc = gfx_fill_rect(gc, &rect);
     1506                if (rc != EOK)
     1507                        return rc;
     1508        }
     1509
     1510        return EOK;
     1511}
     1512
     1513/** Display pane status in the status line.
     1514 *
     1515 * @param pane Pane
     1516 */
     1517static void pane_status_display(pane_t *pane)
    9581518{
    9591519        spt_t caret_pt;
     
    9641524        char *text;
    9651525        size_t n;
    966         int pos;
    9671526        size_t nextra;
    9681527        size_t fnw;
    9691528
    970         tag_get_pt(&pane.caret_pos, &caret_pt);
     1529        tag_get_pt(&pane->caret_pos, &caret_pt);
    9711530        spt_get_coord(&caret_pt, &coord);
    9721531
     
    9871546                return;
    9881547
    989         console_set_pos(con, 0, scr_rows - 1);
    990         console_set_style(con, STYLE_INVERTED);
    991 
    9921548        /*
    9931549         * Make sure the status fits on the screen. This loop should
     
    9951551         */
    9961552        while (true) {
    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);
     1553                int rc = asprintf(&text, "%d, %d (%d): File '%s'. Ctrl-Q Quit  "
     1554                    "F10 Menu", coord.row, coord.column, last_row, fname);
    9991555                if (rc < 0) {
    10001556                        n = 0;
     
    10041560                /* If it already fits, we're done */
    10051561                n = str_width(text);
    1006                 if (n <= scr_columns - 2)
     1562                if ((int)n <= pane->columns - 2)
    10071563                        break;
    10081564
    10091565                /* Compute number of excess characters */
    1010                 nextra = n - (scr_columns - 2);
     1566                nextra = n - (pane->columns - 2);
    10111567                /** With of the file name part */
    10121568                fnw = str_width(fname);
     
    10161572                 * just give up and print a blank status.
    10171573                 */
    1018                 if (nextra > fnw - 2)
     1574                if (nextra > fnw - 2) {
     1575                        text[0] = '\0';
    10191576                        goto finish;
     1577                }
    10201578
    10211579                /* Compute position where we overwrite with '..\0' */
     
    10341592        }
    10351593
    1036         printf("%s", text);
     1594finish:
     1595        (void) ui_label_set_text(edit.status, text);
     1596        (void) ui_label_paint(edit.status);
    10371597        free(text);
    10381598        free(fname);
    1039 finish:
    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. */
    1050 static void pane_caret_display(void)
     1599}
     1600
     1601/** Set cursor to reflect position of the caret.
     1602 *
     1603 * @param pane Pane
     1604 */
     1605static void pane_caret_display(pane_t *pane)
    10511606{
    10521607        spt_t caret_pt;
    10531608        coord_t coord;
    1054 
    1055         tag_get_pt(&pane.caret_pos, &caret_pt);
     1609        gfx_coord2_t pos;
     1610        gfx_context_t *gc;
     1611
     1612        tag_get_pt(&pane->caret_pos, &caret_pt);
    10561613
    10571614        spt_get_coord(&caret_pt, &coord);
    1058         console_set_pos(con, coord.column - pane.sh_column,
    1059             coord.row - pane.sh_row);
     1615
     1616        gc = ui_window_get_gc(edit.window);
     1617        pos.x = pane->rect.p0.x + coord.column - pane->sh_column;
     1618        pos.y = pane->rect.p0.y + coord.row - pane->sh_row;
     1619
     1620        (void) gfx_cursor_set_pos(gc, &pos);
     1621}
     1622
     1623/** Destroy pane control.
     1624 *
     1625 * @param arg Argument (pane_t *)
     1626 */
     1627static void pane_ctl_destroy(void *arg)
     1628{
     1629        pane_t *pane = (pane_t *)arg;
     1630
     1631        pane_fini(pane);
     1632}
     1633
     1634/** Paint pane control.
     1635 *
     1636 * @param arg Argument (pane_t *)
     1637 */
     1638static errno_t pane_ctl_paint(void *arg)
     1639{
     1640        pane_t *pane = (pane_t *)arg;
     1641        gfx_context_t *gc;
     1642        errno_t rc;
     1643
     1644        gc = ui_window_get_gc(pane->window);
     1645
     1646        rc = pane_text_display(pane);
     1647        if (rc != EOK)
     1648                goto error;
     1649
     1650        rc = gfx_update(gc);
     1651        if (rc != EOK)
     1652                goto error;
     1653
     1654error:
     1655        return rc;
     1656}
     1657
     1658/** Handle pane control position event.
     1659 *
     1660 * @param arg Argument (pane_t *)
     1661 * @param event Position event
     1662 */
     1663static ui_evclaim_t pane_ctl_pos_event(void *arg, pos_event_t *event)
     1664{
     1665        gfx_coord2_t pos;
     1666
     1667        pos.x = event->hpos;
     1668        pos.y = event->vpos;
     1669
     1670        if (!gfx_pix_inside_rect(&pos, &pane.rect))
     1671                return ui_unclaimed;
     1672
     1673        pos_handle(event);
     1674        (void) gfx_update(ui_window_get_gc(edit.window));
     1675        return ui_claimed;
    10601676}
    10611677
     
    12701886static void caret_go_to_line_ask(void)
    12711887{
    1272         char *sline;
    1273 
    1274         sline = prompt("Go to line", "");
    1275         if (sline == NULL) {
    1276                 status_display("Go to line cancelled.");
     1888        ui_prompt_dialog_params_t pdparams;
     1889        ui_prompt_dialog_t *dialog;
     1890        errno_t rc;
     1891
     1892        ui_prompt_dialog_params_init(&pdparams);
     1893        pdparams.caption = "Go To Line";
     1894        pdparams.prompt = "Line Number";
     1895
     1896        rc = ui_prompt_dialog_create(edit.ui, &pdparams, &dialog);
     1897        if (rc != EOK) {
     1898                printf("Error creating prompt dialog.\n");
    12771899                return;
    12781900        }
    12791901
    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);
     1902        ui_prompt_dialog_set_cb(dialog, &go_to_line_dialog_cb, &edit);
    12901903}
    12911904
     
    13441957static void search_prompt(bool reverse)
    13451958{
    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 = "";
     1959        ui_prompt_dialog_params_t pdparams;
     1960        ui_prompt_dialog_t *dialog;
     1961        errno_t rc;
     1962
     1963        ui_prompt_dialog_params_init(&pdparams);
     1964        pdparams.caption = reverse ? "Reverse Search" : "Search";
     1965        pdparams.prompt = "Search text";
     1966        pdparams.itext = "";
     1967
    13531968        if (pane.previous_search)
    1354                 default_value = pane.previous_search;
    1355 
    1356         pattern = prompt(prompt_text, default_value);
    1357         if (pattern == NULL) {
    1358                 status_display("Search cancelled.");
     1969                pdparams.itext = pane.previous_search;
     1970
     1971        rc = ui_prompt_dialog_create(edit.ui, &pdparams, &dialog);
     1972        if (rc != EOK) {
     1973                printf("Error creating prompt dialog.\n");
    13591974                return;
    13601975        }
    13611976
    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);
     1977        ui_prompt_dialog_set_cb(dialog, &search_dialog_cb, &edit);
     1978        pane.search_reverse = reverse;
    13681979}
    13691980
     
    15132124        }
    15142125        free(str);
     2126}
     2127
     2128static void edit_paste(void)
     2129{
     2130        selection_delete();
     2131        insert_clipboard_data();
     2132        pane.rflags |= (REDRAW_TEXT | REDRAW_CARET);
     2133        pane_update(&pane);
     2134}
     2135
     2136static void edit_cut(void)
     2137{
     2138        selection_copy();
     2139        selection_delete();
     2140        pane.rflags |= (REDRAW_TEXT | REDRAW_CARET);
     2141        pane_update(&pane);
    15152142}
    15162143
     
    17192346static void status_display(char const *str)
    17202347{
    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);
     2348        (void) ui_label_set_text(edit.status, str);
     2349        (void) ui_label_paint(edit.status);
     2350}
     2351
     2352/** Window close request
     2353 *
     2354 * @param window Window
     2355 * @param arg Argument (edit_t *)
     2356 */
     2357static void edit_wnd_close(ui_window_t *window, void *arg)
     2358{
     2359        edit_t *edit = (edit_t *) arg;
     2360
     2361        ui_quit(edit->ui);
     2362}
     2363
     2364/** Window focus event
     2365 *
     2366 * @param window Window
     2367 * @param arg Argument (edit_t *)
     2368 * @param focus Focus number
     2369 */
     2370static void edit_wnd_focus(ui_window_t *window, void *arg, unsigned focus)
     2371{
     2372        edit_t *edit = (edit_t *)arg;
     2373
     2374        (void)edit;
     2375        pane_caret_display(&pane);
     2376        cursor_setvis(true);
     2377}
     2378
     2379/** Window keyboard event
     2380 *
     2381 * @param window Window
     2382 * @param arg Argument (edit_t *)
     2383 * @param event Keyboard event
     2384 */
     2385static void edit_wnd_kbd_event(ui_window_t *window, void *arg,
     2386    kbd_event_t *event)
     2387{
     2388        pane.keymod = event->mods;
     2389
     2390        if (ui_window_def_kbd(window, event) == ui_claimed)
     2391                return;
     2392
     2393        if (event->type == KEY_PRESS) {
     2394                key_handle_press(event);
     2395                (void) pane_update(&pane);
     2396                (void) gfx_update(ui_window_get_gc(window));
     2397        }
     2398}
     2399
     2400/** Window unfocus event
     2401 *
     2402 * @param window Window
     2403 * @param arg Argument (edit_t *)
     2404 * @param focus Focus number
     2405 */
     2406static void edit_wnd_unfocus(ui_window_t *window, void *arg, unsigned focus)
     2407{
     2408        edit_t *edit = (edit_t *) arg;
     2409
     2410        (void)edit;
     2411        cursor_setvis(false);
     2412}
     2413
     2414/** Menu bar activate event
     2415 *
     2416 * @param mbar Menu bar
     2417 * @param arg Argument (edit_t *)
     2418 */
     2419static void edit_menubar_activate(ui_menu_bar_t *mbar, void *arg)
     2420{
     2421        edit_t *edit = (edit_t *)arg;
     2422
     2423        (void)edit;
     2424        cursor_setvis(false);
     2425}
     2426
     2427/** Menu bar deactivate event
     2428 *
     2429 * @param mbar Menu bar
     2430 * @param arg Argument (edit_t *)
     2431 */
     2432static void edit_menubar_deactivate(ui_menu_bar_t *mbar, void *arg)
     2433{
     2434        edit_t *edit = (edit_t *)arg;
     2435
     2436        (void)edit;
     2437        pane_caret_display(&pane);
     2438        cursor_setvis(true);
     2439}
     2440
     2441/** File / New menu entry selected.
     2442 *
     2443 * @param mentry Menu entry
     2444 * @param arg Argument (edit_t *)
     2445 */
     2446static void edit_file_new(ui_menu_entry_t *mentry, void *arg)
     2447{
     2448        edit_t *edit = (edit_t *) arg;
     2449
     2450        (void)edit;
     2451        file_new();
     2452        (void) gfx_update(ui_window_get_gc(edit->window));
     2453}
     2454
     2455/** File / Open menu entry selected.
     2456 *
     2457 * @param mentry Menu entry
     2458 * @param arg Argument (edit_t *)
     2459 */
     2460static void edit_file_open(ui_menu_entry_t *mentry, void *arg)
     2461{
     2462        edit_t *edit = (edit_t *) arg;
     2463
     2464        (void)edit;
     2465        file_open();
     2466}
     2467
     2468/** File / Save menu entry selected.
     2469 *
     2470 * @param mentry Menu entry
     2471 * @param arg Argument (edit_t *)
     2472 */
     2473static void edit_file_save(ui_menu_entry_t *mentry, void *arg)
     2474{
     2475        edit_t *edit = (edit_t *) arg;
     2476
     2477        (void)edit;
     2478
     2479        if (doc.file_name != NULL)
     2480                file_save(doc.file_name);
     2481        else
     2482                file_save_as();
     2483}
     2484
     2485/** File / Save As menu entry selected.
     2486 *
     2487 * @param mentry Menu entry
     2488 * @param arg Argument (edit_t *)
     2489 */
     2490static void edit_file_save_as(ui_menu_entry_t *mentry, void *arg)
     2491{
     2492        edit_t *edit = (edit_t *) arg;
     2493
     2494        (void)edit;
     2495        file_save_as();
     2496}
     2497
     2498/** File / Exit menu entry selected.
     2499 *
     2500 * @param mentry Menu entry
     2501 * @param arg Argument (edit_t *)
     2502 */
     2503static void edit_file_exit(ui_menu_entry_t *mentry, void *arg)
     2504{
     2505        edit_t *edit = (edit_t *) arg;
     2506
     2507        ui_quit(edit->ui);
     2508}
     2509
     2510/** Edit / Cut menu entry selected.
     2511 *
     2512 * @param mentry Menu entry
     2513 * @param arg Argument (edit_t *)
     2514 */
     2515static void edit_edit_cut(ui_menu_entry_t *mentry, void *arg)
     2516{
     2517        (void) arg;
     2518        edit_cut();
     2519        (void) gfx_update(ui_window_get_gc(edit.window));
     2520}
     2521
     2522/** Edit / Copy menu entry selected.
     2523 *
     2524 * @param mentry Menu entry
     2525 * @param arg Argument (edit_t *)
     2526 */
     2527static void edit_edit_copy(ui_menu_entry_t *mentry, void *arg)
     2528{
     2529        (void) arg;
     2530        selection_copy();
     2531}
     2532
     2533/** Edit / Paste menu entry selected.
     2534 *
     2535 * @param mentry Menu entry
     2536 * @param arg Argument (edit_t *)
     2537 */
     2538static void edit_edit_paste(ui_menu_entry_t *mentry, void *arg)
     2539{
     2540        (void) arg;
     2541        edit_paste();
     2542        (void) gfx_update(ui_window_get_gc(edit.window));
     2543}
     2544
     2545/** Edit / Delete menu entry selected.
     2546 *
     2547 * @param mentry Menu entry
     2548 * @param arg Argument (edit_t *)
     2549 */
     2550static void edit_edit_delete(ui_menu_entry_t *mentry, void *arg)
     2551{
     2552        (void) arg;
     2553
     2554        if (selection_active())
     2555                selection_delete();
    17282556
    17292557        pane.rflags |= REDRAW_CARET;
     2558        (void) pane_update(&pane);
     2559        (void) gfx_update(ui_window_get_gc(edit.window));
     2560}
     2561
     2562/** Edit / Select All menu entry selected.
     2563 *
     2564 * @param mentry Menu entry
     2565 * @param arg Argument (edit_t *)
     2566 */
     2567static void edit_edit_select_all(ui_menu_entry_t *mentry, void *arg)
     2568{
     2569        (void) arg;
     2570
     2571        selection_sel_all();
     2572        pane.rflags |= (REDRAW_CARET | REDRAW_TEXT | REDRAW_STATUS);
     2573        pane_update(&pane);
     2574        (void) gfx_update(ui_window_get_gc(edit.window));
     2575}
     2576
     2577/** Search / Find menu entry selected.
     2578 *
     2579 * @param mentry Menu entry
     2580 * @param arg Argument (edit_t *)
     2581 */
     2582static void edit_search_find(ui_menu_entry_t *mentry, void *arg)
     2583{
     2584        (void) arg;
     2585        search_prompt(false);
     2586}
     2587
     2588/** Search / Reverse Find menu entry selected.
     2589 *
     2590 * @param mentry Menu entry
     2591 * @param arg Argument (edit_t *)
     2592 */
     2593static void edit_search_reverse_find(ui_menu_entry_t *mentry, void *arg)
     2594{
     2595        (void) arg;
     2596        search_prompt(true);
     2597}
     2598
     2599/** Search / Find Next menu entry selected.
     2600 *
     2601 * @param mentry Menu entry
     2602 * @param arg Argument (edit_t *)
     2603 */
     2604static void edit_search_find_next(ui_menu_entry_t *mentry, void *arg)
     2605{
     2606        (void) arg;
     2607        search_repeat();
     2608        (void) pane_update(&pane);
     2609        (void) gfx_update(ui_window_get_gc(edit.window));
     2610}
     2611
     2612/** Search / Go To Line menu entry selected.
     2613 *
     2614 * @param mentry Menu entry
     2615 * @param arg Argument (edit_t *)
     2616 */
     2617static void edit_search_go_to_line(ui_menu_entry_t *mentry, void *arg)
     2618{
     2619        (void) arg;
     2620        caret_go_to_line_ask();
     2621}
     2622
     2623/** Open File dialog OK button press.
     2624 *
     2625 * @param dialog Open File dialog
     2626 * @param arg Argument (ui_demo_t *)
     2627 * @param fname File name
     2628 */
     2629static void open_dialog_bok(ui_file_dialog_t *dialog, void *arg,
     2630    const char *fname)
     2631{
     2632        edit_t *edit = (edit_t *)arg;
     2633        char *cname;
     2634        errno_t rc;
     2635
     2636        (void)edit;
     2637        ui_file_dialog_destroy(dialog);
     2638
     2639        cname = str_dup(fname);
     2640        if (cname == NULL) {
     2641                printf("Out of memory.\n");
     2642                return;
     2643        }
     2644
     2645        rc = file_open_file(fname);
     2646        if (rc != EOK)
     2647                return;
     2648
     2649        if (doc.file_name != NULL)
     2650                free(doc.file_name);
     2651        doc.file_name = cname;
     2652
     2653        (void) gfx_update(ui_window_get_gc(edit->window));
     2654}
     2655
     2656/** Open File dialog cancel button press.
     2657 *
     2658 * @param dialog File dialog
     2659 * @param arg Argument (ui_demo_t *)
     2660 */
     2661static void open_dialog_bcancel(ui_file_dialog_t *dialog, void *arg)
     2662{
     2663        edit_t *edit = (edit_t *)arg;
     2664
     2665        (void)edit;
     2666        ui_file_dialog_destroy(dialog);
     2667}
     2668
     2669/** Open File dialog close request.
     2670 *
     2671 * @param dialog File dialog
     2672 * @param arg Argument (ui_demo_t *)
     2673 */
     2674static void open_dialog_close(ui_file_dialog_t *dialog, void *arg)
     2675{
     2676        edit_t *edit = (edit_t *)arg;
     2677
     2678        (void)edit;
     2679        ui_file_dialog_destroy(dialog);
     2680}
     2681
     2682/** Save As dialog OK button press.
     2683 *
     2684 * @param dialog Save As dialog
     2685 * @param arg Argument (ui_demo_t *)
     2686 * @param fname File name
     2687 */
     2688static void save_as_dialog_bok(ui_file_dialog_t *dialog, void *arg,
     2689    const char *fname)
     2690{
     2691        edit_t *edit = (edit_t *)arg;
     2692        char *cname;
     2693        errno_t rc;
     2694
     2695        (void)edit;
     2696        ui_file_dialog_destroy(dialog);
     2697
     2698        cname = str_dup(fname);
     2699        if (cname == NULL) {
     2700                printf("Out of memory.\n");
     2701                return;
     2702        }
     2703
     2704        rc = file_save(fname);
     2705        if (rc != EOK)
     2706                return;
     2707
     2708        if (doc.file_name != NULL)
     2709                free(doc.file_name);
     2710        doc.file_name = cname;
     2711
     2712}
     2713
     2714/** Save As dialog cancel button press.
     2715 *
     2716 * @param dialog File dialog
     2717 * @param arg Argument (ui_demo_t *)
     2718 */
     2719static void save_as_dialog_bcancel(ui_file_dialog_t *dialog, void *arg)
     2720{
     2721        edit_t *edit = (edit_t *)arg;
     2722
     2723        (void)edit;
     2724        ui_file_dialog_destroy(dialog);
     2725}
     2726
     2727/** Save As dialog close request.
     2728 *
     2729 * @param dialog File dialog
     2730 * @param arg Argument (ui_demo_t *)
     2731 */
     2732static void save_as_dialog_close(ui_file_dialog_t *dialog, void *arg)
     2733{
     2734        edit_t *edit = (edit_t *)arg;
     2735
     2736        (void)edit;
     2737        ui_file_dialog_destroy(dialog);
     2738}
     2739
     2740/** Go To Line dialog OK button press.
     2741 *
     2742 * @param dialog Go To Line dialog
     2743 * @param arg Argument (ui_demo_t *)
     2744 * @param text Submitted text
     2745 */
     2746static void go_to_line_dialog_bok(ui_prompt_dialog_t *dialog, void *arg,
     2747    const char *text)
     2748{
     2749        edit_t *edit = (edit_t *) arg;
     2750        char *endptr;
     2751        int line;
     2752
     2753        ui_prompt_dialog_destroy(dialog);
     2754        line = strtol(text, &endptr, 10);
     2755        if (*endptr != '\0') {
     2756                status_display("Invalid number entered.");
     2757                return;
     2758        }
     2759
     2760        caret_move_absolute(line, pane.ideal_column, dir_before, false);
     2761        (void)edit;
     2762        (void) pane_update(&pane);
     2763}
     2764
     2765/** Go To Line dialog cancel button press.
     2766 *
     2767 * @param dialog File dialog
     2768 * @param arg Argument (ui_demo_t *)
     2769 */
     2770static void go_to_line_dialog_bcancel(ui_prompt_dialog_t *dialog, void *arg)
     2771{
     2772        edit_t *edit = (edit_t *) arg;
     2773
     2774        (void)edit;
     2775        ui_prompt_dialog_destroy(dialog);
     2776}
     2777
     2778/** Go To Line dialog close request.
     2779 *
     2780 * @param dialog File dialog
     2781 * @param arg Argument (ui_demo_t *)
     2782 */
     2783static void go_to_line_dialog_close(ui_prompt_dialog_t *dialog, void *arg)
     2784{
     2785        edit_t *edit = (edit_t *) arg;
     2786
     2787        (void)edit;
     2788        ui_prompt_dialog_destroy(dialog);
     2789}
     2790
     2791/** Search dialog OK button press.
     2792 *
     2793 * @param dialog Search dialog
     2794 * @param arg Argument (ui_demo_t *)
     2795 * @param text Submitted text
     2796 */
     2797static void search_dialog_bok(ui_prompt_dialog_t *dialog, void *arg,
     2798    const char *text)
     2799{
     2800        edit_t *edit = (edit_t *) arg;
     2801        char *pattern;
     2802        bool reverse;
     2803
     2804        (void)edit;
     2805        ui_prompt_dialog_destroy(dialog);
     2806
     2807        /* Abort if search phrase is empty */
     2808        if (text[0] == '\0')
     2809                return;
     2810
     2811        pattern = str_dup(text);
     2812        reverse = pane.search_reverse;
     2813
     2814        if (pane.previous_search)
     2815                free(pane.previous_search);
     2816        pane.previous_search = pattern;
     2817        pane.previous_search_reverse = reverse;
     2818
     2819        search(pattern, reverse);
     2820
     2821        (void) pane_update(&pane);
     2822}
     2823
     2824/** Search dialog cancel button press.
     2825 *
     2826 * @param dialog File dialog
     2827 * @param arg Argument (ui_demo_t *)
     2828 */
     2829static void search_dialog_bcancel(ui_prompt_dialog_t *dialog, void *arg)
     2830{
     2831        edit_t *edit = (edit_t *) arg;
     2832
     2833        (void)edit;
     2834        ui_prompt_dialog_destroy(dialog);
     2835}
     2836
     2837/** Search dialog close request.
     2838 *
     2839 * @param dialog File dialog
     2840 * @param arg Argument (ui_demo_t *)
     2841 */
     2842static void search_dialog_close(ui_prompt_dialog_t *dialog, void *arg)
     2843{
     2844        edit_t *edit = (edit_t *) arg;
     2845
     2846        (void)edit;
     2847        ui_prompt_dialog_destroy(dialog);
    17302848}
    17312849
Note: See TracChangeset for help on using the changeset viewer.