Changeset 8a9a41e in mainline for uspace/app/edit/edit.c


Ignore:
Timestamp:
2021-10-24T08:28:43Z (2 years ago)
Author:
GitHub <noreply@…>
Children:
f628215
Parents:
2ce943a (diff), cd981f2a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
git-author:
Erik Kučák <35500848+Riko196@…> (2021-10-24 08:28:43)
git-committer:
GitHub <noreply@…> (2021-10-24 08:28:43)
Message:

Merge branch 'HelenOS:master' into master

File:
1 edited

Legend:

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

    r2ce943a r8a9a41e  
    11/*
    2  * Copyright (c) 2009 Jiri Svoboda
     2 * Copyright (c) 2021 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/menuentry.h>
     63#include <ui/promptdialog.h>
     64#include <ui/resource.h>
     65#include <ui/ui.h>
     66#include <ui/window.h>
    4267#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>
    5168
    5269#include "sheet.h"
     
    6380 *
    6481 * A rectangular area of the screen used to edit a document. Different
    65  * panes can be possibly used to edit the same document.
     82 * panes can be possibly used to edit the same document. This is a custom
     83 * UI control.
    6684 */
    6785typedef struct {
     86        /** Base control object */
     87        struct ui_control *control;
     88
     89        /** Containing window */
     90        ui_window_t *window;
     91
     92        /** UI resource */
     93        struct ui_resource *res;
     94
     95        /** Pane rectangle */
     96        gfx_rect_t rect;
     97
     98        /** Pane color */
     99        gfx_color_t *color;
     100
     101        /** Selection color */
     102        gfx_color_t *sel_color;
     103
    68104        /* Pane dimensions */
    69105        int rows, columns;
     
    90126        int ideal_column;
    91127
     128        bool search_reverse;
    92129        char *previous_search;
    93130        bool previous_search_reverse;
    94131} pane_t;
     132
     133/** Text editor */
     134typedef struct {
     135        /** User interface */
     136        ui_t *ui;
     137        /** Editor window */
     138        ui_window_t *window;
     139        /** UI resource */
     140        ui_resource_t *ui_res;
     141        /** Menu bar */
     142        ui_menu_bar_t *menubar;
     143        /** Status bar */
     144        ui_label_t *status;
     145} edit_t;
    95146
    96147/** Document
     
    103154} doc_t;
    104155
    105 static console_ctrl_t *con;
     156static edit_t edit;
    106157static doc_t doc;
    107 static bool done;
    108158static pane_t pane;
    109 static bool cursor_visible;
    110 
    111 static sysarg_t scr_rows;
    112 static sysarg_t scr_columns;
    113159
    114160#define ROW_BUF_SIZE 4096
     
    119165#define INFNAME_MAX_LEN 128
    120166
    121 static void cursor_show(void);
    122 static void cursor_hide(void);
    123167static void cursor_setvis(bool visible);
    124168
     
    139183static char *range_get_str(spt_t const *spos, spt_t const *epos);
    140184
    141 static char *prompt(char const *prompt, char const *init_value);
    142 
    143 static void pane_text_display(void);
     185static errno_t pane_init(ui_window_t *, pane_t *);
     186static void pane_fini(pane_t *);
     187static ui_control_t *pane_ctl(pane_t *);
     188static errno_t pane_update(pane_t *);
     189static errno_t pane_text_display(pane_t *);
    144190static 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);
     191static errno_t pane_row_range_display(pane_t *, int r0, int r1);
     192static void pane_status_display(pane_t *);
     193static void pane_caret_display(pane_t *);
    148194
    149195static void insert_char(char32_t c);
     
    164210static void selection_delete(void);
    165211static void selection_copy(void);
     212static void edit_cut(void);
     213static void edit_paste(void);
    166214static void insert_clipboard_data(void);
    167215
     
    185233
    186234static void status_display(char const *str);
     235static errno_t edit_ui_create(edit_t *);
     236static void edit_ui_destroy(edit_t *);
     237
     238static void edit_wnd_close(ui_window_t *, void *);
     239static void edit_wnd_kbd_event(ui_window_t *, void *, kbd_event_t *);
     240
     241static ui_window_cb_t edit_window_cb = {
     242        .close = edit_wnd_close,
     243        .kbd = edit_wnd_kbd_event
     244};
     245
     246static void edit_file_save(ui_menu_entry_t *, void *);
     247static void edit_file_save_as(ui_menu_entry_t *, void *);
     248static void edit_file_exit(ui_menu_entry_t *, void *);
     249static void edit_edit_cut(ui_menu_entry_t *, void *);
     250static void edit_edit_copy(ui_menu_entry_t *, void *);
     251static void edit_edit_paste(ui_menu_entry_t *, void *);
     252static void edit_edit_delete(ui_menu_entry_t *, void *);
     253static void edit_edit_select_all(ui_menu_entry_t *, void *);
     254static void edit_search_find(ui_menu_entry_t *, void *);
     255static void edit_search_reverse_find(ui_menu_entry_t *, void *);
     256static void edit_search_find_next(ui_menu_entry_t *, void *);
     257static void edit_search_go_to_line(ui_menu_entry_t *, void *);
     258
     259static void pane_ctl_destroy(void *);
     260static errno_t pane_ctl_paint(void *);
     261static ui_evclaim_t pane_ctl_pos_event(void *, pos_event_t *);
     262
     263/** Pabe control ops */
     264ui_control_ops_t pane_ctl_ops = {
     265        .destroy = pane_ctl_destroy,
     266        .paint = pane_ctl_paint,
     267        .pos_event = pane_ctl_pos_event
     268};
     269
     270static void save_as_dialog_bok(ui_file_dialog_t *, void *, const char *);
     271static void save_as_dialog_bcancel(ui_file_dialog_t *, void *);
     272static void save_as_dialog_close(ui_file_dialog_t *, void *);
     273
     274static ui_file_dialog_cb_t save_as_dialog_cb = {
     275        .bok = save_as_dialog_bok,
     276        .bcancel = save_as_dialog_bcancel,
     277        .close = save_as_dialog_close
     278};
     279
     280static void go_to_line_dialog_bok(ui_prompt_dialog_t *, void *, const char *);
     281static void go_to_line_dialog_bcancel(ui_prompt_dialog_t *, void *);
     282static void go_to_line_dialog_close(ui_prompt_dialog_t *, void *);
     283
     284static ui_prompt_dialog_cb_t go_to_line_dialog_cb = {
     285        .bok = go_to_line_dialog_bok,
     286        .bcancel = go_to_line_dialog_bcancel,
     287        .close =  go_to_line_dialog_close
     288};
     289
     290static void search_dialog_bok(ui_prompt_dialog_t *, void *, const char *);
     291static void search_dialog_bcancel(ui_prompt_dialog_t *, void *);
     292static void search_dialog_close(ui_prompt_dialog_t *, void *);
     293
     294static ui_prompt_dialog_cb_t search_dialog_cb = {
     295        .bok = search_dialog_bok,
     296        .bcancel = search_dialog_bcancel,
     297        .close =  search_dialog_close
     298};
    187299
    188300int main(int argc, char *argv[])
    189301{
    190         cons_event_t ev;
    191302        bool new_file;
    192303        errno_t rc;
    193304
    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;
    201305        pane.sh_row = 1;
    202306        pane.sh_column = 1;
     
    234338        /* Move to beginning of file. */
    235339        pt_get_sof(&sof);
     340
     341        /* Create UI */
     342        rc = edit_ui_create(&edit);
     343        if (rc != EOK)
     344                return 1;
     345
    236346        caret_move(sof, true, true);
    237347
    238348        /* Initial display */
    239         cursor_visible = true;
    240 
    241         cursor_hide();
    242         console_clear(con);
    243         pane_text_display();
    244         pane_status_display();
     349        rc = ui_window_paint(edit.window);
     350        if (rc != EOK) {
     351                printf("Error painting window.\n");
     352                return rc;
     353        }
     354
     355        pane_status_display(&pane);
    245356        if (new_file && doc.file_name != NULL)
    246357                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 
     358        pane_caret_display(&pane);
     359        cursor_setvis(true);
     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 *msave = NULL;
     380        ui_menu_entry_t *msaveas = NULL;
     381        ui_menu_entry_t *mfsep = NULL;
     382        ui_menu_entry_t *mexit = NULL;
     383        ui_menu_entry_t *mcut = NULL;
     384        ui_menu_entry_t *mcopy = NULL;
     385        ui_menu_entry_t *mpaste = NULL;
     386        ui_menu_entry_t *mdelete = NULL;
     387        ui_menu_entry_t *mesep = NULL;
     388        ui_menu_entry_t *mselall = NULL;
     389        ui_menu_t *msearch = NULL;
     390        ui_menu_entry_t *mfind = NULL;
     391        ui_menu_entry_t *mfindr = NULL;
     392        ui_menu_entry_t *mfindn = NULL;
     393        ui_menu_entry_t *mssep = NULL;
     394        ui_menu_entry_t *mgoto = NULL;
     395        gfx_rect_t arect;
     396        gfx_rect_t rect;
     397
     398        rc = ui_create(UI_CONSOLE_DEFAULT, &edit->ui);
     399        if (rc != EOK) {
     400                printf("Error creating UI on display %s.\n",
     401                    UI_CONSOLE_DEFAULT);
     402                goto error;
     403        }
     404
     405        ui_wnd_params_init(&params);
     406        params.caption = "Text Editor";
     407        params.style &= ~ui_wds_decorated;
     408        params.placement = ui_wnd_place_full_screen;
     409
     410        rc = ui_window_create(edit->ui, &params, &edit->window);
     411        if (rc != EOK) {
     412                printf("Error creating window.\n");
     413                goto error;
     414        }
     415
     416        ui_window_set_cb(edit->window, &edit_window_cb, (void *) edit);
     417
     418        edit->ui_res = ui_window_get_res(edit->window);
     419
     420        rc = ui_fixed_create(&fixed);
     421        if (rc != EOK) {
     422                printf("Error creating fixed layout.\n");
     423                return rc;
     424        }
     425
     426        rc = ui_menu_bar_create(edit->ui, edit->window, &edit->menubar);
     427        if (rc != EOK) {
     428                printf("Error creating menu bar.\n");
     429                return rc;
     430        }
     431
     432        rc = ui_menu_create(edit->menubar, "File", &mfile);
     433        if (rc != EOK) {
     434                printf("Error creating menu.\n");
     435                return rc;
     436        }
     437
     438        rc = ui_menu_entry_create(mfile, "Save", "Ctrl-S", &msave);
     439        if (rc != EOK) {
     440                printf("Error creating menu.\n");
     441                return rc;
     442        }
     443
     444        ui_menu_entry_set_cb(msave, edit_file_save, (void *) edit);
     445
     446        rc = ui_menu_entry_create(mfile, "Save As", "Ctrl-E", &msaveas);
     447        if (rc != EOK) {
     448                printf("Error creating menu.\n");
     449                return rc;
     450        }
     451
     452        ui_menu_entry_set_cb(msaveas, edit_file_save_as, (void *) edit);
     453
     454        rc = ui_menu_entry_sep_create(mfile, &mfsep);
     455        if (rc != EOK) {
     456                printf("Error creating menu.\n");
     457                return rc;
     458        }
     459
     460        rc = ui_menu_entry_create(mfile, "Exit", "Ctrl-Q", &mexit);
     461        if (rc != EOK) {
     462                printf("Error creating menu.\n");
     463                return rc;
     464        }
     465
     466        ui_menu_entry_set_cb(mexit, edit_file_exit, (void *) edit);
     467
     468        rc = ui_menu_create(edit->menubar, "Edit", &medit);
     469        if (rc != EOK) {
     470                printf("Error creating menu.\n");
     471                return rc;
     472        }
     473
     474        rc = ui_menu_entry_create(medit, "Cut", "Ctrl-X", &mcut);
     475        if (rc != EOK) {
     476                printf("Error creating menu.\n");
     477                return rc;
     478        }
     479
     480        ui_menu_entry_set_cb(mcut, edit_edit_cut, (void *) edit);
     481
     482        rc = ui_menu_entry_create(medit, "Copy", "Ctrl-C", &mcopy);
     483        if (rc != EOK) {
     484                printf("Error creating menu.\n");
     485                return rc;
     486        }
     487
     488        ui_menu_entry_set_cb(mcopy, edit_edit_copy, (void *) edit);
     489
     490        rc = ui_menu_entry_create(medit, "Paste", "Ctrl-V", &mpaste);
     491        if (rc != EOK) {
     492                printf("Error creating menu.\n");
     493                return rc;
     494        }
     495
     496        ui_menu_entry_set_cb(mpaste, edit_edit_paste, (void *) edit);
     497
     498        rc = ui_menu_entry_create(medit, "Delete", "Del", &mdelete);
     499        if (rc != EOK) {
     500                printf("Error creating menu.\n");
     501                return rc;
     502        }
     503
     504        ui_menu_entry_set_cb(mdelete, edit_edit_delete, (void *) edit);
     505
     506        rc = ui_menu_entry_sep_create(medit, &mesep);
     507        if (rc != EOK) {
     508                printf("Error creating menu.\n");
     509                return rc;
     510        }
     511
     512        rc = ui_menu_entry_create(medit, "Select All", "Ctrl-A", &mselall);
     513        if (rc != EOK) {
     514                printf("Error creating menu.\n");
     515                return rc;
     516        }
     517
     518        ui_menu_entry_set_cb(mselall, edit_edit_select_all, (void *) edit);
     519
     520        rc = ui_menu_create(edit->menubar, "Search", &msearch);
     521        if (rc != EOK) {
     522                printf("Error creating menu.\n");
     523                return rc;
     524        }
     525
     526        rc = ui_menu_entry_create(msearch, "Find", "Ctrl-F", &mfind);
     527        if (rc != EOK) {
     528                printf("Error creating menu.\n");
     529                return rc;
     530        }
     531
     532        ui_menu_entry_set_cb(mfind, edit_search_find, (void *) edit);
     533
     534        rc = ui_menu_entry_create(msearch, "Reverse Find", "Ctrl-Shift-F", &mfindr);
     535        if (rc != EOK) {
     536                printf("Error creating menu.\n");
     537                return rc;
     538        }
     539
     540        ui_menu_entry_set_cb(mfindr, edit_search_reverse_find, (void *) edit);
     541
     542        rc = ui_menu_entry_create(msearch, "Find Next", "Ctrl-N", &mfindn);
     543        if (rc != EOK) {
     544                printf("Error creating menu.\n");
     545                return rc;
     546        }
     547
     548        ui_menu_entry_set_cb(mfindn, edit_search_find_next, (void *) edit);
     549
     550        rc = ui_menu_entry_sep_create(msearch, &mssep);
     551        if (rc != EOK) {
     552                printf("Error creating menu.\n");
     553                return rc;
     554        }
     555
     556        rc = ui_menu_entry_create(msearch, "Go To Line", "Ctrl-L", &mgoto);
     557        if (rc != EOK) {
     558                printf("Error creating menu.\n");
     559                return rc;
     560        }
     561
     562        ui_menu_entry_set_cb(mgoto, edit_search_go_to_line, (void *) edit);
     563
     564        ui_window_get_app_rect(edit->window, &arect);
     565
     566        rect.p0 = arect.p0;
     567        rect.p1.x = arect.p1.x;
     568        rect.p1.y = arect.p0.y + 1;
     569        ui_menu_bar_set_rect(edit->menubar, &rect);
     570
     571        rc = ui_fixed_add(fixed, ui_menu_bar_ctl(edit->menubar));
     572        if (rc != EOK) {
     573                printf("Error adding control to layout.\n");
     574                return rc;
     575        }
     576
     577        rc = pane_init(edit->window, &pane);
     578        if (rc != EOK) {
     579                printf("Error initializing pane.\n");
     580                return rc;
     581        }
     582
     583        rc = ui_fixed_add(fixed, pane_ctl(&pane));
     584        if (rc != EOK) {
     585                printf("Error adding control to layout.\n");
     586                return rc;
     587        }
     588
     589        rc = ui_label_create(edit->ui_res, "", &edit->status);
     590        if (rc != EOK) {
     591                printf("Error creating menu bar.\n");
     592                return rc;
     593        }
     594
     595        rect.p0.x = arect.p0.x;
     596        rect.p0.y = arect.p1.y - 1;
     597        rect.p1 = arect.p1;
     598        ui_label_set_rect(edit->status, &rect);
     599
     600        rc = ui_fixed_add(fixed, ui_label_ctl(edit->status));
     601        if (rc != EOK) {
     602                printf("Error adding control to layout.\n");
     603                return rc;
     604        }
     605
     606        ui_window_add(edit->window, ui_fixed_ctl(fixed));
     607        return EOK;
     608error:
     609        if (edit->window != NULL)
     610                ui_window_destroy(edit->window);
     611        if (edit->ui != NULL)
     612                ui_destroy(edit->ui);
     613        return rc;
     614}
     615
     616/** Destroy text editor UI.
     617 *
     618 * @param edit Editor
     619 */
     620static void edit_ui_destroy(edit_t *edit)
     621{
     622        ui_window_destroy(edit->window);
     623        ui_destroy(edit->ui);
    289624}
    290625
     
    309644}
    310645
    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 
    321646static void cursor_setvis(bool visible)
    322647{
    323         if (cursor_visible != visible) {
    324                 console_cursor_visibility(con, visible);
    325                 cursor_visible = visible;
    326         }
     648        gfx_context_t *gc = ui_window_get_gc(edit.window);
     649
     650        (void) gfx_cursor_set_visible(gc, visible);
    327651}
    328652
     
    400724        switch (ev->key) {
    401725        case KC_Q:
    402                 done = true;
     726                ui_quit(edit.ui);
    403727                break;
    404728        case KC_S:
     
    415739                break;
    416740        case KC_V:
    417                 selection_delete();
    418                 insert_clipboard_data();
    419                 pane.rflags |= REDRAW_TEXT;
    420                 caret_update();
     741                edit_paste();
    421742                break;
    422743        case KC_X:
    423                 selection_copy();
    424                 selection_delete();
    425                 pane.rflags |= REDRAW_TEXT;
    426                 caret_update();
     744                edit_cut();
    427745                break;
    428746        case KC_A:
     
    490808
    491809        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;
     810                bc.row = pane.sh_row + ev->vpos - pane.rect.p0.y;
     811                bc.column = pane.sh_column + ev->hpos - pane.rect.p0.x;
    494812                sheet_get_cell_pt(doc.sh, &bc, dir_before, &pt);
    495813
     
    497815
    498816                caret_move(pt, select, true);
     817                pane_update(&pane);
    499818        }
    500819}
     
    606925}
    607926
    608 /** Change document name and save. */
     927/** Open Save As dialog. */
    609928static void file_save_as(void)
    610929{
    611930        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.");
     931        ui_file_dialog_params_t fdparams;
     932        ui_file_dialog_t *dialog;
     933        errno_t rc;
     934
     935        ui_file_dialog_params_init(&fdparams);
     936        fdparams.caption = "Save As";
     937        fdparams.ifname = old_fname;
     938
     939        rc = ui_file_dialog_create(edit.ui, &fdparams, &dialog);
     940        if (rc != EOK) {
     941                printf("Error creating message dialog.\n");
    617942                return;
    618943        }
    619944
    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;
     945        ui_file_dialog_set_cb(dialog, &save_as_dialog_cb, &edit);
    694946}
    695947
     
    8081060}
    8091061
    810 static void pane_text_display(void)
    811 {
     1062/** Initialize pane.
     1063 *
     1064 * TODO: Replace with pane_create() that allocates the pane.
     1065 *
     1066 * @param window Editor window
     1067 * @param pane Pane
     1068 * @return EOK on success or an error code
     1069 */
     1070static errno_t pane_init(ui_window_t *window, pane_t *pane)
     1071{
     1072        errno_t rc;
     1073        gfx_rect_t arect;
     1074
     1075        pane->control = NULL;
     1076        pane->color = NULL;
     1077        pane->sel_color = NULL;
     1078
     1079        rc = ui_control_new(&pane_ctl_ops, (void *) pane, &pane->control);
     1080        if (rc != EOK)
     1081                goto error;
     1082
     1083        rc = gfx_color_new_ega(0x07, &pane->color);
     1084        if (rc != EOK)
     1085                goto error;
     1086
     1087        rc = gfx_color_new_ega(0x1e, &pane->sel_color);
     1088        if (rc != EOK)
     1089                goto error;
     1090
     1091        pane->res = ui_window_get_res(window);
     1092        pane->window = window;
     1093
     1094        ui_window_get_app_rect(window, &arect);
     1095        pane->rect.p0.x = arect.p0.x;
     1096        pane->rect.p0.y = arect.p0.y + 1;
     1097        pane->rect.p1.x = arect.p1.x;
     1098        pane->rect.p1.y = arect.p1.y - 1;
     1099
     1100        pane->columns = pane->rect.p1.x - pane->rect.p0.x;
     1101        pane->rows = pane->rect.p1.y - pane->rect.p0.y;
     1102
     1103        return EOK;
     1104error:
     1105        if (pane->control != NULL) {
     1106                ui_control_delete(pane->control);
     1107                pane->control = NULL;
     1108        }
     1109
     1110        if (pane->color != NULL) {
     1111                gfx_color_delete(pane->color);
     1112                pane->color = NULL;
     1113        }
     1114
     1115        return rc;
     1116}
     1117
     1118/** Finalize pane.
     1119 *
     1120 * TODO: Replace with pane_destroy() that deallocates the pane.
     1121 *
     1122 * @param pane Pane
     1123 */
     1124static void pane_fini(pane_t *pane)
     1125{
     1126        gfx_color_delete(pane->color);
     1127        pane->color = NULL;
     1128        gfx_color_delete(pane->sel_color);
     1129        pane->sel_color = NULL;
     1130        ui_control_delete(pane->control);
     1131        pane->control = NULL;
     1132}
     1133
     1134/** Return base control object for a pane.
     1135 *
     1136 * @param pane Pane
     1137 * @return Base UI cntrol
     1138 */
     1139static ui_control_t *pane_ctl(pane_t *pane)
     1140{
     1141        return pane->control;
     1142}
     1143
     1144/** Repaint parts of pane that need updating.
     1145 *
     1146 * @param pane Pane
     1147 * @return EOK on succes or an error code
     1148 */
     1149static errno_t pane_update(pane_t *pane)
     1150{
     1151        errno_t rc;
     1152
     1153        if (pane->rflags & REDRAW_TEXT) {
     1154                rc = pane_text_display(pane);
     1155                if (rc != EOK)
     1156                        return rc;
     1157        }
     1158
     1159        if (pane->rflags & REDRAW_ROW)
     1160                pane_row_display();
     1161
     1162        if (pane->rflags & REDRAW_STATUS)
     1163                pane_status_display(pane);
     1164
     1165        if (pane->rflags & REDRAW_CARET)
     1166                pane_caret_display(pane);
     1167
     1168        pane->rflags &= ~(REDRAW_TEXT | REDRAW_ROW | REDRAW_STATUS |
     1169            REDRAW_CARET);
     1170        return EOK;
     1171}
     1172
     1173/** Display pane text.
     1174 *
     1175 * @param pane Pane
     1176 * @return EOK on success or an error code
     1177 */
     1178static errno_t pane_text_display(pane_t *pane)
     1179{
     1180        gfx_rect_t rect;
     1181        gfx_context_t *gc;
     1182        errno_t rc;
    8121183        int sh_rows, rows;
    8131184
    8141185        sheet_get_num_rows(doc.sh, &sh_rows);
    815         rows = min(sh_rows - pane.sh_row + 1, pane.rows);
     1186        rows = min(sh_rows - pane->sh_row + 1, pane->rows);
    8161187
    8171188        /* Draw rows from the sheet. */
    8181189
    819         console_set_pos(con, 0, 0);
    820         pane_row_range_display(0, rows);
     1190        rc = pane_row_range_display(pane, 0, rows);
     1191        if (rc != EOK)
     1192                return rc;
    8211193
    8221194        /* Clear the remaining rows if file is short. */
    8231195
    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;
     1196        gc = ui_window_get_gc(pane->window);
     1197
     1198        rc = gfx_set_color(gc, pane->color);
     1199        if (rc != EOK)
     1200                goto error;
     1201
     1202        rect.p0.x = pane->rect.p0.x;
     1203        rect.p0.y = pane->rect.p0.y + rows;
     1204        rect.p1.x = pane->rect.p1.x;
     1205        rect.p1.y = pane->rect.p1.y;
     1206
     1207        rc = gfx_fill_rect(gc, &rect);
     1208        if (rc != EOK)
     1209                goto error;
     1210
     1211        pane->rflags &= ~REDRAW_ROW;
     1212        return EOK;
     1213error:
     1214        return rc;
    8351215}
    8361216
     
    8461226
    8471227        ridx = coord.row - pane.sh_row;
    848         pane_row_range_display(ridx, ridx + 1);
     1228        (void) pane_row_range_display(&pane, ridx, ridx + 1);
    8491229        pane.rflags |= (REDRAW_STATUS | REDRAW_CARET);
    8501230}
    8511231
    852 static void pane_row_range_display(int r0, int r1)
    853 {
    854         int i, j, fill;
     1232/** Display a range of rows of text.
     1233 *
     1234 * @param r0 Start row (inclusive)
     1235 * @param r1 End row (exclusive)
     1236 * @return EOk on success or an error code
     1237 */
     1238static errno_t pane_row_range_display(pane_t *pane, int r0, int r1)
     1239{
     1240        int i, fill;
    8551241        spt_t rb, re, dep, pt;
    8561242        coord_t rbc, rec;
    8571243        char row_buf[ROW_BUF_SIZE];
     1244        char cbuf[STR_BOUNDS(1) + 1];
    8581245        char32_t c;
    8591246        size_t pos, size;
     1247        size_t cpos;
    8601248        int s_column;
    8611249        coord_t csel_start, csel_end, ctmp;
     1250        gfx_font_t *font;
     1251        gfx_context_t *gc;
     1252        gfx_text_fmt_t fmt;
     1253        gfx_coord2_t tpos;
     1254        gfx_rect_t rect;
     1255        errno_t rc;
     1256
     1257        font = ui_resource_get_font(edit.ui_res);
     1258        gc = ui_window_get_gc(edit.window);
     1259
     1260        gfx_text_fmt_init(&fmt);
     1261        fmt.color = pane->color;
    8621262
    8631263        /* Determine selection start and end. */
    8641264
    865         tag_get_pt(&pane.sel_start, &pt);
     1265        tag_get_pt(&pane->sel_start, &pt);
    8661266        spt_get_coord(&pt, &csel_start);
    8671267
    868         tag_get_pt(&pane.caret_pos, &pt);
     1268        tag_get_pt(&pane->caret_pos, &pt);
    8691269        spt_get_coord(&pt, &csel_end);
    8701270
     
    8771277        /* Draw rows from the sheet. */
    8781278
    879         console_set_pos(con, 0, 0);
    8801279        for (i = r0; i < r1; ++i) {
     1280                tpos.x = pane->rect.p0.x;
     1281                tpos.y = pane->rect.p0.y + i;
     1282
    8811283                /* Starting point for row display */
    882                 rbc.row = pane.sh_row + i;
    883                 rbc.column = pane.sh_column;
     1284                rbc.row = pane->sh_row + i;
     1285                rbc.column = pane->sh_column;
    8841286                sheet_get_cell_pt(doc.sh, &rbc, dir_before, &rb);
    8851287
    8861288                /* Ending point for row display */
    887                 rec.row = pane.sh_row + i;
    888                 rec.column = pane.sh_column + pane.columns;
     1289                rec.row = pane->sh_row + i;
     1290                rec.column = pane->sh_column + pane->columns;
    8891291                sheet_get_cell_pt(doc.sh, &rec, dir_before, &re);
    8901292
     
    8961298                if (coord_cmp(&csel_start, &rbc) <= 0 &&
    8971299                    coord_cmp(&rbc, &csel_end) < 0) {
    898                         console_flush(con);
    899                         console_set_style(con, STYLE_SELECTED);
    900                         console_flush(con);
     1300                        fmt.color = pane->sel_color;
    9011301                }
    9021302
    903                 console_set_pos(con, 0, i);
    9041303                size = str_size(row_buf);
    9051304                pos = 0;
    906                 s_column = pane.sh_column;
     1305                s_column = pane->sh_column;
    9071306                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                         }
     1307                        if ((csel_start.row == rbc.row) && (csel_start.column == s_column))
     1308                                fmt.color = pane->sel_color;
     1309
     1310                        if ((csel_end.row == rbc.row) && (csel_end.column == s_column))
     1311                                fmt.color = pane->color;
    9191312
    9201313                        c = str_decode(row_buf, &pos, size);
    9211314                        if (c != '\t') {
    922                                 printf("%lc", (wint_t) c);
     1315                                cpos = 0;
     1316                                rc = chr_encode(c, cbuf, &cpos, sizeof(cbuf));
     1317                                if (rc != EOK)
     1318                                        return rc;
     1319
     1320                                rc = gfx_puttext(font, &tpos, &fmt, cbuf);
     1321                                if (rc != EOK)
     1322                                        return rc;
     1323
    9231324                                s_column += 1;
     1325                                tpos.x++;
    9241326                        } else {
    9251327                                fill = 1 + ALIGN_UP(s_column, TAB_WIDTH) -
    9261328                                    s_column;
    9271329
    928                                 for (j = 0; j < fill; ++j)
    929                                         putchar(' ');
     1330                                rc = gfx_set_color(gc, fmt.color);
     1331                                if (rc != EOK)
     1332                                        return rc;
     1333
     1334                                rect.p0.x = tpos.x;
     1335                                rect.p0.y = tpos.y;
     1336                                rect.p1.x = tpos.x + fill;
     1337                                rect.p1.y = tpos.y + 1;
     1338
     1339                                rc = gfx_fill_rect(gc, &rect);
     1340                                if (rc != EOK)
     1341                                        return rc;
     1342
    9301343                                s_column += fill;
     1344                                tpos.x += fill;
    9311345                        }
    9321346                }
    9331347
    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                 }
     1348                if ((csel_end.row == rbc.row) && (csel_end.column == s_column))
     1349                        fmt.color = pane->color;
    9391350
    9401351                /* Fill until the end of display area. */
    9411352
    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)
     1353                rc = gfx_set_color(gc, fmt.color);
     1354                if (rc != EOK)
     1355                        return rc;
     1356
     1357                rect.p0.x = tpos.x;
     1358                rect.p0.y = tpos.y;
     1359                rect.p1.x = pane->rect.p1.x;
     1360                rect.p1.y = tpos.y + 1;
     1361
     1362                rc = gfx_fill_rect(gc, &rect);
     1363                if (rc != EOK)
     1364                        return rc;
     1365        }
     1366
     1367        return EOK;
     1368}
     1369
     1370/** Display pane status in the status line.
     1371 *
     1372 * @param pane Pane
     1373 */
     1374static void pane_status_display(pane_t *pane)
    9581375{
    9591376        spt_t caret_pt;
     
    9641381        char *text;
    9651382        size_t n;
    966         int pos;
    9671383        size_t nextra;
    9681384        size_t fnw;
    9691385
    970         tag_get_pt(&pane.caret_pos, &caret_pt);
     1386        tag_get_pt(&pane->caret_pos, &caret_pt);
    9711387        spt_get_coord(&caret_pt, &coord);
    9721388
     
    9871403                return;
    9881404
    989         console_set_pos(con, 0, scr_rows - 1);
    990         console_set_style(con, STYLE_INVERTED);
    991 
    9921405        /*
    9931406         * Make sure the status fits on the screen. This loop should
     
    9951408         */
    9961409        while (true) {
    997                 int rc = asprintf(&text, " %d, %d (%d): File '%s'. Ctrl-Q Quit  Ctrl-S Save  "
     1410                int rc = asprintf(&text, "%d, %d (%d): File '%s'. Ctrl-Q Quit  Ctrl-S Save  "
    9981411                    "Ctrl-E Save As", coord.row, coord.column, last_row, fname);
    9991412                if (rc < 0) {
     
    10041417                /* If it already fits, we're done */
    10051418                n = str_width(text);
    1006                 if (n <= scr_columns - 2)
     1419                if ((int)n <= pane->columns - 2)
    10071420                        break;
    10081421
    10091422                /* Compute number of excess characters */
    1010                 nextra = n - (scr_columns - 2);
     1423                nextra = n - (pane->columns - 2);
    10111424                /** With of the file name part */
    10121425                fnw = str_width(fname);
     
    10161429                 * just give up and print a blank status.
    10171430                 */
    1018                 if (nextra > fnw - 2)
     1431                if (nextra > fnw - 2) {
     1432                        text[0] = '\0';
    10191433                        goto finish;
     1434                }
    10201435
    10211436                /* Compute position where we overwrite with '..\0' */
     
    10341449        }
    10351450
    1036         printf("%s", text);
     1451finish:
     1452        (void) ui_label_set_text(edit.status, text);
     1453        (void) ui_label_paint(edit.status);
    10371454        free(text);
    10381455        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)
     1456}
     1457
     1458/** Set cursor to reflect position of the caret.
     1459 *
     1460 * @param pane Pane
     1461 */
     1462static void pane_caret_display(pane_t *pane)
    10511463{
    10521464        spt_t caret_pt;
    10531465        coord_t coord;
    1054 
    1055         tag_get_pt(&pane.caret_pos, &caret_pt);
     1466        gfx_coord2_t pos;
     1467        gfx_context_t *gc;
     1468
     1469        tag_get_pt(&pane->caret_pos, &caret_pt);
    10561470
    10571471        spt_get_coord(&caret_pt, &coord);
    1058         console_set_pos(con, coord.column - pane.sh_column,
    1059             coord.row - pane.sh_row);
     1472
     1473        gc = ui_window_get_gc(edit.window);
     1474        pos.x = pane->rect.p0.x + coord.column - pane->sh_column;
     1475        pos.y = pane->rect.p0.y + coord.row - pane->sh_row;
     1476
     1477        (void) gfx_cursor_set_pos(gc, &pos);
     1478}
     1479
     1480/** Destroy pane control.
     1481 *
     1482 * @param arg Argument (pane_t *)
     1483 */
     1484static void pane_ctl_destroy(void *arg)
     1485{
     1486        pane_t *pane = (pane_t *)arg;
     1487
     1488        pane_fini(pane);
     1489}
     1490
     1491/** Paint pane control.
     1492 *
     1493 * @param arg Argument (pane_t *)
     1494 */
     1495static errno_t pane_ctl_paint(void *arg)
     1496{
     1497        pane_t *pane = (pane_t *)arg;
     1498        gfx_context_t *gc;
     1499        errno_t rc;
     1500
     1501        gc = ui_window_get_gc(pane->window);
     1502
     1503        rc = pane_text_display(pane);
     1504        if (rc != EOK)
     1505                goto error;
     1506
     1507        rc = gfx_update(gc);
     1508        if (rc != EOK)
     1509                goto error;
     1510
     1511error:
     1512        return rc;
     1513}
     1514
     1515/** Handle pane control position event.
     1516 *
     1517 * @param arg Argument (pane_t *)
     1518 * @param event Position event
     1519 */
     1520static ui_evclaim_t pane_ctl_pos_event(void *arg, pos_event_t *event)
     1521{
     1522        gfx_coord2_t pos;
     1523
     1524        pos.x = event->hpos;
     1525        pos.y = event->vpos;
     1526
     1527        if (!gfx_pix_inside_rect(&pos, &pane.rect))
     1528                return ui_unclaimed;
     1529
     1530        pos_handle(event);
     1531        (void) gfx_update(ui_window_get_gc(edit.window));
     1532        return ui_claimed;
    10601533}
    10611534
     
    12701743static void caret_go_to_line_ask(void)
    12711744{
    1272         char *sline;
    1273 
    1274         sline = prompt("Go to line", "");
    1275         if (sline == NULL) {
    1276                 status_display("Go to line cancelled.");
     1745        ui_prompt_dialog_params_t pdparams;
     1746        ui_prompt_dialog_t *dialog;
     1747        errno_t rc;
     1748
     1749        ui_prompt_dialog_params_init(&pdparams);
     1750        pdparams.caption = "Go To Line";
     1751        pdparams.prompt = "Line Number";
     1752
     1753        rc = ui_prompt_dialog_create(edit.ui, &pdparams, &dialog);
     1754        if (rc != EOK) {
     1755                printf("Error creating prompt dialog.\n");
    12771756                return;
    12781757        }
    12791758
    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);
     1759        ui_prompt_dialog_set_cb(dialog, &go_to_line_dialog_cb, &edit);
    12901760}
    12911761
     
    13441814static void search_prompt(bool reverse)
    13451815{
    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 = "";
     1816        ui_prompt_dialog_params_t pdparams;
     1817        ui_prompt_dialog_t *dialog;
     1818        errno_t rc;
     1819
     1820        ui_prompt_dialog_params_init(&pdparams);
     1821        pdparams.caption = reverse ? "Reverse Search" : "Search";
     1822        pdparams.prompt = "Search text";
     1823        pdparams.itext = "";
     1824
    13531825        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.");
     1826                pdparams.itext = pane.previous_search;
     1827
     1828        rc = ui_prompt_dialog_create(edit.ui, &pdparams, &dialog);
     1829        if (rc != EOK) {
     1830                printf("Error creating prompt dialog.\n");
    13591831                return;
    13601832        }
    13611833
    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);
     1834        ui_prompt_dialog_set_cb(dialog, &search_dialog_cb, &edit);
     1835        pane.search_reverse = reverse;
    13681836}
    13691837
     
    15131981        }
    15141982        free(str);
     1983}
     1984
     1985static void edit_paste(void)
     1986{
     1987        selection_delete();
     1988        insert_clipboard_data();
     1989        pane.rflags |= (REDRAW_TEXT | REDRAW_CARET);
     1990        pane_update(&pane);
     1991}
     1992
     1993static void edit_cut(void)
     1994{
     1995        selection_copy();
     1996        selection_delete();
     1997        pane.rflags |= (REDRAW_TEXT | REDRAW_CARET);
     1998        pane_update(&pane);
    15151999}
    15162000
     
    17192203static void status_display(char const *str)
    17202204{
    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);
     2205        (void) ui_label_set_text(edit.status, str);
     2206        (void) ui_label_paint(edit.status);
     2207}
     2208
     2209/** Window close request
     2210 *
     2211 * @param window Window
     2212 * @param arg Argument (edit_t *)
     2213 */
     2214static void edit_wnd_close(ui_window_t *window, void *arg)
     2215{
     2216        edit_t *edit = (edit_t *) arg;
     2217
     2218        ui_quit(edit->ui);
     2219}
     2220
     2221/** Window keyboard event
     2222 *
     2223 * @param window Window
     2224 * @param arg Argument (edit_t *)
     2225 * @param event Keyboard event
     2226 */
     2227static void edit_wnd_kbd_event(ui_window_t *window, void *arg,
     2228    kbd_event_t *event)
     2229{
     2230        pane.keymod = event->mods;
     2231
     2232        if (event->type == KEY_PRESS) {
     2233                key_handle_press(event);
     2234                (void) pane_update(&pane);
     2235                (void) gfx_update(ui_window_get_gc(window));
     2236        }
     2237}
     2238
     2239/** File / Save menu entry selected.
     2240 *
     2241 * @param mentry Menu entry
     2242 * @param arg Argument (edit_t *)
     2243 */
     2244static void edit_file_save(ui_menu_entry_t *mentry, void *arg)
     2245{
     2246        edit_t *edit = (edit_t *) arg;
     2247
     2248        (void)edit;
     2249
     2250        if (doc.file_name != NULL)
     2251                file_save(doc.file_name);
     2252        else
     2253                file_save_as();
     2254}
     2255
     2256/** File / Save As menu entry selected.
     2257 *
     2258 * @param mentry Menu entry
     2259 * @param arg Argument (edit_t *)
     2260 */
     2261static void edit_file_save_as(ui_menu_entry_t *mentry, void *arg)
     2262{
     2263        edit_t *edit = (edit_t *) arg;
     2264
     2265        (void)edit;
     2266        file_save_as();
     2267}
     2268
     2269/** File / Exit menu entry selected.
     2270 *
     2271 * @param mentry Menu entry
     2272 * @param arg Argument (edit_t *)
     2273 */
     2274static void edit_file_exit(ui_menu_entry_t *mentry, void *arg)
     2275{
     2276        edit_t *edit = (edit_t *) arg;
     2277
     2278        ui_quit(edit->ui);
     2279}
     2280
     2281/** Edit / Cut menu entry selected.
     2282 *
     2283 * @param mentry Menu entry
     2284 * @param arg Argument (edit_t *)
     2285 */
     2286static void edit_edit_cut(ui_menu_entry_t *mentry, void *arg)
     2287{
     2288        (void) arg;
     2289        edit_cut();
     2290        (void) gfx_update(ui_window_get_gc(edit.window));
     2291}
     2292
     2293/** Edit / Copy menu entry selected.
     2294 *
     2295 * @param mentry Menu entry
     2296 * @param arg Argument (edit_t *)
     2297 */
     2298static void edit_edit_copy(ui_menu_entry_t *mentry, void *arg)
     2299{
     2300        (void) arg;
     2301        selection_copy();
     2302}
     2303
     2304/** Edit / Paste menu entry selected.
     2305 *
     2306 * @param mentry Menu entry
     2307 * @param arg Argument (edit_t *)
     2308 */
     2309static void edit_edit_paste(ui_menu_entry_t *mentry, void *arg)
     2310{
     2311        (void) arg;
     2312        edit_paste();
     2313        (void) gfx_update(ui_window_get_gc(edit.window));
     2314}
     2315
     2316/** Edit / Delete menu entry selected.
     2317 *
     2318 * @param mentry Menu entry
     2319 * @param arg Argument (edit_t *)
     2320 */
     2321static void edit_edit_delete(ui_menu_entry_t *mentry, void *arg)
     2322{
     2323        (void) arg;
     2324
     2325        if (selection_active())
     2326                selection_delete();
    17282327
    17292328        pane.rflags |= REDRAW_CARET;
     2329        (void) pane_update(&pane);
     2330        (void) gfx_update(ui_window_get_gc(edit.window));
     2331}
     2332
     2333/** Edit / Select All menu entry selected.
     2334 *
     2335 * @param mentry Menu entry
     2336 * @param arg Argument (edit_t *)
     2337 */
     2338static void edit_edit_select_all(ui_menu_entry_t *mentry, void *arg)
     2339{
     2340        (void) arg;
     2341
     2342        selection_sel_all();
     2343        pane.rflags |= (REDRAW_CARET | REDRAW_TEXT | REDRAW_STATUS);
     2344        pane_update(&pane);
     2345        (void) gfx_update(ui_window_get_gc(edit.window));
     2346}
     2347
     2348/** Search / Find menu entry selected.
     2349 *
     2350 * @param mentry Menu entry
     2351 * @param arg Argument (edit_t *)
     2352 */
     2353static void edit_search_find(ui_menu_entry_t *mentry, void *arg)
     2354{
     2355        (void) arg;
     2356        search_prompt(false);
     2357}
     2358
     2359/** Search / Reverse Find menu entry selected.
     2360 *
     2361 * @param mentry Menu entry
     2362 * @param arg Argument (edit_t *)
     2363 */
     2364static void edit_search_reverse_find(ui_menu_entry_t *mentry, void *arg)
     2365{
     2366        (void) arg;
     2367        search_prompt(true);
     2368}
     2369
     2370/** Search / Find Next menu entry selected.
     2371 *
     2372 * @param mentry Menu entry
     2373 * @param arg Argument (edit_t *)
     2374 */
     2375static void edit_search_find_next(ui_menu_entry_t *mentry, void *arg)
     2376{
     2377        (void) arg;
     2378        search_repeat();
     2379        (void) pane_update(&pane);
     2380        (void) gfx_update(ui_window_get_gc(edit.window));
     2381}
     2382
     2383/** Search / Go To Line menu entry selected.
     2384 *
     2385 * @param mentry Menu entry
     2386 * @param arg Argument (edit_t *)
     2387 */
     2388static void edit_search_go_to_line(ui_menu_entry_t *mentry, void *arg)
     2389{
     2390        (void) arg;
     2391        caret_go_to_line_ask();
     2392}
     2393
     2394/** Save As dialog OK button press.
     2395 *
     2396 * @param dialog Save As dialog
     2397 * @param arg Argument (ui_demo_t *)
     2398 * @param fname File name
     2399 */
     2400static void save_as_dialog_bok(ui_file_dialog_t *dialog, void *arg,
     2401    const char *fname)
     2402{
     2403        edit_t *edit = (edit_t *)arg;
     2404        gfx_context_t *gc = ui_window_get_gc(edit->window);
     2405        char *cname;
     2406        errno_t rc;
     2407
     2408        ui_file_dialog_destroy(dialog);
     2409        // TODO Smarter cursor management
     2410        pane.rflags |= REDRAW_CARET;
     2411        (void) pane_update(&pane);
     2412        gfx_cursor_set_visible(gc, true);
     2413
     2414        cname = str_dup(fname);
     2415        if (cname == NULL) {
     2416                printf("Out of memory.\n");
     2417                return;
     2418        }
     2419
     2420        rc = file_save(fname);
     2421        if (rc != EOK)
     2422                return;
     2423
     2424        if (doc.file_name != NULL)
     2425                free(doc.file_name);
     2426        doc.file_name = cname;
     2427
     2428}
     2429
     2430/** Save As dialog cancel button press.
     2431 *
     2432 * @param dialog File dialog
     2433 * @param arg Argument (ui_demo_t *)
     2434 */
     2435static void save_as_dialog_bcancel(ui_file_dialog_t *dialog, void *arg)
     2436{
     2437        edit_t *edit = (edit_t *)arg;
     2438        gfx_context_t *gc = ui_window_get_gc(edit->window);
     2439
     2440        ui_file_dialog_destroy(dialog);
     2441        // TODO Smarter cursor management
     2442        pane.rflags |= REDRAW_CARET;
     2443        (void) pane_update(&pane);
     2444        gfx_cursor_set_visible(gc, true);
     2445}
     2446
     2447/** Save As dialog close request.
     2448 *
     2449 * @param dialog File dialog
     2450 * @param arg Argument (ui_demo_t *)
     2451 */
     2452static void save_as_dialog_close(ui_file_dialog_t *dialog, void *arg)
     2453{
     2454        edit_t *edit = (edit_t *)arg;
     2455        gfx_context_t *gc = ui_window_get_gc(edit->window);
     2456
     2457        ui_file_dialog_destroy(dialog);
     2458        // TODO Smarter cursor management
     2459        pane.rflags |= REDRAW_CARET;
     2460        (void) pane_update(&pane);
     2461        gfx_cursor_set_visible(gc, true);
     2462}
     2463
     2464/** Go To Line dialog OK button press.
     2465 *
     2466 * @param dialog Go To Line dialog
     2467 * @param arg Argument (ui_demo_t *)
     2468 * @param text Submitted text
     2469 */
     2470static void go_to_line_dialog_bok(ui_prompt_dialog_t *dialog, void *arg,
     2471    const char *text)
     2472{
     2473        edit_t *edit = (edit_t *) arg;
     2474        gfx_context_t *gc = ui_window_get_gc(edit->window);
     2475        char *endptr;
     2476        int line;
     2477
     2478        ui_prompt_dialog_destroy(dialog);
     2479        line = strtol(text, &endptr, 10);
     2480        if (*endptr != '\0') {
     2481                status_display("Invalid number entered.");
     2482                return;
     2483        }
     2484
     2485        caret_move_absolute(line, pane.ideal_column, dir_before, false);
     2486        // TODO Smarter cursor management
     2487        (void) pane_update(&pane);
     2488        gfx_cursor_set_visible(gc, true);
     2489        (void) gfx_update(gc);
     2490}
     2491
     2492/** Go To Line dialog cancel button press.
     2493 *
     2494 * @param dialog File dialog
     2495 * @param arg Argument (ui_demo_t *)
     2496 */
     2497static void go_to_line_dialog_bcancel(ui_prompt_dialog_t *dialog, void *arg)
     2498{
     2499        edit_t *edit = (edit_t *) arg;
     2500        gfx_context_t *gc = ui_window_get_gc(edit->window);
     2501
     2502        ui_prompt_dialog_destroy(dialog);
     2503        // TODO Smarter cursor management
     2504        pane.rflags |= REDRAW_CARET;
     2505        (void) pane_update(&pane);
     2506        gfx_cursor_set_visible(gc, true);
     2507}
     2508
     2509/** Go To Line dialog close request.
     2510 *
     2511 * @param dialog File dialog
     2512 * @param arg Argument (ui_demo_t *)
     2513 */
     2514static void go_to_line_dialog_close(ui_prompt_dialog_t *dialog, void *arg)
     2515{
     2516        edit_t *edit = (edit_t *) arg;
     2517        gfx_context_t *gc = ui_window_get_gc(edit->window);
     2518
     2519        ui_prompt_dialog_destroy(dialog);
     2520        // TODO Smarter cursor management
     2521        pane.rflags |= REDRAW_CARET;
     2522        (void) pane_update(&pane);
     2523        gfx_cursor_set_visible(gc, true);
     2524}
     2525
     2526/** Search dialog OK button press.
     2527 *
     2528 * @param dialog Search dialog
     2529 * @param arg Argument (ui_demo_t *)
     2530 * @param text Submitted text
     2531 */
     2532static void search_dialog_bok(ui_prompt_dialog_t *dialog, void *arg,
     2533    const char *text)
     2534{
     2535        edit_t *edit = (edit_t *) arg;
     2536        gfx_context_t *gc = ui_window_get_gc(edit->window);
     2537        char *pattern;
     2538        bool reverse;
     2539
     2540        ui_prompt_dialog_destroy(dialog);
     2541
     2542        /* Abort if search phrase is empty */
     2543        if (text[0] == '\0')
     2544                return;
     2545
     2546        pattern = str_dup(text);
     2547        reverse = pane.search_reverse;
     2548
     2549        if (pane.previous_search)
     2550                free(pane.previous_search);
     2551        pane.previous_search = pattern;
     2552        pane.previous_search_reverse = reverse;
     2553
     2554        search(pattern, reverse);
     2555
     2556        // TODO Smarter cursor management
     2557        (void) pane_update(&pane);
     2558        gfx_cursor_set_visible(gc, true);
     2559        (void) gfx_update(gc);
     2560}
     2561
     2562/** Search dialog cancel button press.
     2563 *
     2564 * @param dialog File dialog
     2565 * @param arg Argument (ui_demo_t *)
     2566 */
     2567static void search_dialog_bcancel(ui_prompt_dialog_t *dialog, void *arg)
     2568{
     2569        edit_t *edit = (edit_t *) arg;
     2570        gfx_context_t *gc = ui_window_get_gc(edit->window);
     2571
     2572        ui_prompt_dialog_destroy(dialog);
     2573        // TODO Smarter cursor management
     2574        pane.rflags |= REDRAW_CARET;
     2575        (void) pane_update(&pane);
     2576        gfx_cursor_set_visible(gc, true);
     2577}
     2578
     2579/** Search dialog close request.
     2580 *
     2581 * @param dialog File dialog
     2582 * @param arg Argument (ui_demo_t *)
     2583 */
     2584static void search_dialog_close(ui_prompt_dialog_t *dialog, void *arg)
     2585{
     2586        edit_t *edit = (edit_t *) arg;
     2587        gfx_context_t *gc = ui_window_get_gc(edit->window);
     2588
     2589        ui_prompt_dialog_destroy(dialog);
     2590        // TODO Smarter cursor management
     2591        pane.rflags |= REDRAW_CARET;
     2592        (void) pane_update(&pane);
     2593        gfx_cursor_set_visible(gc, true);
    17302594}
    17312595
Note: See TracChangeset for help on using the changeset viewer.