All functions with a doc as first argument returns it in mp_search.mpsl (except for...
[mp-5.x.git] / mp_clipboard.mpsl
blob43b761b621f9734af7f161cab51feb6c77f326db
1 /*
3     Minimum Profit 5.x
4     A Programmer's Text Editor
6     Clipboard routines.
8     Copyright (C) 1991-2007 Angel Ortega <angel@triptico.com>
10     This program is free software; you can redistribute it and/or
11     modify it under the terms of the GNU General Public License
12     as published by the Free Software Foundation; either version 2
13     of the License, or (at your option) any later version.
15     This program is distributed in the hope that it will be useful,
16     but WITHOUT ANY WARRANTY; without even the implied warranty of
17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18     GNU General Public License for more details.
20     You should have received a copy of the GNU General Public License
21     along with this program; if not, write to the Free Software
22     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24     http://www.triptico.com
28 /** editor actions **/
31 mp.actions['unmark']    = sub (d) { mp.unmark(d); };
32 mp.actions['mark']      = sub (d) { mp.mark(d); };
33 mp.actions['mark_vertical'] = sub (d) { mp.mark_vertical(d); };
34 mp.actions['copy_mark'] = sub (d) {
35                                         mp.busy(1);
36                                         mp.copy(d);
37                                         mp.unmark(d);
38                                         mp.busy(0);
39                                 };
41 mp.actions['paste_mark'] = sub (d) {
42                                         mp.busy(1);
43                                         mp.store_undo(d);
44                                         mp.paste(d);
45                                         mp.busy(0);
46                                 };
48 mp.actions['cut_mark']  = sub (d) {
49                                         mp.busy(1);
50                                         mp.store_undo(d);
51                                         mp.cut(d);
52                                         mp.busy(0);
53                                 };
55 mp.actions['delete_mark'] = sub (d) {
56                                         mp.busy(1);
57                                         mp.store_undo(d);
58                                         mp.delete_mark(d);
59                                         mp.busy(0);
60                                 };
62 mp.actions['mouse_drag_mark'] = sub (d) {
64         /* no selection yet? move to initial click and mark */
65         if (d.txt.mark == NULL)
66                 mp.mark(d);
68         /* move to drag position */
69         mp.move_to_coords_xy(d, mp.mouse_to_x, mp.mouse_to_y);
71         /* and mark */
72         mp.mark(d);
75 /** default key bindings **/
77 mp.keycodes['f8']               = "unmark";
78 mp.keycodes['f9']               = "mark";
79 mp.keycodes['ctrl-b']           = "mark_vertical";
80 mp.keycodes['ctrl-c']           = "copy_mark";
81 mp.keycodes['ctrl-v']           = "paste_mark";
82 mp.keycodes['ctrl-x']           = "cut_mark";
83 mp.keycodes['mouse-drag']       = "mouse_drag_mark";
85 /** action descriptions **/
87 mp.actdesc['unmark']            = LL("Unmark block");
88 mp.actdesc['mark']              = LL("Mark beginning/end of block");
89 mp.actdesc['mark_vertical']     = LL("Mark vertical block");
90 mp.actdesc['copy_mark']         = LL("Copy block");
91 mp.actdesc['paste_mark']        = LL("Paste block");
92 mp.actdesc['cut_mark']          = LL("Cut block");
93 mp.actdesc['delete_mark']       = LL("Delete block");
94 mp.actdesc['mouse_drag_mark']   = LL("Mark using mouse dragging");
96 /** code **/
99 sub mp.unmark(doc)
100 /* unmarks the block */
102         /* just destroy the mark */
103         doc.txt.mark = NULL;
105         return doc;
109 sub mp.mark(doc)
110 /* marks the start or end of the block */
112         local txt = doc.txt;
114         if (txt.mark == NULL) {
115                 /* no mark; create one */
116                 txt.mark = {};
117                 txt.mark.ax = txt.mark.bx = txt.mark.ex = txt.x;
118                 txt.mark.ay = txt.mark.by = txt.mark.ey = txt.y;
119                 txt.mark.vertical = 0;
120                 txt.mark.incomplete = 1;
121         }
122         else {
123                 /* mark exists; extend current one */
124                 if (txt.mark.vertical == 0) {
125                         /* normal selection */
126                         if (txt.y < txt.mark.ay ||
127                                 (txt.y == txt.mark.ay && txt.x < txt.mark.ax)) {
128                                 /* move the beginning of the block */
129                                 txt.mark.bx = txt.x;
130                                 txt.mark.by = txt.y;
131                                 txt.mark.ex = txt.mark.ax;
132                                 txt.mark.ey = txt.mark.ay;
133                         }
134                         else {
135                                 /* move the end of the block */
136                                 txt.mark.ex = txt.x;
137                                 txt.mark.ey = txt.y;
138                                 txt.mark.bx = txt.mark.ax;
139                                 txt.mark.by = txt.mark.ay;
140                         }
141                 }
142                 else {
143                         /* vertical selection */
144                         txt.mark.by = txt.mark.ay;
145                         txt.mark.ey = txt.y;
146                         if (txt.y < txt.mark.ay) {
147                                 txt.mark.by = txt.y;
148                                 txt.mark.ey = txt.mark.ay;
149                         }
151                         txt.mark.bx = txt.mark.ax;
152                         txt.mark.ex = txt.x;
153                         if (txt.x < txt.mark.ax) {
154                                 txt.mark.bx = txt.x;
155                                 txt.mark.ex = txt.mark.ax;
156                         }
157                 }
159                 txt.mark.incomplete = 0;
160         }
162         return doc;
166 sub mp.mark_vertical(doc)
167 /* start vertical block selection */
169         mp.mark(doc);
170         doc.txt.mark.vertical = 1;
172         return doc;
176 sub mp.get_active_area(doc)
177 /* returns the active area: the selection or the full document */
179         local m;
181         if ((m = doc.txt.mark) == NULL)
182                 return doc.txt.lines;
183         else
184                 return mp.get_range(doc, m.bx, m.by, m.ex, m.ey, m.vertical);
189  * mp.copy - Copies to the clipboard
190  * @doc: the source of the copy
192  * If @doc is a document, it copies to the clipboard the content of the
193  * selected block, if one exists. If @doc is an array or scalar, it copies
194  * that data directly into it.
195  */
196 sub mp.copy(doc)
198         if (is_hash(doc)) {
199                 if (doc.txt.mark) {
200                         mp.clipboard = mp.get_active_area(doc);
201                         mp.clipboard_vertical = doc.txt.mark.vertical;
203                         mp.drv.clip_to_sys();
204                 }
205         }
206         else {
207                 if (!is_array(doc))
208                         doc = split("\n", doc);
210                 mp.clipboard = doc;
211                 mp.clipboard_vertical = 0;
212                 mp.drv.clip_to_sys();
213         }
215         return doc;
219 sub mp.delete_mark(doc)
220 /* deletes current selection */
222         local txt = doc.txt;
224         /* no mark? done */
225         if (txt.mark != NULL) {
226                 /* deletes the range */
227                 mp.delete_range(doc, txt.mark.bx, txt.mark.by,
228                                         txt.mark.ex, txt.mark.ey, txt.mark.vertical);
230                 mp.unmark(doc);
231         }
233         return doc;
237 sub mp.cut(doc)
238 /* cut (copy + delete) selected mark */
240         mp.copy(doc);
241         mp.delete_mark(doc);
242         mp.drv.clip_to_sys();
244         return doc;
248 sub mp.paste(doc)
249 /* pastes from the clipboard into a text */
251         mp.drv.sys_to_clip();
253         if (size(mp.clipboard) == 0)
254                 return doc;
256         local t = mp.config.auto_indent;
257         mp.config.auto_indent = 0;
259         /* is there a block? replace it */
260         if (doc.txt.mark != NULL) {
261                 /* move there */
262                 doc.txt.x = doc.txt.mark.bx;
263                 doc.txt.y = doc.txt.mark.by;
265                 /* and delete the block */
266                 mp.delete_mark(doc);
267         }
269         if (mp.clipboard_vertical == 0) {
270                 /* normal selection in clipboard */
271                 mp.insert(doc, mp.clipboard);
272         }
273         else {
274                 /* vertical selection in clipboard */
275                 local txt = doc.txt;
276                 local s = size(mp.clipboard);
277                 local i = 0;
278                 local w;
279                 local e;
280                 while (i < s) {
281                         /* pad out to current x position */
282                         e = txt.x - size(txt.lines[txt.y]);
284                         while(e-- > 0)
285                                 txt.lines[txt.y] = txt.lines[txt.y] ~ " ";
286                         
287                         /* insert this line of the clipboard */
288                         w = splice(txt.lines[txt.y], mp.clipboard[i++], txt.x, 0);
289                         txt.lines[txt.y++] = w[0];
290                 }
291                 txt.y--;
292                 txt.mod++;
293         }
295         mp.config.auto_indent = t;
297         return doc;