2 * header_text.c oct-2003
4 * Functions to draw the "Text Editor" window header
5 * and handle user events sent to it.
9 * ***** BEGIN GPL LICENSE BLOCK *****
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.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software Foundation,
23 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
26 * All rights reserved.
28 * The Original Code is: all of this file.
30 * Contributor(s): none yet.
32 * ***** END GPL LICENSE BLOCK *****
39 /* file time checking */
41 #include <sys/types.h>
48 #include "BLI_winstuff.h"
56 #include "BIF_language.h"
57 #include "MEM_guardedalloc.h"
59 #include "BSE_headerbuttons.h"
62 #include "DNA_screen_types.h"
63 #include "DNA_space_types.h"
64 #include "DNA_text_types.h"
65 #include "DNA_constraint_types.h"
66 #include "DNA_action_types.h"
68 #include "BIF_gl.h" /* for glRasterPos2i */
69 #include "BIF_drawtext.h"
70 #include "BIF_interface.h"
71 #include "BIF_resources.h"
72 #include "BIF_screen.h"
73 #include "BIF_space.h"
74 #include "BIF_toolbox.h"
76 #include "BKE_global.h"
77 #include "BKE_library.h"
81 #include "BKE_depsgraph.h"
83 #include "BSE_filesel.h"
85 #include "BLI_blenlib.h"
87 #ifndef DISABLE_PYTHON
88 #include "BPY_extern.h"
89 #include "BPY_menus.h"
95 extern void redraw_alltext(void); /* defined in drawtext.c */
97 void do_text_buttons(unsigned short event)
99 SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */
104 if (st==NULL || st->spacetype != SPACE_TEXT) return;
108 if (st->menunr==-2) {
109 activate_databrowse((ID *)st->text, ID_TXT, 0, B_TEXTBROWSE,
110 &st->menunr, do_text_buttons);
113 if(st->menunr < 0) break;
120 if (st->menunr==32767) {
121 st->text= (Text *)add_empty_text( "Text" );
125 allqueue(REDRAWTEXT, 0);
126 allqueue(REDRAWHEADERS, 0);
128 else if (st->menunr==32766) {
129 activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, add_text_fs);
133 idtest= G.main->text.first;
139 idtest= idtest->next;
141 if(idtest==0) { /* new text */
142 activate_fileselect(FILE_SPECIAL, "Open Text File",
147 st->text= (Text *)idtest;
151 if (st->showsyntax) txt_format_text(st);
152 allqueue(REDRAWTEXT, 0);
153 allqueue(REDRAWHEADERS, 0);
163 /* make the previous text active, if its not there make the next text active */
164 if (st->text->id.prev) {
165 st->text = st->text->id.prev;
167 } else if (st->text->id.next) {
168 st->text = st->text->id.next;
172 #ifndef DISABLE_PYTHON
173 BPY_clear_bad_scriptlinks(text);
174 BPY_free_pyconstraint_links(text);
175 free_text_controllers(text);
178 free_libblock(&G.main->text, text);
180 allqueue(REDRAWTEXT, 0);
181 allqueue(REDRAWHEADERS, 0);
183 /*for if any object constraints were changed.*/
184 allqueue(REDRAWVIEW3D, 0);
185 allqueue(REDRAWBUTSOBJECT, 0);
186 allqueue(REDRAWBUTSEDIT, 0);
188 BIF_undo_push("Delete Text");
194 st->text->flags ^= TXT_ISEXT;
196 allqueue(REDRAWHEADERS, 0);
200 allqueue(REDRAWTEXT, 0);
201 allqueue(REDRAWHEADERS, 0);
205 switch(st->font_id) {
207 st->lheight= 12; break;
213 allqueue(REDRAWTEXT, 0);
214 allqueue(REDRAWHEADERS, 0);
218 if (st->showsyntax) txt_format_text(st);
219 allqueue(REDRAWTEXT, 0);
220 allqueue(REDRAWHEADERS, 0);
223 if (st->showsyntax) txt_format_text(st);
224 allqueue(REDRAWTEXT, 0);
225 allqueue(REDRAWHEADERS, 0);
228 allqueue(REDRAWHEADERS, 0);
232 allqueue(REDRAWTEXT, 0);
233 allqueue(REDRAWHEADERS, 0);
237 #ifndef DISABLE_PYTHON
238 static void do_text_template_scriptsmenu(void *arg, int event)
240 BPY_menu_do_python(PYMENU_SCRIPTTEMPLATE, event);
242 allqueue(REDRAWIMAGE, 0);
245 static uiBlock *text_template_scriptsmenu (void *args_unused)
250 short yco = 20, menuwidth = 120;
252 block= uiNewBlock(&curarea->uiblocks, "text_template_scriptsmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
253 uiBlockSetButmFunc(block, do_text_template_scriptsmenu, NULL);
255 /* note that we acount for the N previous entries with i+20: */
256 for (pym = BPyMenuTable[PYMENU_SCRIPTTEMPLATE]; pym; pym = pym->next, i++) {
258 uiDefIconTextBut(block, BUTM, 1, ICON_PYTHON, pym->name, 0, yco-=20, menuwidth, 19,
259 NULL, 0.0, 0.0, 1, i,
260 pym->tooltip?pym->tooltip:pym->filename);
263 uiBlockSetDirection(block, UI_RIGHT);
264 uiTextBoundsBlock(block, 60);
269 static void do_text_plugin_scriptsmenu(void *arg, int event)
271 BPY_menu_do_python(PYMENU_TEXTPLUGIN, event);
273 allqueue(REDRAWIMAGE, 0);
276 static uiBlock *text_plugin_scriptsmenu (void *args_unused)
281 short yco = 20, menuwidth = 120;
283 block= uiNewBlock(&curarea->uiblocks, "text_plugin_scriptsmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
284 uiBlockSetButmFunc(block, do_text_plugin_scriptsmenu, NULL);
286 /* note that we acount for the N previous entries with i+20: */
287 for (pym = BPyMenuTable[PYMENU_TEXTPLUGIN]; pym; pym = pym->next, i++) {
289 uiDefIconTextBut(block, BUTM, 1, ICON_PYTHON, pym->name, 0, yco-=20, menuwidth, 19,
290 NULL, 0.0, 0.0, 1, i,
291 pym->tooltip?pym->tooltip:pym->filename);
294 uiBlockSetDirection(block, UI_RIGHT);
295 uiTextBoundsBlock(block, 60);
301 /* action executed after clicking in File menu */
302 static void do_text_filemenu(void *arg, int event)
304 SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */
307 if (st==NULL || st->spacetype != SPACE_TEXT) return;
313 st->text= add_empty_text( "Text" );
316 allqueue(REDRAWTEXT, 0);
317 allqueue(REDRAWHEADERS, 0);
320 activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, add_text_fs);
323 #ifndef DISABLE_PYTHON
324 if (text->compiled) BPY_free_compiled_text(text);
325 text->compiled = NULL;
327 if (okee("Reopen Text")) {
328 if (!reopen_text(text)) {
329 error("Could not reopen file");
331 if (st->showsyntax) txt_format_text(st);
335 text->flags |= TXT_ISMEM;
337 txt_write_file(text);
340 text->flags |= TXT_ISMEM | TXT_ISDIRTY | TXT_ISTMP;
341 MEM_freeN(text->name);
345 run_python_script(st);
348 #ifndef DISABLE_PYTHON
354 /* check all pyconstraints */
355 for (ob= G.main->object.first; ob; ob= ob->id.next) {
357 if (ob->type==OB_ARMATURE && ob->pose) {
359 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
360 for (con = pchan->constraints.first; con; con= con->next) {
361 if (con->type==CONSTRAINT_TYPE_PYTHON) {
362 bPythonConstraint *data = con->data;
363 if (data->text==text) BPY_pyconstraint_update(ob, con);
370 for (con = ob->constraints.first; con; con= con->next) {
371 if (con->type==CONSTRAINT_TYPE_PYTHON) {
372 bPythonConstraint *data = con->data;
373 if (data->text==text) BPY_pyconstraint_update(ob, con);
379 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
392 /* action executed after clicking in Edit menu */
393 static void do_text_editmenu(void *arg, int event)
395 SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */
398 if (st==NULL || st->spacetype != SPACE_TEXT) return;
412 if (text && text->id.lib) {
416 txt_copy_clipboard(text);
421 //txt_copy_sel(text);
422 txt_copy_clipboard(text);
425 if (text && text->id.lib) {
429 txt_paste_clipboard(text);
430 if (st->showsyntax) txt_format_text(st);
433 txt_print_cutbuffer();
436 jumptoline_interactive(st);
440 find_and_replace(st, 0);
443 find_and_replace(st, 1);
452 /* action executed after clicking in View menu */
453 static void do_text_editmenu_viewmenu(void *arg, int event)
455 SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */
458 if (st==NULL || st->spacetype != SPACE_TEXT) return;
464 txt_move_bof(text, 0);
468 txt_move_eof(text, 0);
478 /* action executed after clicking in Select menu */
479 static void do_text_editmenu_selectmenu(void *arg, int event)
481 SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */
484 if (st==NULL || st->spacetype != SPACE_TEXT) return;
502 /* action executed after clicking in Markers menu */
503 static void do_text_editmenu_markermenu(void *arg, int event)
505 SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */
510 if (st==NULL || st->spacetype != SPACE_TEXT) return;
516 txt_clear_markers(text, 0, 0);
519 lineno= txt_get_span(text->lines.first, text->curl);
520 mrk= text->markers.first;
521 while (mrk && (mrk->lineno<lineno || (mrk->lineno==lineno && mrk->start <= text->curc)))
523 if (!mrk) mrk= text->markers.first;
525 txt_move_to(text, mrk->lineno, mrk->start, 0);
526 txt_move_to(text, mrk->lineno, mrk->end, 1);
530 lineno= txt_get_span(text->lines.first, text->curl);
531 mrk= text->markers.last;
532 while (mrk && (mrk->lineno>lineno || (mrk->lineno==lineno && mrk->end > text->curc)))
534 if (!mrk) mrk= text->markers.last;
536 txt_move_to(text, mrk->lineno, mrk->start, 0);
537 txt_move_to(text, mrk->lineno, mrk->end, 1);
547 /* action executed after clicking in Format menu */
548 static void do_text_formatmenu(void *arg, int event)
550 SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */
553 if (st==NULL || st->spacetype != SPACE_TEXT) return;
559 if (text && text->id.lib) {
563 if (txt_has_sel(text)) {
564 txt_order_cursors(text);
569 txt_add_char(text, '\t');
573 if (text && text->id.lib) {
577 if ( txt_has_sel(text)) {
578 txt_order_cursors(text);
584 if (text && text->id.lib) {
588 if ( txt_has_sel(text)) {
589 txt_order_cursors(text);
591 if (st->showsyntax) txt_format_text(st);
596 if (text && text->id.lib) {
600 if ( txt_has_sel(text)) {
601 txt_order_cursors(text);
603 if (st->showsyntax) txt_format_text(st);
615 static uiBlock *text_editmenu_viewmenu(void *arg_unused)
618 short yco = 20, menuwidth = 120;
620 block= uiNewBlock(&curarea->uiblocks, "text_editmenu_viewmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
621 uiBlockSetButmFunc(block, do_text_editmenu_viewmenu, NULL);
623 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Top of File", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
624 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Bottom of File", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
626 uiBlockSetDirection(block, UI_RIGHT);
627 uiTextBoundsBlock(block, 60);
633 static uiBlock *text_editmenu_selectmenu(void *arg_unused)
636 short yco = 20, menuwidth = 120;
638 block= uiNewBlock(&curarea->uiblocks, "text_editmenu_selectmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
639 uiBlockSetButmFunc(block, do_text_editmenu_selectmenu, NULL);
641 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select All|Ctrl A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
642 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Select Line", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
644 uiBlockSetDirection(block, UI_RIGHT);
645 uiTextBoundsBlock(block, 60);
651 static uiBlock *text_editmenu_markermenu(void *arg_unused)
654 short yco = 20, menuwidth = 120;
656 block= uiNewBlock(&curarea->uiblocks, "text_editmenu_markermenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
657 uiBlockSetButmFunc(block, do_text_editmenu_markermenu, NULL);
659 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear All", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
660 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Next Marker", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
661 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Previous Marker", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
663 uiBlockSetDirection(block, UI_RIGHT);
664 uiTextBoundsBlock(block, 60);
669 void do_text_formatmenu_convert(void *arg, int event)
671 SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */
673 if (st==NULL || st->spacetype != SPACE_TEXT) return;
676 case 1: convert_tabs(st, 0); break;
677 case 2: convert_tabs(st, 1); break;
679 allqueue(REDRAWVIEW3D, 0);
682 static uiBlock *text_formatmenu_convert(void *arg_unused)
685 short yco = 20, menuwidth = 120;
687 block= uiNewBlock(&curarea->uiblocks, "do_text_formatmenu_convert", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
688 uiBlockSetButmFunc(block, do_text_formatmenu_convert, NULL);
690 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:");
691 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:");
693 uiBlockSetDirection(block, UI_RIGHT);
694 uiTextBoundsBlock(block, 60);
699 static uiBlock *text_formatmenu(void *arg_unused)
702 short yco= 0, menuwidth=120;
704 block= uiNewBlock(&curarea->uiblocks, "text_formatmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
705 uiBlockSetButmFunc(block, do_text_formatmenu, NULL);
707 uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
708 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Indent|Tab", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
709 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Unindent|Shift Tab", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
710 uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
711 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Comment", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
712 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Uncomment|Ctrl Shift D", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");
713 uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
714 uiDefIconTextBlockBut(block, text_formatmenu_convert, NULL, ICON_RIGHTARROW_THIN, "Convert whitespace", 0, yco-=20, menuwidth, 19, "");
716 if(curarea->headertype==HEADERTOP) {
717 uiBlockSetDirection(block, UI_DOWN);
720 uiBlockSetDirection(block, UI_TOP);
721 uiBlockFlipOrder(block);
724 uiTextBoundsBlock(block, 50);
729 /* action executed after clicking in Object to 3d Sub Menu */
730 void do_text_editmenu_to3dmenu(void *arg, int event)
732 SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */
734 if (st==NULL || st->spacetype != SPACE_TEXT) return;
739 case 1: txt_export_to_object(text); break;
740 case 2: txt_export_to_objects(text); break;
742 allqueue(REDRAWVIEW3D, 0);
745 /* Object to 3d Sub Menu */
746 static uiBlock *text_editmenu_to3dmenu(void *arg_unused)
749 short yco = 20, menuwidth = 120;
751 block= uiNewBlock(&curarea->uiblocks, "do_text_editmenu_to3dmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
752 uiBlockSetButmFunc(block, do_text_editmenu_to3dmenu, NULL);
754 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "One Object | Alt-M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
755 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "One Object Per Line", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
757 uiBlockSetDirection(block, UI_RIGHT);
758 uiTextBoundsBlock(block, 60);
764 static uiBlock *text_editmenu(void *arg_unused)
767 short yco= 0, menuwidth=120;
769 block= uiNewBlock(&curarea->uiblocks, "text_editmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
770 uiBlockSetButmFunc(block, do_text_editmenu, NULL);
772 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Undo|Ctrl Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
773 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Redo|Ctrl Shift Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
774 uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
775 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Cut|Alt X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
776 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Copy|Alt C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
777 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Paste|Alt V", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
778 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Print Cut Buffer", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");
779 uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
780 uiDefIconTextBlockBut(block, text_editmenu_viewmenu, NULL, ICON_RIGHTARROW_THIN, "View|Alt Shift V ", 0, yco-=20, 120, 19, "");
781 uiDefIconTextBlockBut(block, text_editmenu_selectmenu, NULL, ICON_RIGHTARROW_THIN, "Select|Alt Shift S ", 0, yco-=20, 120, 19, "");
782 uiDefIconTextBlockBut(block, text_editmenu_markermenu, NULL, ICON_RIGHTARROW_THIN, "Markers", 0, yco-=20, 120, 19, "");
783 uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
784 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Jump...|Alt J", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, "");
785 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find And Replace...|Alt F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, "");
786 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find Next|Alt F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, "");
787 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Replace|Alt H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 10, "");
788 uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
789 uiDefIconTextBlockBut(block, text_editmenu_to3dmenu, NULL, ICON_RIGHTARROW_THIN, "Text to 3d Object", 0, yco-=20, 120, 19, "");
791 if(curarea->headertype==HEADERTOP) {
792 uiBlockSetDirection(block, UI_DOWN);
795 uiBlockSetDirection(block, UI_TOP);
796 uiBlockFlipOrder(block);
799 uiTextBoundsBlock(block, 50);
804 static uiBlock *text_filemenu(void *arg_unused)
806 SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */
807 Text *text= st->text;
809 short yco= 0, menuwidth=120;
811 block= uiNewBlock(&curarea->uiblocks, "text_filemenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
812 uiBlockSetButmFunc(block, do_text_filemenu, NULL);
814 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "New|Alt N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
815 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Open...|Alt O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
818 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reopen|Alt R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
820 uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
822 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save|Alt S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
823 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save As...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
826 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Internal", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");
828 uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
830 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Run Python Script|Alt P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, "");
831 #ifndef DISABLE_PYTHON
832 if (BPY_is_pyconstraint(text))
833 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Refresh All PyConstraints", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, "");
835 uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
838 #ifndef DISABLE_PYTHON
839 uiDefIconTextBlockBut(block, text_template_scriptsmenu, NULL, ICON_RIGHTARROW_THIN, "Script Templates", 0, yco-=20, 120, 19, "");
840 uiDefIconTextBlockBut(block, text_plugin_scriptsmenu, NULL, ICON_RIGHTARROW_THIN, "Text Plugins", 0, yco-=20, 120, 19, "");
843 if(curarea->headertype==HEADERTOP) {
844 uiBlockSetDirection(block, UI_DOWN);
847 uiBlockSetDirection(block, UI_TOP);
848 uiBlockFlipOrder(block);
851 uiTextBoundsBlock(block, 50);
856 /* text sync functions */
858 /* returns 0 if file on disk is the same or Text is in memory only
859 returns 1 if file has been modified on disk since last local edit
860 returns 2 if file on disk has been deleted
861 -1 is returned if an error occurs
863 static int txt_file_modified(Text *text)
867 char file[FILE_MAXDIR+FILE_MAXFILE];
869 if (!text || !text->name)
872 BLI_strncpy(file, text->name, FILE_MAXDIR+FILE_MAXFILE);
873 BLI_convertstringcode(file, G.sce);
875 if (!BLI_exists(file))
878 result = stat(file, &st);
883 if((st.st_mode & S_IFMT) != S_IFREG)
886 if (st.st_mtime > text->mtime)
892 static void txt_ignore_modified(Text *text) {
895 char file[FILE_MAXDIR+FILE_MAXFILE];
897 if (!text || !text->name) return;
899 BLI_strncpy(file, text->name, FILE_MAXDIR+FILE_MAXFILE);
900 BLI_convertstringcode(file, G.sce);
902 if (!BLI_exists(file)) return;
904 result = stat(file, &st);
906 if(result == -1 || (st.st_mode & S_IFMT) != S_IFREG)
909 text->mtime= st.st_mtime;
912 static short do_modification_check(SpaceText *st_v) {
913 SpaceText *st = (SpaceText *)st_v;
914 Text *text= st->text;
916 switch (txt_file_modified(text)) {
918 /* Modified locally and externally, ahhh. Offer more possibilites. */
919 if (text->flags & TXT_ISDIRTY) {
920 switch (pupmenu("File Modified Outside and Inside Blender %t|Load outside changes (ignore local changes) %x0|Save local changes (ignore outside changes) %x1|Make text internal (separate copy) %x2")) {
923 if (st->showsyntax) txt_format_text(st);
926 txt_write_file(text);
929 text->flags |= TXT_ISMEM | TXT_ISDIRTY | TXT_ISTMP;
930 MEM_freeN(text->name);
935 switch (pupmenu("File Modified Outside Blender %t|Reload from disk %x0|Make text internal (separate copy) %x1|Ignore %x2")) {
937 #ifndef DISABLE_PYTHON
938 if (text->compiled) BPY_free_compiled_text(text);
939 text->compiled = NULL;
942 if (st->showsyntax) txt_format_text(st);
945 text->flags |= TXT_ISMEM | TXT_ISDIRTY | TXT_ISTMP;
946 MEM_freeN(text->name);
950 txt_ignore_modified(text);
956 switch (pupmenu("File Deleted Outside Blender %t|Make text internal %x0|Recreate file %x1")) {
958 text->flags |= TXT_ISMEM | TXT_ISDIRTY | TXT_ISTMP;
959 MEM_freeN(text->name);
963 txt_write_file(text);
973 static void do_modification_func(void *st_v, void *dummy)
975 if (do_modification_check((SpaceText *)st_v))
980 #define HEADER_PATH_MAX 260
981 void text_buttons(void)
984 SpaceText *st= curarea->spacedata.first;
987 char naam[256], fname[HEADER_PATH_MAX], headtxt[HEADER_PATH_MAX+17];
990 if (st==NULL || st->spacetype != SPACE_TEXT) return;
994 sprintf(naam, "header %d", curarea->headwin);
995 block= uiNewBlock(&curarea->uiblocks, naam, UI_EMBOSS, UI_HELV, curarea->headwin);
997 if(area_is_active_area(curarea)) uiBlockSetCol(block, TH_HEADER);
998 else uiBlockSetCol(block, TH_HEADERDESEL);
1000 curarea->butspacetype= SPACE_TEXT;
1003 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.");
1006 uiBlockSetEmboss(block, UI_EMBOSSN);
1007 if(curarea->flag & HEADER_NO_PULLDOWN) {
1008 uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, B_FLIPINFOMENU, ICON_DISCLOSURE_TRI_RIGHT,
1010 &(curarea->flag), 0, 0, 0, 0, "Enables display of pulldown menus");
1012 uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, B_FLIPINFOMENU, ICON_DISCLOSURE_TRI_DOWN,
1014 &(curarea->flag), 0, 0, 0, 0, "Hides pulldown menus");
1016 uiBlockSetEmboss(block, UI_EMBOSS);
1019 /* pull down menus */
1020 if((curarea->flag & HEADER_NO_PULLDOWN)==0) {
1021 uiBlockSetEmboss(block, UI_EMBOSSP);
1023 xmax= GetButStringLength("Text");
1024 uiDefPulldownBut(block,text_filemenu, NULL, "Text", xco, 0, xmax, 20, "");
1028 xmax= GetButStringLength("Edit");
1029 uiDefPulldownBut(block,text_editmenu, NULL, "Edit", xco, 0, xmax, 20, "");
1032 xmax= GetButStringLength("Format");
1033 uiDefPulldownBut(block,text_formatmenu, NULL, "Format", xco, 0, xmax, 20, "");
1037 uiBlockSetEmboss(block, UI_EMBOSS);
1041 uiBlockBeginAlign(block);
1042 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)");
1043 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)");
1045 uiDefIconButI(block, ICONTOG, B_TEXTLINENUM, ICON_LONGDISPLAY, xco+=XIC,0,XIC,YIC, &st->showlinenrs, 0, 0, 0, 0, "Displays line numbers");
1046 uiDefIconButI(block, ICONTOG, B_WORDWRAP, ICON_WORDWRAP, xco+=XIC,0,XIC,YIC, &st->wordwrap, 0, 0, 0, 0, "Enables word wrap");
1047 uiDefIconButI(block, ICONTOG, B_SYNTAX, ICON_SYNTAX, xco+=XIC,0,XIC,YIC, &st->showsyntax, 0, 0, 0, 0, "Enables syntax highlighting");
1048 uiDefIconButI(block, ICONTOG, B_TEXTPLUGINS, ICON_PYTHON, xco+=XIC,0,XIC,YIC, &st->doplugins, 0, 0, 0, 0, "Enables Python text plugins");
1049 uiBlockEndAlign(block);
1051 /* Warning button if text is out of date*/
1052 if (text && txt_file_modified(text)) {
1055 uiBlockSetCol(block, TH_REDALERT);
1056 bt= uiDefIconBut(block, BUT, B_NOP, ICON_HELP, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "External text is out of sync, click for options to resolve the conflict");
1057 uiButSetFunc(bt, do_modification_func, (void *)st, NULL);
1058 uiBlockSetCol(block, TH_AUTO);
1061 /* STD TEXT BUTTONS */
1063 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);
1068 if (st->text->flags & TXT_ISDIRTY && (st->text->flags & TXT_ISEXT || !(st->text->flags & TXT_ISMEM)))
1069 uiDefIconBut(block, BUT,0, ICON_ERROR, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "The text has been changed");
1070 if (st->text->flags & TXT_ISEXT)
1071 uiDefBut(block, BUT,B_TEXTSTORE, ICON(), xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Stores text in project file");
1073 uiDefBut(block, BUT,B_TEXTSTORE, ICON(), xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Disables storing of text in project file");
1079 if(st->font_id>1) st->font_id= 0;
1080 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");
1083 uiDefButI(block, NUM, B_TAB_NUMBERS, "Tab:", xco, 0, XIC+50, YIC, &st->tabnumber, 2, 8, 0, 0, "Set spacing of Tab");
1089 len = strlen(text->name);
1090 if (len > HEADER_PATH_MAX-1)
1091 len = HEADER_PATH_MAX-1;
1092 strncpy(fname, text->name, len);
1094 if (text->flags & TXT_ISDIRTY)
1095 sprintf(headtxt, "File: *%s (unsaved)", fname);
1097 sprintf(headtxt, "File: %s", fname);
1099 sprintf(headtxt, text->id.lib?"Text: External":"Text: Internal");
1101 BIF_ThemeColor(TH_MENU_TEXT);
1102 glRasterPos2i(xco+=XIC, 5);
1103 BMF_DrawString(G.font, headtxt);
1104 xco += BMF_GetStringWidth(G.font, headtxt);
1107 /* always as last */
1108 curarea->headbutlen= xco+2*XIC;