=== Custom Transform Orientation ===
[blender.git] / source / blender / src / header_text.c
1 /**
2  * header_text.c oct-2003
3  *
4  * Functions to draw the "Text Editor" window header
5  * and handle user events sent to it.
6  * 
7  * $Id$
8  *
9  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version. The Blender
15  * Foundation also sells licenses for use in proprietary software under
16  * the Blender License.  See http://www.blender.org/BL/ for information
17  * about this.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software Foundation,
26  * Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA.
27  *
28  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
29  * All rights reserved.
30  *
31  * The Original Code is: all of this file.
32  *
33  * Contributor(s): none yet.
34  *
35  * ***** END GPL/BL DUAL LICENSE BLOCK *****
36  */
37
38 #include <stdlib.h>
39 #include <string.h>
40 #include <stdio.h>
41
42 #ifdef HAVE_CONFIG_H
43 #include <config.h>
44 #endif
45
46 #include "BMF_Api.h"
47 #include "BIF_language.h"
48
49 #include "BSE_headerbuttons.h"
50
51 #include "DNA_ID.h"
52 #include "DNA_screen_types.h"
53 #include "DNA_space_types.h"
54 #include "DNA_text_types.h"
55 #include "DNA_constraint_types.h"
56 #include "DNA_action_types.h"
57
58 #include "BIF_drawtext.h"
59 #include "BIF_interface.h"
60 #include "BIF_resources.h"
61 #include "BIF_screen.h"
62 #include "BIF_space.h"
63 #include "BIF_toolbox.h"
64
65 #include "BKE_global.h"
66 #include "BKE_library.h"
67 #include "BKE_main.h"
68 #include "BKE_sca.h"
69 #include "BKE_text.h"
70 #include "BKE_depsgraph.h"
71
72 #include "BSE_filesel.h"
73
74 #include "BPY_extern.h"
75 #include "BPY_menus.h"
76
77 #include "blendef.h"
78 #include "mydevice.h"
79
80 void do_text_buttons(unsigned short event)
81 {
82         SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */
83         ID *id, *idtest;
84         int nr= 1;
85         Text *text;
86         
87         if (st==NULL || st->spacetype != SPACE_TEXT) return;
88         
89         switch (event) {
90         case B_TEXTBROWSE:
91                 if (st->menunr==-2) {
92                         activate_databrowse((ID *)st->text, ID_TXT, 0, B_TEXTBROWSE,
93                                                                                         &st->menunr, do_text_buttons);
94                         break;
95                 }
96                 if(st->menunr < 0) break;
97                         
98                 text= st->text;
99
100                 nr= 1;
101                 id= (ID *)text;
102                 
103                 if (st->menunr==32767) {
104                         st->text= (Text *)add_empty_text( "Text" );
105
106                         st->top= 0;
107                         
108                         allqueue(REDRAWTEXT, 0);
109                         allqueue(REDRAWHEADERS, 0); 
110                 }
111                 else if (st->menunr==32766) {
112                         activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, add_text_fs); 
113                         return;
114                 }
115                 else {          
116                         idtest= G.main->text.first;
117                         while(idtest) {
118                                 if(nr==st->menunr) {
119                                         break;
120                                 }
121                                 nr++;
122                                 idtest= idtest->next;
123                         }
124                         if(idtest==0) { /* new text */
125                                 activate_fileselect(FILE_SPECIAL, "Open Text File",
126                                                                                                 G.sce, add_text_fs); 
127                                 return;
128                         }
129                         if(idtest!=id) {
130                                 st->text= (Text *)idtest;
131                                 st->top= 0;
132                                 
133                                 pop_space_text(st);
134                                 if (st->showsyntax) get_format_string(st);
135                                 allqueue(REDRAWTEXT, 0);
136                                 allqueue(REDRAWHEADERS, 0);
137                         }
138                 }
139                 break;
140                 
141         case B_TEXTDELETE:
142                 {
143                         Object *obt;
144                         bConstraint *con;
145                         int update;
146                         
147                         text= st->text;
148                         if (!text) return;
149                         
150                         /* make the previous text active, if its not there make the next text active */
151                         if (st->text->id.prev) {
152                                 st->text = st->text->id.prev;
153                                 pop_space_text(st);
154                         } else if (st->text->id.next) {
155                                 st->text = st->text->id.next;
156                                 pop_space_text(st);
157                         }
158                         
159                         /*check all pyconstraints*/
160                         for (obt=G.main->object.first; obt; obt=obt->id.next) {
161                                 update = 0;
162                                 if(obt->type==OB_ARMATURE && obt->pose) {
163                                         bPoseChannel *pchan;
164                                         for(pchan= obt->pose->chanbase.first; pchan; pchan= pchan->next) {
165                                                 for (con = pchan->constraints.first; con; con=con->next) {
166                                                         if (con->type==CONSTRAINT_TYPE_PYTHON) {
167                                                                 bPythonConstraint *data = con->data;
168                                                                 if (data->text==text) data->text = NULL;
169                                                                 update = 1;
170                                                                 
171                                                         }
172                                                 }
173                                         }
174                                 }
175                                 for (con = obt->constraints.first; con; con=con->next) {
176                                         if (con->type==CONSTRAINT_TYPE_PYTHON) {
177                                                 bPythonConstraint *data = con->data;
178                                                 if (data->text==text) data->text = NULL;
179                                                 update = 1;
180                                         }
181                                 }
182                                 
183                                 if (update) {
184                                         DAG_object_flush_update(G.scene, obt, OB_RECALC_DATA);
185                                 }
186                         }
187                         
188                         BPY_clear_bad_scriptlinks(text);
189                         free_text_controllers(text);
190                         
191                         unlink_text(text);
192                         free_libblock(&G.main->text, text);
193                         
194                         allqueue(REDRAWTEXT, 0);
195                         allqueue(REDRAWHEADERS, 0);
196                         
197                         /*for if any object constraints were changed.*/
198                         allqueue(REDRAWVIEW3D, 0);
199                         allqueue(REDRAWBUTSOBJECT, 0);
200                         allqueue(REDRAWBUTSEDIT, 0);
201                         
202                         BIF_undo_push("Delete Text");
203                 }
204                 break;
205                 
206 /*
207         case B_TEXTSTORE:
208                 st->text->flags ^= TXT_ISEXT;
209                 
210                 allqueue(REDRAWHEADERS, 0);
211                 break;
212 */               
213         case B_TEXTLINENUM:
214                 allqueue(REDRAWTEXT, 0);
215                 allqueue(REDRAWHEADERS, 0);
216                 break;
217
218         case B_TEXTFONT:
219                 switch(st->font_id) {
220                 case 0:
221                         st->lheight= 12; break;
222                 case 1:
223                         st->lheight= 15; 
224                         break;
225                 }
226                         
227                 allqueue(REDRAWTEXT, 0);
228                 allqueue(REDRAWHEADERS, 0);
229
230                 break;
231         case B_TAB_NUMBERS:
232                 if (st->showsyntax) get_format_string(st);
233                 allqueue(REDRAWTEXT, 0);
234                 allqueue(REDRAWHEADERS, 0);
235                 break;
236         case B_SYNTAX:
237                 if (st->showsyntax) {
238                         get_format_string(st);
239                 }
240                 allqueue(REDRAWTEXT, 0);
241                 allqueue(REDRAWHEADERS, 0);
242                 break;
243         }
244 }
245
246 static void do_text_template_scriptsmenu(void *arg, int event)
247 {
248         BPY_menu_do_python(PYMENU_SCRIPTTEMPLATE, event);
249         
250         allqueue(REDRAWIMAGE, 0);
251 }
252
253 static uiBlock *text_template_scriptsmenu (void *args_unused)
254 {
255         uiBlock *block;
256         BPyMenu *pym;
257         int i= 0;
258         short yco = 20, menuwidth = 120;
259         
260         block= uiNewBlock(&curarea->uiblocks, "text_template_scriptsmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
261         uiBlockSetButmFunc(block, do_text_template_scriptsmenu, NULL);
262         
263         /* note that we acount for the N previous entries with i+20: */
264         for (pym = BPyMenuTable[PYMENU_SCRIPTTEMPLATE]; pym; pym = pym->next, i++) {
265                 
266                 uiDefIconTextBut(block, BUTM, 1, ICON_PYTHON, pym->name, 0, yco-=20, menuwidth, 19, 
267                                                  NULL, 0.0, 0.0, 1, i, 
268                                                  pym->tooltip?pym->tooltip:pym->filename);
269         }
270         
271         uiBlockSetDirection(block, UI_RIGHT);
272         uiTextBoundsBlock(block, 60);
273         
274         return block;
275 }
276
277 /* action executed after clicking in File menu */
278 static void do_text_filemenu(void *arg, int event)
279 {
280         SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */
281         Text *text;
282         ScrArea *sa;
283         
284         if (st==NULL || st->spacetype != SPACE_TEXT) return;
285         
286         text= st->text;
287         
288         switch(event) {
289         case 1:
290                 st->text= add_empty_text( "Text" );
291                 st->top=0;
292                 
293                 allqueue(REDRAWTEXT, 0);
294                 allqueue(REDRAWHEADERS, 0);
295                 break;
296         case 2:
297                 activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, add_text_fs);
298                 break;
299         case 3:
300                 if (text->compiled) BPY_free_compiled_text(text);
301                         text->compiled = NULL;
302                         if (okee("Reopen Text")) {
303                                 if (!reopen_text(text)) {
304                                         error("Could not reopen file");
305                                 }
306                         if (st->showsyntax) get_format_string(st);
307                         }
308                 break;
309         case 5:
310                 text->flags |= TXT_ISMEM;
311         case 4:
312                 txt_write_file(text);
313                 break;
314         case 6:
315                 run_python_script(st);
316                 break;
317         case 7:
318         {
319                 Object *ob;
320                 bConstraint *con;
321                 short update;
322                 
323                 /* check all pyconstraints */
324                 for (ob= G.main->object.first; ob; ob= ob->id.next) {
325                         update = 0;
326                         if (ob->type==OB_ARMATURE && ob->pose) {
327                                 bPoseChannel *pchan;
328                                 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
329                                         for (con = pchan->constraints.first; con; con= con->next) {
330                                                 if (con->type==CONSTRAINT_TYPE_PYTHON) {
331                                                         bPythonConstraint *data = con->data;
332                                                         if (data->text==text) BPY_pyconstraint_update(ob, con);
333                                                         update = 1;
334                                                         
335                                                 }
336                                         }
337                                 }
338                         }
339                         for (con = ob->constraints.first; con; con= con->next) {
340                                 if (con->type==CONSTRAINT_TYPE_PYTHON) {
341                                         bPythonConstraint *data = con->data;
342                                         if (data->text==text) BPY_pyconstraint_update(ob, con);
343                                         update = 1;
344                                 }
345                         }
346                         
347                         if (update) {
348                                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
349                         }
350                 }
351         }
352                 break;
353         default:
354                 break;
355         }
356         for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
357                 SpaceText *st= sa->spacedata.first;
358                 if (st && st->spacetype==SPACE_TEXT) {
359                         scrarea_queue_redraw(sa);
360                 }
361         }
362 }
363
364 /* action executed after clicking in Edit menu */
365 static void do_text_editmenu(void *arg, int event)
366 {
367         SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */
368         Text *text;
369         ScrArea *sa;
370         
371         if (st==NULL || st->spacetype != SPACE_TEXT) return;
372         
373         text= st->text;
374         
375         switch(event) {
376         case 1:
377                 txt_do_undo(text);
378                 break;
379         case 2:
380                 txt_do_redo(text);
381                 break;
382         case 3:
383                 txt_cut_sel(text);
384                 pop_space_text(st);
385                 break;
386         case 4:
387                 txt_copy_sel(text);
388                 break;
389         case 5:
390                 txt_paste(text);
391                 if (st->showsyntax) get_format_string(st);
392                 break;
393         case 6:
394                 txt_print_cutbuffer();
395                 break;
396         case 7:
397                 jumptoline_interactive(st);
398                 break;
399         case 8:
400                 txt_find_panel(st,1);
401                 break;
402         case 9:
403                 txt_find_panel(st,0);
404                 break;
405         default:
406                 break;
407         }
408
409         for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
410                 SpaceText *st= sa->spacedata.first;
411                 if (st && st->spacetype==SPACE_TEXT) {
412                         scrarea_queue_redraw(sa);
413                 }
414         }
415 }
416
417 /* action executed after clicking in View menu */
418 static void do_text_editmenu_viewmenu(void *arg, int event)
419 {
420         SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */
421         Text *text;
422         ScrArea *sa;
423         
424         if (st==NULL || st->spacetype != SPACE_TEXT) return;
425         
426         text = st->text;
427         
428         switch(event) {
429                 case 1:
430                         txt_move_bof(text, 0);
431                         pop_space_text(st);
432                         break;
433                 case 2:
434                         txt_move_eof(text, 0);
435                         pop_space_text(st);
436                         break;
437                 default:
438                         break;
439         }
440
441         for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
442                 SpaceText *st= sa->spacedata.first;
443                 if (st && st->spacetype==SPACE_TEXT) {
444                         scrarea_queue_redraw(sa);
445                 }
446         }
447 }
448
449 /* action executed after clicking in Select menu */
450 static void do_text_editmenu_selectmenu(void *arg, int event)
451 {
452         SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */
453         Text *text;
454         ScrArea *sa;
455         
456         if (st==NULL || st->spacetype != SPACE_TEXT) return;
457         
458         text = st->text;
459         
460         switch(event) {
461         case 1:
462                 txt_sel_all(text);
463                 break;          
464         case 2:
465                 txt_sel_line(text);
466                 break;
467         default:
468                 break;
469         }
470
471         for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
472                 SpaceText *st= sa->spacedata.first;
473                 if (st && st->spacetype==SPACE_TEXT) {
474                         scrarea_queue_redraw(sa);
475                 }
476         }
477 }
478
479 /* action executed after clicking in Format menu */
480 static void do_text_formatmenu(void *arg, int event)
481 {
482         SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */
483         Text *text;
484         ScrArea *sa;
485         
486         if (st==NULL || st->spacetype != SPACE_TEXT) return;
487         
488         text = st->text;
489         
490         switch(event) {
491         case 3:
492                 if (txt_has_sel(text)) {
493                         txt_order_cursors(text);
494                         indent(text);
495                         break;
496                 }
497                 else {
498                         txt_add_char(text, '\t');
499                         break;
500                 }
501         case 4:
502                 if ( txt_has_sel(text)) {
503                         txt_order_cursors(text);
504                         unindent(text);
505                         break;
506                 }
507                 break;
508         case 5:
509                 if ( txt_has_sel(text)) {
510                         txt_order_cursors(text);
511                         comment(text);
512                         if (st->showsyntax) get_format_string(st);
513                         break;
514                 }
515                 break;
516         case 6:
517                 if ( txt_has_sel(text)) {
518                         txt_order_cursors(text);
519                         uncomment(text);
520                         if (st->showsyntax) get_format_string(st);
521                         break;
522                 }
523                 break;
524         default:
525                 break;
526         }
527
528         for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
529                 SpaceText *st= sa->spacedata.first;
530                 if (st && st->spacetype==SPACE_TEXT) {
531                         scrarea_queue_redraw(sa);
532                 }
533         }
534 }
535
536 /* View menu */
537 static uiBlock *text_editmenu_viewmenu(void *arg_unused)
538 {
539         uiBlock *block;
540         short yco = 20, menuwidth = 120;
541
542         block= uiNewBlock(&curarea->uiblocks, "text_editmenu_viewmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
543         uiBlockSetButmFunc(block, do_text_editmenu_viewmenu, NULL);
544
545         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Top of File", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
546         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Bottom of File", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
547
548         uiBlockSetDirection(block, UI_RIGHT);
549         uiTextBoundsBlock(block, 60);
550         
551         return block;
552 }
553
554 /* Select menu */
555 static uiBlock *text_editmenu_selectmenu(void *arg_unused)
556 {
557         uiBlock *block;
558         short yco = 20, menuwidth = 120;
559
560         block= uiNewBlock(&curarea->uiblocks, "text_editmenu_selectmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
561         uiBlockSetButmFunc(block, do_text_editmenu_selectmenu, NULL);
562
563         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select All|Ctrl A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
564         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Line", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
565         
566         uiBlockSetDirection(block, UI_RIGHT);
567         uiTextBoundsBlock(block, 60);
568         
569         return block;
570 }
571
572 void do_text_formatmenu_convert(void *arg, int event)
573 {
574         SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */
575         
576         if (st==NULL || st->spacetype != SPACE_TEXT) return;
577         
578         switch(event) {
579         case 1: convert_tabs(st, 0); break;
580         case 2: convert_tabs(st, 1); break;
581         }
582         allqueue(REDRAWVIEW3D, 0);
583 }
584
585 static uiBlock *text_formatmenu_convert(void *arg_unused)
586 {
587         uiBlock *block;
588         short yco = 20, menuwidth = 120;
589
590         block= uiNewBlock(&curarea->uiblocks, "do_text_formatmenu_convert", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
591         uiBlockSetButmFunc(block, do_text_formatmenu_convert, NULL);
592
593         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "To Spaces",              0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "Converts script whitespace to spaces based on Tab:");
594         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "To Tabs",                0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "Converts script whitespace to tabs based on Tab:");
595         
596         uiBlockSetDirection(block, UI_RIGHT);
597         uiTextBoundsBlock(block, 60);
598         return block;
599 }
600
601 /* Format menu */
602 static uiBlock *text_formatmenu(void *arg_unused)
603 {
604         uiBlock *block;
605         short yco= 0, menuwidth=120;
606
607         block= uiNewBlock(&curarea->uiblocks, "text_formatmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
608         uiBlockSetButmFunc(block, do_text_formatmenu, NULL);
609
610         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
611         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Indent|Tab", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
612         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Unindent|Shift Tab", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
613         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
614         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Comment", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
615         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Uncomment|Ctrl Shift D", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");
616         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
617         uiDefIconTextBlockBut(block, text_formatmenu_convert, NULL, ICON_RIGHTARROW_THIN, "Convert whitespace", 0, yco-=20, menuwidth, 19, "");
618         
619         if(curarea->headertype==HEADERTOP) {
620                 uiBlockSetDirection(block, UI_DOWN);
621         }
622         else {
623                 uiBlockSetDirection(block, UI_TOP);
624                 uiBlockFlipOrder(block);
625         }
626
627         uiTextBoundsBlock(block, 50);
628         return block;
629 }
630
631
632 /* action executed after clicking in Object to 3d Sub Menu */
633 void do_text_editmenu_to3dmenu(void *arg, int event)
634 {
635         SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */
636         Text *text;
637         if (st==NULL || st->spacetype != SPACE_TEXT) return;
638         
639         text = st->text;
640         
641         switch(event) {
642         case 1: txt_export_to_object(text); break;
643         case 2: txt_export_to_objects(text); break;
644         }
645         allqueue(REDRAWVIEW3D, 0);
646 }
647
648 /* Object to 3d Sub Menu */
649 static uiBlock *text_editmenu_to3dmenu(void *arg_unused)
650 {
651         uiBlock *block;
652         short yco = 20, menuwidth = 120;
653
654         block= uiNewBlock(&curarea->uiblocks, "do_text_editmenu_to3dmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
655         uiBlockSetButmFunc(block, do_text_editmenu_to3dmenu, NULL);
656
657         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "One Object | Alt-M",             0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
658         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "One Object Per Line",            0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
659         
660         uiBlockSetDirection(block, UI_RIGHT);
661         uiTextBoundsBlock(block, 60);
662         return block;
663 }
664
665
666 /* Edit menu */
667 static uiBlock *text_editmenu(void *arg_unused)
668 {
669         uiBlock *block;
670         short yco= 0, menuwidth=120;
671
672         block= uiNewBlock(&curarea->uiblocks, "text_editmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
673         uiBlockSetButmFunc(block, do_text_editmenu, NULL);
674
675         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Undo|Ctrl Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
676         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Redo|Ctrl Shift Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
677         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
678         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Cut|Alt X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
679         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Copy|Alt C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
680         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Paste|Alt V", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
681         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Print Cut Buffer", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");
682         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
683         uiDefIconTextBlockBut(block, text_editmenu_viewmenu, NULL, ICON_RIGHTARROW_THIN, "View|Alt Shift V   ", 0, yco-=20, 120, 19, "");
684         uiDefIconTextBlockBut(block, text_editmenu_selectmenu, NULL, ICON_RIGHTARROW_THIN, "Select|Alt Shift S   ", 0, yco-=20, 120, 19, "");
685         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
686         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Jump...|Alt J", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, "");
687         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find...|Alt Ctrl F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, "");
688         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find Again|Alt F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, "");
689         uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
690         uiDefIconTextBlockBut(block, text_editmenu_to3dmenu, NULL, ICON_RIGHTARROW_THIN, "Text to 3d Object", 0, yco-=20, 120, 19, "");
691         
692         if(curarea->headertype==HEADERTOP) {
693                 uiBlockSetDirection(block, UI_DOWN);
694         }
695         else {
696                 uiBlockSetDirection(block, UI_TOP);
697                 uiBlockFlipOrder(block);
698         }
699
700         uiTextBoundsBlock(block, 50);
701         return block;
702 }
703
704 /* File menu */
705 static uiBlock *text_filemenu(void *arg_unused)
706 {
707         SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */
708         Text *text= st->text;
709         uiBlock *block;
710         short yco= 0, menuwidth=120;
711
712         block= uiNewBlock(&curarea->uiblocks, "text_filemenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
713         uiBlockSetButmFunc(block, do_text_filemenu, NULL);
714
715         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "New|Alt N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
716         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Open...|Alt O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
717         
718         if(text) {
719                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reopen|Alt R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
720                 
721                 uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
722                 
723                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save|Alt S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
724                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save As...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
725                 
726                 uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
727                 
728                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Run Python Script|Alt P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");
729                 
730                 if (BPY_is_pyconstraint(text))
731                         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Refresh All PyConstraints", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, "");
732                         
733                 uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
734         }
735         
736         uiDefIconTextBlockBut(block, text_template_scriptsmenu, NULL, ICON_RIGHTARROW_THIN, "Script Templates", 0, yco-=20, 120, 19, "");
737
738         if(curarea->headertype==HEADERTOP) {
739                 uiBlockSetDirection(block, UI_DOWN);
740         }
741         else {
742                 uiBlockSetDirection(block, UI_TOP);
743                 uiBlockFlipOrder(block);
744         }
745
746         uiTextBoundsBlock(block, 50);
747         return block;
748 }
749
750 /* header */
751 void text_buttons(void)
752 {
753         uiBlock *block;
754         SpaceText *st= curarea->spacedata.first;
755         Text *text;
756         short xco, xmax;
757         char naam[256];
758         
759         if (st==NULL || st->spacetype != SPACE_TEXT) return;
760         
761         text = st->text;
762
763         sprintf(naam, "header %d", curarea->headwin);
764         block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSS, UI_HELV, curarea->headwin);
765
766         if(area_is_active_area(curarea)) uiBlockSetCol(block, TH_HEADER);
767         else uiBlockSetCol(block, TH_HEADERDESEL);
768
769         curarea->butspacetype= SPACE_TEXT;
770
771         xco = 8;
772         uiDefIconTextButC(block, ICONTEXTROW,B_NEWSPACE, ICON_VIEW3D, windowtype_pup(), xco,0,XIC+10,YIC, &(curarea->butspacetype), 1.0, SPACEICONMAX, 0, 0, "Displays Current Window Type. Click for menu of available types.");
773         xco+= XIC+14;
774
775         uiBlockSetEmboss(block, UI_EMBOSSN);
776         if(curarea->flag & HEADER_NO_PULLDOWN) {
777                 uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, B_FLIPINFOMENU, ICON_DISCLOSURE_TRI_RIGHT,
778                                 xco,2,XIC,YIC-2,
779                                 &(curarea->flag), 0, 0, 0, 0, "Enables display of pulldown menus");
780         } else {
781                 uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, B_FLIPINFOMENU, ICON_DISCLOSURE_TRI_DOWN,
782                                 xco,2,XIC,YIC-2,
783                                 &(curarea->flag), 0, 0, 0, 0, "Hides pulldown menus");
784         }
785         uiBlockSetEmboss(block, UI_EMBOSS);
786         xco+=XIC;
787
788         /* pull down menus */
789         if((curarea->flag & HEADER_NO_PULLDOWN)==0) {
790                 uiBlockSetEmboss(block, UI_EMBOSSP);
791         
792                 xmax= GetButStringLength("File");
793                 uiDefPulldownBut(block,text_filemenu, NULL, "File", xco, 0, xmax, 20, "");
794                 xco+=xmax;
795         
796                 if(text) {
797                         xmax= GetButStringLength("Edit");
798                         uiDefPulldownBut(block,text_editmenu, NULL, "Edit", xco, 0, xmax, 20, "");
799                         xco+=xmax;
800                         
801                         xmax= GetButStringLength("Format");
802                         uiDefPulldownBut(block,text_formatmenu, NULL, "Format", xco, 0, xmax, 20, "");
803                         xco+=xmax;
804                 }
805         }
806         uiBlockSetEmboss(block, UI_EMBOSS);
807         xco += 10;
808         
809         /* FULL WINDOW */
810         uiBlockBeginAlign(block);
811         if(curarea->full) uiDefIconBut(block, BUT,B_FULL, ICON_SPLITSCREEN,     xco,0,XIC,YIC, 0, 0, 0, 0, 0, "Returns to multiple views window (CTRL+Up arrow)");
812         else uiDefIconBut(block, BUT,B_FULL, ICON_FULLSCREEN,   xco,0,XIC,YIC, 0, 0, 0, 0, 0, "Makes current window full screen (CTRL+Down arrow)");
813                 
814         uiDefIconButI(block, ICONTOG, B_TEXTLINENUM, ICON_LONGDISPLAY, xco+=XIC,0,XIC,YIC, &st->showlinenrs, 0, 0, 0, 0, "Displays line numbers");
815
816         uiDefIconButI(block, ICONTOG, B_SYNTAX, ICON_SYNTAX, xco+=XIC,0,XIC,YIC, &st->showsyntax, 0, 0, 0, 0, "Enables Syntax Highlighting");
817         uiBlockEndAlign(block);
818         
819         /* STD TEXT BUTTONS */
820         xco+= 2*XIC;
821         xco= std_libbuttons(block, xco, 0, 0, NULL, B_TEXTBROWSE, ID_TXT, 0, (ID*)st->text, 0, &(st->menunr), 0, 0, B_TEXTDELETE, 0, 0);
822
823         /*
824         if (st->text) {
825                 if (st->text->flags & TXT_ISDIRTY && (st->text->flags & TXT_ISEXT || !(st->text->flags & TXT_ISMEM)))
826                         uiDefIconBut(block, BUT,0, ICON_ERROR, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "The text has been changed");
827                 if (st->text->flags & TXT_ISEXT) 
828                         uiDefBut(block, BUT,B_TEXTSTORE, ICON(),        xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Stores text in project file");
829                 else 
830                         uiDefBut(block, BUT,B_TEXTSTORE, ICON(),        xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Disables storing of text in project file");
831                 xco+=10;
832         }
833         */              
834
835         xco+=XIC;
836         if(st->font_id>1) st->font_id= 0;
837         uiDefButI(block, MENU, B_TEXTFONT, "Screen 12 %x0|Screen 15%x1", xco,0,100,YIC, &st->font_id, 0, 0, 0, 0, "Displays available fonts");
838         xco+=110;
839         
840         uiDefButI(block, NUM, B_TAB_NUMBERS, "Tab:",            xco, 0, XIC+50, YIC, &st->tabnumber, 2, 8, 0, 0, "Set spacing of Tab");
841         xco+= XIC+50;
842         
843         /* always as last  */
844         curarea->headbutlen= xco+2*XIC;
845
846         uiDrawBlock(block);
847 }