📄 listedit.c
字号:
/* listedit.c * (c) 2002 Petr 'Brain' Kulhavy * This file is a part of the Links program, released under GPL. */#include "links.h"/* (#####) (#########) )))) (######) ,C--O (###) _________________ |`:, \ ~~ |. , v , .| `-__o ~~ ; | ZAKAZ KOURENI | / _ \ ` |. .| | ( \__`_=k== `~~~~~~~~~~~~~~~~~' | `-/__---' |=====C/ `. ),' \ / ||_| || |__ ||____) v v v , ,v KONECNE NEJAKE KOMENTARE...*//* Klikani myssi (nebo mysijou, jak rika Mikulas) v list-okne: * (hrozne dulezity komentar ;-P ) * * Klikani je vyreseno nasledovne, pokud ma nekdo lepsi napad, nebo nejake * vyhrady, tak at mi je posle. * * Prostredni tlacitko+pohyb je scroll nahoru/dolu. Levym tlacitkem se nastavi * kurzor (cerna lista) na konkretni polozku. Kdyz se levym klikne na adresar * (na ty graficke nesmysly, ne na ten text), tak se adresar toggle * otevre/zavre. Prave tlacitko oznaci/odznaci polozku/adresar. *//* Premistovani polozek: * * Pravym tlacitkem se oznaci/odznaci polozka. Cudlikem "Odznacit vse" se * vsechny polozky odznaci. Cudlik "Prestehovat" presune vsechny oznacene * polozky za aktualni pozici, v tom poradi, jak jsou v seznamu. Pri zavreni * adresare se vsechny polozky v adresari odznaci. */ /* Prekreslovani grafickych nesmyslu v okenku je samozrejme bez jedineho * v * bliknuti. Ne jako nejmenovane browsery... Proste obraz jako BIC (TM) *//* Ovladani klavesnici: * sipky, page up, page down, home end pohyb * + otevri adresar * - zavri adresar * mezera toggle adresar * ins, *, 8, i toggle oznacit * ?, /, N, n hledani nahoru, dolu, znova, znova na druhou stranu *//* * Struktura struct list_decription obsahuje popis seznamu. Tenhle file * obsahuje obecne funkce k obsluze seznamu. Pomoci struct list_description se * seznam customizuje. Obecne funkce volaji funkce z list_description. * * Jedina funkce z tohoto filu, ktera se vola zvenku, je create_list_window. Ta * vyrobi a obstarava okno pro obsluhu seznamu. * * Obecny list neresi veci jako nahravani seznamu z filu, ukladani na disk * atd.(tyhle funkce si uzivatel musi napsat sam). Resi vlastne jenom to velke * okno na manipulaci se seznamem. *//* * Aby bylo konzistentni pridavani a editovani polozek, tak se musi pytlacit. * * To znamena, ze pri pridavani polozky do listu se vyrobi nova polozka * (NEPRIDA se do seznamu), pusti se edit a po zmacknuti OK se polozka prida do * seznamu. Pri zmacknuti cancel, se polozka smaze. * * Pri editovani polozky se vyrobi nova polozka, zkopiruje se do ni obsah te * puvodni (od toho tam je funkce copy_item), pak se zavola edit a podobne jako * v predchozim pripade: pri cancel se polozka smaze, pri OK se zkopiruje do * puvodni polozky a smaze se taky. * * O smazani polozky pri cancelu se bude starat uzivatelska funkce edit_item * sama. Funkce edit_item po zmacknuti OK zavola funkci, kterou dostane. Jako * 1. argument ji da data, ktera dostane, jako 2. argument ji preda pointer na * item. *//* * Seznam je definovan ve struct list. Muze byt bud placaty nebo stromovy. * * K placatemu asi neni co dodat. U placateho se ignoruje hloubka a neexistuji * adresare - vsechny polozky jsou si rovny (typ polozky se ignoruje). * * Stromovy seznam: * Kazdy clen seznamu ma flag sbaleno/rozbaleno. U itemy se to ignoruje, u * adresare to znamena, zda se zobrazuje obsah nebo ne. Aby rozbaleno/sbaleno * bylo u vsech prvku adresare, to by neslo: kdybych mel adresar a v nem dalsi * adresar, tak bych u toho vnoreneho adresare nevedel, jestli to * sbaleno/rozbaleno je od toho vnoreneho adresare, nebo od toho nad nim. * * Clenove seznamu maji hloubku - cislo od 0 vyse. Cim je prvek hloubeji ve * strukture, tim je hloubka vyssi. Obsah adresare s hloubkou x je souvisly blok * nasledujicich prvku s hloubkou >x. * * Hlava ma hloubku -1 a zobrazuje se taky jako clen seznamu (aby se dal * zobrazit prazdny seznam a dalo se do nej pridavat), takze se da vlastne cely * seznam zabalit/rozbalit. Hlava sice nema data, ale funkce type_item ji musi * umet zobrazit. Jako popis bude psat fixni text, napriklad "Bookmarks". * * Pro urychleni vykreslovani kazdy prvek v seznamu s adresarema obsahuje * pointer na otce (polozka fotr). U plocheho seznamu se tento pointer * ignoruje. * * Strukturu stromu bude vykreslovat obecna funkce (v tomto filu), protoze v * obecnem listu je struktura uz zachycena. *//* * V hlavnim okne se da nadefinovat 1 uzivatelske tlacitko. Polozka button ve * struct list_description obsahuje popisku tlacitka (kod stringu v * prekodovavacich tabulkach). Funkce button_fn je zavolana pri stisku * tlacitka, jako argument (void *) dostane aktualni polozku. Pokud je * button_fn NULL, tlacitko se nekona. * * Toto tlacitko se da vyuzit napriklad u bookmarku, kde je potreba [ Goto ]. * * Kdyz bude potreba predavat obsluzne funkci tlacitka nejake dalsi argumenty, * tak se pripadne definice obsluzne funkce prepise. * * Tlacitko funguje jen na polozky. Nefunguje na adresare (pokud se jedna o * stromovy list) ani na hlavu. *//* Jak funguje default_value: * kdyz se zmackne tlacitko add, zavola se funkce default_value, ktera si * naalokuje nejaky data pro new_item. Do funkce default_value se treba u * bookmarku umisti okopirovani altualniho nazvu a url stranky. Pak se zavola * new_item, ktera si prislusne hodnoty dekoduje a pomoci nich vyplni novou * polozku. Funkce new_item pak MUSI data dealokovat. Pokud funkce new_item * dostane misto pointeru s daty NULL, vyrobi prazdnou polozku. * * Default value musi vratit hodnoty v kodovani uvedenem v list_description *//* Pristupovani z vice linksu: * * ... se neresi - je zakazano. K tomu slouzi polozka open ve struct * list_description, ktera rika, jestli je okno uz otevrene, nebo ne. *//* Prekodovavani znakovych sad: * * type_item vraci text prekodovany do kodovani terminalu, ktery dostane. *//* struct list *current_pos; current cursor position in the list *//* struct list *win_offset; item at the top of the window *//* int win_pos; current y position in the window */#define BOHNICE "+420-2-84016111"#define BFU_ELEMENT_PIPE 0#define BFU_ELEMENT_TEE 1#define BFU_ELEMENT_CLOSED 2#define BFU_ELEMENT_OPEN 3/* for mouse scrolling */long last_mouse_y;#ifdef G #define sirka_scrollovadla (G_SCROLL_BAR_WIDTH<<1)#else #define sirka_scrollovadla 0#endif/* prototypes */int draw_bfu_element(struct terminal *, int, int, unsigned, long, long, unsigned char, unsigned char);struct list *next_in_tree(struct list_description *, struct list *);struct list *prev_in_tree(struct list_description *, struct list *);void list_insert_behind_item(struct dialog_data *, void *, void *, struct list_description *);void list_copy_item(struct dialog_data *, void *, void *, struct list_description *);int list_item_add(struct dialog_data *, struct dialog_item_data *);int list_folder_add(struct dialog_data *, struct dialog_item_data *);int list_item_edit(struct dialog_data *, struct dialog_item_data *);int list_item_move(struct dialog_data *, struct dialog_item_data *);int list_item_unselect(struct dialog_data *, struct dialog_item_data *);int list_item_button(struct dialog_data *, struct dialog_item_data *);int is_empty_dir(struct list_description *, struct list *);int list_item_delete(struct dialog_data *, struct dialog_item_data *);void redraw_list_line(struct terminal *, void *);void scroll_list(struct terminal *, void *);int list_event_handler(struct dialog_data *, struct event *);void create_list_window_fn(struct dialog_data *);void close_list_window(struct dialog_data *);/* This function uses these defines from setup.h: * * BFU_GRX_WIDTH * BFU_GRX_HEIGHT * BFU_ELEMENT_WIDTH *//* draws one of BFU elements: | |- [-] [+] *//* BFU elements are used in the list window *//* this function also defines shape and size of the elements *//* returns width of the BFU element (all elements have the same size, but sizes differ if we're in text mode or in graphics mode) */int draw_bfu_element(struct terminal * term, int x, int y, unsigned c, long b, long f, unsigned char type, unsigned char selected){ if (!F){ unsigned char vertical=179; unsigned char horizontal=196; unsigned char tee=195; switch (type) { case BFU_ELEMENT_PIPE: c|=ATTR_FRAME; set_char(term,x,y,c+' '); set_char(term,x+1,y,c+vertical); set_char(term,x+2,y,c+' '); set_char(term,x+3,y,c+' '); set_char(term,x+4,y,c+' '); break; case BFU_ELEMENT_TEE: c|=ATTR_FRAME; set_char(term,x,y,c+' '); set_char(term,x+1,y,c+tee); set_char(term,x+2,y,c+horizontal); set_char(term,x+3,y,c+horizontal); set_char(term,x+4,y,c+' '); break; case BFU_ELEMENT_CLOSED: set_char(term,x,y,c+'['); set_char(term,x+1,y,c+'+'); set_char(term,x+2,y,c+']'); c|=ATTR_FRAME; set_char(term,x+3,y,c+horizontal); set_char(term,x+4,y,c+' '); break; case BFU_ELEMENT_OPEN: set_char(term,x,y,c+'['); set_char(term,x+1,y,c+'-'); set_char(term,x+2,y,c+']'); c|=ATTR_FRAME; set_char(term,x+3,y,c+horizontal); set_char(term,x+4,y,c+' '); break; default: internal("draw_bfu_element: unknown BFU element type %d.\n",type); } if (selected)set_char(term,x+4,y,c+'*'); return BFU_ELEMENT_WIDTH; /* BFU element size in text mode */#ifdef G }else{ struct graphics_device *dev=term->dev; struct rect r; restrict_clip_area(dev,&r,x,y,x+5*BFU_GRX_WIDTH,y+BFU_GRX_HEIGHT); switch (type) { case BFU_ELEMENT_PIPE: /* pipe */ drv->draw_vline(dev,x+1*BFU_GRX_WIDTH,y,y+BFU_GRX_HEIGHT,f); drv->draw_vline(dev,x+1+1*BFU_GRX_WIDTH,y,y+BFU_GRX_HEIGHT,f); /* clear the rest */ drv->fill_area(dev,x,y,x+1*BFU_GRX_WIDTH,y+BFU_GRX_HEIGHT,b); drv->fill_area(dev,x+2+1*BFU_GRX_WIDTH,y,x+4*BFU_GRX_WIDTH,y+BFU_GRX_HEIGHT,b); break; case BFU_ELEMENT_TEE: /* tee */ drv->draw_vline(dev,x+1*BFU_GRX_WIDTH,y,y+BFU_GRX_HEIGHT,f); drv->draw_vline(dev,x+1+1*BFU_GRX_WIDTH,y,y+BFU_GRX_HEIGHT,f); drv->draw_hline(dev,x+1*BFU_GRX_WIDTH,y+.5*BFU_GRX_HEIGHT,x+1+3.5*BFU_GRX_WIDTH,f); drv->draw_hline(dev,x+1*BFU_GRX_WIDTH,y-1+.5*BFU_GRX_HEIGHT,x+1+3.5*BFU_GRX_WIDTH,f); /* clear the rest */ drv->fill_area(dev,x,y,x+1*BFU_GRX_WIDTH,y+BFU_GRX_HEIGHT,b); drv->fill_area(dev,x+2+BFU_GRX_WIDTH,y+.5*BFU_GRX_HEIGHT+1,x+1+3.5*BFU_GRX_WIDTH,y+BFU_GRX_HEIGHT,b); drv->fill_area(dev,x+2+BFU_GRX_WIDTH,y,x+1+3.5*BFU_GRX_WIDTH,y-1+.5*BFU_GRX_HEIGHT,b); drv->fill_area(dev,x+1+3.5*BFU_GRX_WIDTH,y,x+4*BFU_GRX_WIDTH,y+BFU_GRX_HEIGHT,b); break; case BFU_ELEMENT_CLOSED: /* vertical line of the + */ drv->draw_vline(dev,x+1*BFU_GRX_WIDTH,y+1+.25*BFU_GRX_HEIGHT,y-1+.75*BFU_GRX_HEIGHT,f); drv->draw_vline(dev,x+1+1*BFU_GRX_WIDTH,y+1+.25*BFU_GRX_HEIGHT,y-1+.75*BFU_GRX_HEIGHT,f); /* clear around the + */ drv->fill_area(dev,x+2+.5*BFU_GRX_WIDTH,y+3,x+1.5*BFU_GRX_WIDTH,y+1+.25*BFU_GRX_HEIGHT,b); drv->fill_area(dev,x+2+.5*BFU_GRX_WIDTH,y-1+.75*BFU_GRX_HEIGHT,x+1.5*BFU_GRX_WIDTH,y-3+BFU_GRX_HEIGHT,b); drv->fill_area(dev,x+2+.5*BFU_GRX_WIDTH,y+1+.25*BFU_GRX_HEIGHT,x+BFU_GRX_WIDTH,y-1+.5*BFU_GRX_HEIGHT,b); drv->fill_area(dev,x+2+BFU_GRX_WIDTH,y+1+.25*BFU_GRX_HEIGHT,x+1.5*BFU_GRX_WIDTH,y-1+.5*BFU_GRX_HEIGHT,b); drv->fill_area(dev,x+2+.5*BFU_GRX_WIDTH,y+1+.5*BFU_GRX_HEIGHT,x+BFU_GRX_WIDTH,y-3+BFU_GRX_HEIGHT,b); drv->fill_area(dev,x+2+BFU_GRX_WIDTH,y+1+.5*BFU_GRX_HEIGHT,x+1.5*BFU_GRX_WIDTH,y-3+BFU_GRX_HEIGHT,b); case BFU_ELEMENT_OPEN: /* box */ drv->draw_vline(dev,x+2,y+1,y-1+BFU_GRX_HEIGHT,f); drv->draw_vline(dev,x+3,y+1,y-1+BFU_GRX_HEIGHT,f); drv->draw_vline(dev,x-1+2*BFU_GRX_WIDTH,y+1,y-1+BFU_GRX_HEIGHT,f); drv->draw_vline(dev,x-2+2*BFU_GRX_WIDTH,y+1,y-1+BFU_GRX_HEIGHT,f); drv->draw_hline(dev,x+4,y+1,x-2+2*BFU_GRX_WIDTH,f); drv->draw_hline(dev,x+4,y+2,x-2+2*BFU_GRX_WIDTH,f); drv->draw_hline(dev,x+4,y-2+BFU_GRX_HEIGHT,x-2+2*BFU_GRX_WIDTH,f); drv->draw_hline(dev,x+4,y-3+BFU_GRX_HEIGHT,x-2+2*BFU_GRX_WIDTH,f); /* horizontal line of the - */ drv->draw_hline(dev,x+2+.5*BFU_GRX_WIDTH,y+.5*BFU_GRX_HEIGHT,x+1.5*BFU_GRX_WIDTH,f); drv->draw_hline(dev,x+2+.5*BFU_GRX_WIDTH,y-1+.5*BFU_GRX_HEIGHT,x+1.5*BFU_GRX_WIDTH,f); /* line to title */ drv->draw_hline(dev,x+2*BFU_GRX_WIDTH,y+(BFU_GRX_HEIGHT>>1),x+1+3.5*BFU_GRX_WIDTH,f); drv->draw_hline(dev,x+2*BFU_GRX_WIDTH,y-1+(BFU_GRX_HEIGHT>>1),x+1+3.5*BFU_GRX_WIDTH,f); /* top and bottom short vertical line */ drv->draw_hline(dev,x+1*BFU_GRX_WIDTH,y,x+2+1*BFU_GRX_WIDTH,f); drv->draw_hline(dev,x+1*BFU_GRX_WIDTH,y-1+BFU_GRX_HEIGHT,x+2+1*BFU_GRX_WIDTH,f); /* clear the rest */ drv->draw_vline(dev,x,y,y+BFU_GRX_HEIGHT,b); drv->draw_vline(dev,x+1,y,y+BFU_GRX_HEIGHT,b); drv->draw_hline(dev,x+2,y,x+BFU_GRX_WIDTH,b); drv->draw_hline(dev,x+2,y-1+BFU_GRX_HEIGHT,x+BFU_GRX_WIDTH,b); drv->draw_hline(dev,x+2+BFU_GRX_WIDTH,y,x+2*BFU_GRX_WIDTH,b); drv->draw_hline(dev,x+2+BFU_GRX_WIDTH,y-1+BFU_GRX_HEIGHT,x+2*BFU_GRX_WIDTH,b); drv->fill_area(dev,x+2*BFU_GRX_WIDTH,y,x+1+3.5*BFU_GRX_WIDTH,y+.5*BFU_GRX_HEIGHT-1,b); drv->fill_area(dev,x+2*BFU_GRX_WIDTH,y+1+.5*BFU_GRX_HEIGHT,x+1+3.5*BFU_GRX_WIDTH,y+BFU_GRX_HEIGHT,b); drv->fill_area(dev,x+4,y+3,x+2+.5*BFU_GRX_WIDTH,y-3+BFU_GRX_HEIGHT,b); drv->fill_area(dev,x+1.5*BFU_GRX_WIDTH,y+3,x-2+2*BFU_GRX_WIDTH,y-3+BFU_GRX_HEIGHT,b); drv->fill_area(dev,x+2+.5*BFU_GRX_WIDTH,y+3,x+1.5*BFU_GRX_WIDTH,y+1+.25*BFU_GRX_HEIGHT,b); drv->fill_area(dev,x+2+.5*BFU_GRX_WIDTH,y-1+.75*BFU_GRX_HEIGHT,x+1.5*BFU_GRX_WIDTH,y-3+BFU_GRX_HEIGHT,b); if (type==BFU_ELEMENT_OPEN) { drv->fill_area(dev,x+2+.5*BFU_GRX_WIDTH,y+3,x+1.5*BFU_GRX_WIDTH,y-1+.5*BFU_GRX_HEIGHT,b); drv->fill_area(dev,x+2+.5*BFU_GRX_WIDTH,y+1+.5*BFU_GRX_HEIGHT,x+1.5*BFU_GRX_WIDTH,y-3+BFU_GRX_HEIGHT,b); } drv->fill_area(dev,x+1+3.5*BFU_GRX_WIDTH,y,x+4*BFU_GRX_WIDTH,y+BFU_GRX_HEIGHT,b); break; default: internal("draw_bfu_element: unknown BFU element type %d.\n",type); } if (!selected) drv->fill_area(dev,x+4*BFU_GRX_WIDTH,y,x+5*BFU_GRX_WIDTH,y+BFU_GRX_HEIGHT,b); else { drv->fill_area(dev,x+4*BFU_GRX_WIDTH,y,x+4.25*BFU_GRX_WIDTH,y+BFU_GRX_HEIGHT,b); drv->fill_area(dev,x+4.25*BFU_GRX_WIDTH,y,x+4.75*BFU_GRX_WIDTH,y+2.5*BFU_GRX_HEIGHT,b); drv->fill_area(dev,x+4.25*BFU_GRX_WIDTH,y+.25*BFU_GRX_HEIGHT,x+4.75*BFU_GRX_WIDTH,y+.75*BFU_GRX_HEIGHT,f); drv->fill_area(dev,x+4.25*BFU_GRX_WIDTH,y+.75*BFU_GRX_HEIGHT,x+4.75*BFU_GRX_WIDTH,y+BFU_GRX_HEIGHT,b); drv->fill_area(dev,x+4.75*BFU_GRX_WIDTH,y,x+5*BFU_GRX_WIDTH,y+BFU_GRX_HEIGHT,b); } drv->set_clip_area(dev, &r); return BFU_ELEMENT_WIDTH;#endif }}/* aux structure for parameter exchange for redrawing list window */struct redraw_data{ struct list_description *ld; struct dialog_data *dlg; int n;};void redraw_list(struct terminal *term, void *bla);void list_find_next(struct redraw_data *, int);void list_search_for_back(struct redraw_data *, unsigned char *);void list_search_for(struct redraw_data *, unsigned char *);/* returns next visible item in tree list *//* works only with visible items (head or any item returned by this function) *//* when list is flat returns next item */struct list *next_in_tree(struct list_description *ld, struct list *item){ int depth=item->depth; /* flat list */ if (!(ld->type))return item->next; if (!((item->type)&1)||((item->type)&2)) /* item or opened folder */ return item->next; /* skip content of this folder */ do item=item->next; while (item->depth>depth); /* must stop on head 'cause it's depth is -1 */ return item;}/* returns previous visible item in tree list *//* works only with visible items (head or any item returned by this function) *//* when list is flat returns previous item */struct list *prev_in_tree(struct list_description *ld, struct list *item){ struct list *last_closed; int depth=item->depth; /* flat list */ if (!(ld->type))return item->prev; if (item==ld->list)depth=0; /* items with same or lower depth must be visible, because current item is visible */ if ((((struct list*)(item->prev))->depth)<=(item->depth))return item->prev; /* find item followed with opened fotr's only */ /* searched item is last closed folder (going up from item) or item->prev */ last_closed=item->prev; item=item->prev; while (1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -