doxygen: blender/editors tagged.
[blender.git] / source / blender / editors / space_console / space_console.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  * 
20  * Contributor(s): Campbell Barton
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 /** \file blender/editors/space_console/space_console.c
26  *  \ingroup spconsole
27  */
28
29 #include <string.h>
30 #include <stdio.h>
31
32 #ifdef WIN32
33 #include "BLI_winstuff.h"
34 #endif
35
36 #include "MEM_guardedalloc.h"
37
38 #include "BLI_blenlib.h"
39 #include "BLI_math.h"
40 #include "BLI_utildefines.h"
41
42 #include "BKE_context.h"
43 #include "BKE_screen.h"
44 #include "BKE_idcode.h"
45
46 #include "ED_space_api.h"
47 #include "ED_screen.h"
48
49 #include "BIF_gl.h"
50
51 #include "RNA_access.h"
52
53 #include "WM_api.h"
54 #include "WM_types.h"
55
56 #include "UI_resources.h"
57 #include "UI_view2d.h"
58
59 #include "console_intern.h"     // own include
60
61 /* ******************** default callbacks for console space ***************** */
62
63 static SpaceLink *console_new(const bContext *UNUSED(C))
64 {
65         ARegion *ar;
66         SpaceConsole *sconsole;
67         
68         sconsole= MEM_callocN(sizeof(SpaceConsole), "initconsole");
69         sconsole->spacetype= SPACE_CONSOLE;
70         
71         sconsole->lheight=      14;
72         
73         /* header */
74         ar= MEM_callocN(sizeof(ARegion), "header for console");
75         
76         BLI_addtail(&sconsole->regionbase, ar);
77         ar->regiontype= RGN_TYPE_HEADER;
78         ar->alignment= RGN_ALIGN_BOTTOM;
79         
80         
81         /* main area */
82         ar= MEM_callocN(sizeof(ARegion), "main area for text");
83         
84         BLI_addtail(&sconsole->regionbase, ar);
85         ar->regiontype= RGN_TYPE_WINDOW;
86         
87         /* keep in sync with info */
88         ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
89         ar->v2d.align |= V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_NEG_Y; /* align bottom left */
90         ar->v2d.keepofs |= V2D_LOCKOFS_X;
91         ar->v2d.keepzoom = (V2D_LOCKZOOM_X|V2D_LOCKZOOM_Y|V2D_LIMITZOOM|V2D_KEEPASPECT);
92         ar->v2d.keeptot= V2D_KEEPTOT_BOUNDS;
93         ar->v2d.minzoom= ar->v2d.maxzoom= 1.0f;
94
95         /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
96         //ar->v2d.keepzoom= (V2D_KEEPASPECT|V2D_LIMITZOOM);
97
98         return (SpaceLink *)sconsole;
99 }
100
101 /* not spacelink itself */
102 static void console_free(SpaceLink *sl)
103 {
104         SpaceConsole *sc= (SpaceConsole*) sl;
105         
106         while(sc->scrollback.first)
107                 console_scrollback_free(sc, sc->scrollback.first);
108         
109         while(sc->history.first)
110                 console_history_free(sc, sc->history.first);
111 }
112
113
114 /* spacetype; init callback */
115 static void console_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
116 {
117
118 }
119
120 static SpaceLink *console_duplicate(SpaceLink *sl)
121 {
122         SpaceConsole *sconsolen= MEM_dupallocN(sl);
123         
124         /* clear or remove stuff from old */
125         
126         /* TODO - duplicate?, then we also need to duplicate the py namespace */
127         sconsolen->scrollback.first= sconsolen->scrollback.last= NULL;
128         sconsolen->history.first= sconsolen->history.last= NULL;
129         
130         return (SpaceLink *)sconsolen;
131 }
132
133
134
135 /* add handlers, stuff you only do once or on area/region changes */
136 static void console_main_area_init(wmWindowManager *wm, ARegion *ar)
137 {
138         wmKeyMap *keymap;
139         ListBase *lb;
140
141         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
142
143         /* own keymap */
144         keymap= WM_keymap_find(wm->defaultconf, "Console", SPACE_CONSOLE, 0);
145         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
146         
147         /* add drop boxes */
148         lb= WM_dropboxmap_find("Console", SPACE_CONSOLE, RGN_TYPE_WINDOW);
149         
150         WM_event_add_dropbox_handler(&ar->handlers, lb);
151 }
152
153
154 /* ************* dropboxes ************* */
155
156 static int id_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
157 {
158 //      SpaceConsole *sc= CTX_wm_space_console(C);
159         if(drag->type==WM_DRAG_ID)
160                 return 1;
161         return 0;
162 }
163
164 static void id_drop_copy(wmDrag *drag, wmDropBox *drop)
165 {
166         char text[64];
167         ID *id= drag->poin;
168
169         snprintf(text, sizeof(text), "bpy.data.%s['%s']", BKE_idcode_to_name_plural(GS(id->name)), id->name+2); 
170
171         /* copy drag path to properties */
172         RNA_string_set(drop->ptr, "text", text);
173 }
174
175 static int path_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
176 {
177 //    SpaceConsole *sc= CTX_wm_space_console(C);
178         if(drag->type==WM_DRAG_PATH)
179                 return 1;
180         return 0;
181 }
182
183 static void path_drop_copy(wmDrag *drag, wmDropBox *drop)
184 {
185     char pathname[FILE_MAXDIR+FILE_MAXFILE+2];
186     snprintf(pathname, sizeof(pathname), "\"%s\"", drag->path);
187         RNA_string_set(drop->ptr, "text", pathname);
188 }
189
190
191 /* this region dropbox definition */
192 static void console_dropboxes(void)
193 {
194         ListBase *lb= WM_dropboxmap_find("Console", SPACE_CONSOLE, RGN_TYPE_WINDOW);
195         
196         WM_dropbox_add(lb, "CONSOLE_OT_insert", id_drop_poll, id_drop_copy);
197         WM_dropbox_add(lb, "CONSOLE_OT_insert", path_drop_poll, path_drop_copy);
198 }
199
200 /* ************* end drop *********** */
201
202 static void console_main_area_draw(const bContext *C, ARegion *ar)
203 {
204         /* draw entirely, view changes should be handled here */
205         SpaceConsole *sc= CTX_wm_space_console(C);
206         View2D *v2d= &ar->v2d;
207         View2DScrollers *scrollers;
208
209         if(sc->scrollback.first==NULL)
210                 WM_operator_name_call((bContext *)C, "CONSOLE_OT_banner", WM_OP_EXEC_DEFAULT, NULL);
211
212         /* clear and setup matrix */
213         UI_ThemeClearColor(TH_BACK);
214         glClear(GL_COLOR_BUFFER_BIT);
215
216         /* worlks best with no view2d matrix set */
217         UI_view2d_view_ortho(v2d);
218
219         /* data... */
220
221         console_history_verify(C); /* make sure we have some command line */
222         console_textview_main(sc, ar);
223         
224         /* reset view matrix */
225         UI_view2d_view_restore(C);
226         
227         /* scrollers */
228         scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_GRID_CLAMP);
229         UI_view2d_scrollers_draw(C, v2d, scrollers);
230         UI_view2d_scrollers_free(scrollers);
231 }
232
233 static void console_operatortypes(void)
234 {
235         /* console_ops.c */
236         WM_operatortype_append(CONSOLE_OT_move);
237         WM_operatortype_append(CONSOLE_OT_delete);
238         WM_operatortype_append(CONSOLE_OT_insert);
239         
240         /* for use by python only */
241         WM_operatortype_append(CONSOLE_OT_history_append); 
242         WM_operatortype_append(CONSOLE_OT_scrollback_append);
243         
244         WM_operatortype_append(CONSOLE_OT_clear); 
245         WM_operatortype_append(CONSOLE_OT_history_cycle);
246         WM_operatortype_append(CONSOLE_OT_copy);
247         WM_operatortype_append(CONSOLE_OT_paste);
248         WM_operatortype_append(CONSOLE_OT_select_set);
249 }
250
251 static void console_keymap(struct wmKeyConfig *keyconf)
252 {
253         wmKeyMap *keymap= WM_keymap_find(keyconf, "Console", SPACE_CONSOLE, 0);
254         wmKeyMapItem *kmi;
255         
256 #ifdef __APPLE__
257         RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", LEFTARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", LINE_BEGIN);
258         RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", RIGHTARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", LINE_END);
259 #endif
260
261         RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", PREV_WORD);
262         RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", NEXT_WORD);
263         
264         RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", HOMEKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_BEGIN);
265         RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", ENDKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_END);
266         
267         kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", WHEELUPMOUSE, KM_PRESS, KM_CTRL, 0);
268         RNA_string_set(kmi->ptr, "data_path", "space_data.font_size");
269         RNA_boolean_set(kmi->ptr, "reverse", 0);
270         
271         kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL, 0);
272         RNA_string_set(kmi->ptr, "data_path", "space_data.font_size");
273         RNA_boolean_set(kmi->ptr, "reverse", 1);
274
275         kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
276         RNA_string_set(kmi->ptr, "data_path", "space_data.font_size");
277         RNA_boolean_set(kmi->ptr, "reverse", 0);
278         
279         kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", PADMINUS, KM_PRESS, KM_CTRL, 0);
280         RNA_string_set(kmi->ptr, "data_path", "space_data.font_size");
281         RNA_boolean_set(kmi->ptr, "reverse", 1);
282
283         RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", LEFTARROWKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_CHAR);
284         RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", RIGHTARROWKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_CHAR);
285         
286         RNA_boolean_set(WM_keymap_add_item(keymap, "CONSOLE_OT_history_cycle", UPARROWKEY, KM_PRESS, 0, 0)->ptr, "reverse", 1);
287         WM_keymap_add_item(keymap, "CONSOLE_OT_history_cycle", DOWNARROWKEY, KM_PRESS, 0, 0);
288         
289         /*
290         RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", PREV_WORD);
291         RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", NEXT_WORD);
292         RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", UPARROWKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_LINE);
293         RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", DOWNARROWKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_LINE);
294         RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", PAGEUPKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_PAGE);
295         RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", PAGEDOWNKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_PAGE);
296
297
298         //RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", DELKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_NEXT_CHAR);
299         RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", DKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_NEXT_CHAR);
300         //RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", BACKSPACEKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_PREV_CHAR);
301         RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", DELKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_NEXT_WORD);
302         RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", BACKSPACEKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_PREV_WORD);
303         */
304         
305         RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", DELKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_NEXT_CHAR);
306         RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", BACKSPACEKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_PREV_CHAR);
307
308 #ifdef WITH_PYTHON
309         WM_keymap_add_item(keymap, "CONSOLE_OT_execute", RETKEY, KM_PRESS, 0, 0); /* python operator - space_text.py */
310         WM_keymap_add_item(keymap, "CONSOLE_OT_execute", PADENTER, KM_PRESS, 0, 0);
311         
312         //WM_keymap_add_item(keymap, "CONSOLE_OT_autocomplete", TABKEY, KM_PRESS, 0, 0); /* python operator - space_text.py */
313         WM_keymap_add_item(keymap, "CONSOLE_OT_autocomplete", SPACEKEY, KM_PRESS, KM_CTRL, 0); /* python operator - space_text.py */
314 #endif
315
316         WM_keymap_add_item(keymap, "CONSOLE_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
317         WM_keymap_add_item(keymap, "CONSOLE_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
318 #ifdef __APPLE__
319         WM_keymap_add_item(keymap, "CONSOLE_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0);
320         WM_keymap_add_item(keymap, "CONSOLE_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0);
321 #endif
322         
323         WM_keymap_add_item(keymap, "CONSOLE_OT_select_set", LEFTMOUSE, KM_PRESS, 0, 0);
324
325         RNA_string_set(WM_keymap_add_item(keymap, "CONSOLE_OT_insert", TABKEY, KM_PRESS, 0, 0)->ptr, "text", "\t"); /* fake tabs */
326         WM_keymap_add_item(keymap, "CONSOLE_OT_insert", KM_TEXTINPUT, KM_ANY, KM_ANY, 0); // last!
327 }
328
329 /****************** header region ******************/
330
331 /* add handlers, stuff you only do once or on area/region changes */
332 static void console_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
333 {
334         ED_region_header_init(ar);
335 }
336
337 static void console_header_area_draw(const bContext *C, ARegion *ar)
338 {
339         ED_region_header(C, ar);
340 }
341
342 static void console_main_area_listener(ARegion *ar, wmNotifier *wmn)
343 {
344         // SpaceInfo *sinfo= sa->spacedata.first;
345
346         /* context changes */
347         switch(wmn->category) {
348                 case NC_SPACE:
349                         if(wmn->data == ND_SPACE_CONSOLE) { /* generic redraw request */
350                                 ED_region_tag_redraw(ar);
351                         }
352                         break;
353         }
354 }
355
356 /* only called once, from space/spacetypes.c */
357 void ED_spacetype_console(void)
358 {
359         SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype console");
360         ARegionType *art;
361         
362         st->spaceid= SPACE_CONSOLE;
363         strncpy(st->name, "Console", BKE_ST_MAXNAME);
364         
365         st->new= console_new;
366         st->free= console_free;
367         st->init= console_init;
368         st->duplicate= console_duplicate;
369         st->operatortypes= console_operatortypes;
370         st->keymap= console_keymap;
371         st->dropboxes= console_dropboxes;
372         
373         /* regions: main window */
374         art= MEM_callocN(sizeof(ARegionType), "spacetype console region");
375         art->regionid = RGN_TYPE_WINDOW;
376         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
377
378         art->init= console_main_area_init;
379         art->draw= console_main_area_draw;
380         art->listener= console_main_area_listener;
381         
382         
383
384         BLI_addhead(&st->regiontypes, art);
385         
386         /* regions: header */
387         art= MEM_callocN(sizeof(ARegionType), "spacetype console region");
388         art->regionid = RGN_TYPE_HEADER;
389         art->prefsizey= HEADERY;
390         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_HEADER;
391         
392         art->init= console_header_area_init;
393         art->draw= console_header_area_draw;
394         
395         BLI_addhead(&st->regiontypes, art);
396
397
398         BKE_spacetype_register(st);
399 }