2.5: Text Editor back.
[blender.git] / source / blender / editors / space_text / text_header.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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2008 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdio.h>
32
33 /* file time checking */
34 #include <ctype.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37
38 #ifndef _WIN32
39 #include <unistd.h>
40 #else
41 #include <io.h>
42 #include "BLI_winstuff.h"
43 #endif
44
45 #include "DNA_space_types.h"
46 #include "DNA_scene_types.h"
47 #include "DNA_screen_types.h"
48 #include "DNA_text_types.h"
49 #include "DNA_windowmanager_types.h"
50
51 #include "MEM_guardedalloc.h"
52
53 #include "BLI_blenlib.h"
54
55 #include "BKE_context.h"
56 #include "BKE_global.h"
57 #include "BKE_library.h"
58 #include "BKE_main.h"
59 #include "BKE_screen.h"
60 #include "BKE_text.h"
61
62 #include "ED_screen.h"
63 #include "ED_types.h"
64 #include "ED_util.h"
65
66 #include "WM_api.h"
67 #include "WM_types.h"
68
69 #include "BIF_gl.h"
70 #include "BIF_glutil.h"
71
72 #include "UI_interface.h"
73 #include "UI_resources.h"
74 #include "UI_text.h"
75 #include "UI_view2d.h"
76
77 #include "RNA_access.h"
78
79 #ifndef DISABLE_PYTHON
80 #include "BPY_extern.h"
81 // XXX #include "BPY_menus.h"
82 #endif
83
84 #include "text_intern.h"
85
86 #define HEADER_PATH_MAX 260
87
88 /* ************************ header area region *********************** */
89
90 #ifndef DISABLE_PYTHON
91 static void do_text_template_scriptsmenu(bContext *C, void *arg, int event)
92 {
93         // XXX BPY_menu_do_python(PYMENU_SCRIPTTEMPLATE, event);
94 }
95
96 uiBlock *text_template_scriptsmenu(bContext *C, void *args_unused)
97 {
98         ARegion *ar= CTX_wm_region(C);
99         uiBlock *block;
100         // XXX BPyMenu *pym;
101         // int i= 0;
102         // short yco = 20, menuwidth = 120;
103         
104         block= uiBeginBlock(C, ar, "text_template_scriptsmenu", UI_EMBOSSP, UI_HELV);
105         uiBlockSetButmFunc(block, do_text_template_scriptsmenu, NULL);
106         
107         /* note that we acount for the N previous entries with i+20: */
108         /* XXX for (pym = BPyMenuTable[PYMENU_SCRIPTTEMPLATE]; pym; pym = pym->next, i++) {
109                 
110                 uiDefIconTextBut(block, BUTM, 1, ICON_PYTHON, pym->name, 0, yco-=20, menuwidth, 19, 
111                                                  NULL, 0.0, 0.0, 1, i, 
112                                                  pym->tooltip?pym->tooltip:pym->filename);
113         }*/
114         
115         uiBlockSetDirection(block, UI_RIGHT);
116         uiTextBoundsBlock(block, 60);
117
118         uiEndBlock(C, block);
119         uiDrawBlock(C, block);
120         
121         return block;
122 }
123
124 static void do_text_plugin_scriptsmenu(bContext *C, void *arg, int event)
125 {
126         // XXX BPY_menu_do_python(PYMENU_TEXTPLUGIN, event);
127 }
128
129 uiBlock *text_plugin_scriptsmenu(bContext *C, void *args_unused)
130 {
131         ARegion *ar= CTX_wm_region(C);
132         uiBlock *block;
133         // XXX BPyMenu *pym;
134         // int i= 0;
135         // short yco = 20, menuwidth = 120;
136         
137         block= uiBeginBlock(C, ar, "text_plugin_scriptsmenu", UI_EMBOSSP, UI_HELV);
138         uiBlockSetButmFunc(block, do_text_plugin_scriptsmenu, NULL);
139         
140         /* note that we acount for the N previous entries with i+20: */
141         /* XXX for (pym = BPyMenuTable[PYMENU_TEXTPLUGIN]; pym; pym = pym->next, i++) {
142                 
143                 uiDefIconTextBut(block, BUTM, 1, ICON_PYTHON, pym->name, 0, yco-=20, menuwidth, 19, 
144                                                  NULL, 0.0, 0.0, 1, i, 
145                                                  pym->tooltip?pym->tooltip:pym->filename);
146         }*/
147         
148         uiBlockSetDirection(block, UI_RIGHT);
149         uiTextBoundsBlock(block, 60);
150
151         uiEndBlock(C, block);
152         uiDrawBlock(C, block);
153
154         return block;
155 }
156 #endif
157
158 static void text_editmenu_viewmenu(bContext *C, uiMenuItem *head, void *arg_unused)
159 {
160         uiMenuItemEnumO(head, "Top of File", 0, "TEXT_OT_move", "type", FILE_TOP);
161         uiMenuItemEnumO(head, "Bottom of File", 0, "TEXT_OT_move", "type", FILE_BOTTOM);
162 }
163
164 static void text_editmenu_selectmenu(bContext *C, uiMenuItem *head, void *arg_unused)
165 {
166         uiMenuItemO(head, 0, "TEXT_OT_select_all");
167         uiMenuItemO(head, 0, "TEXT_OT_select_line");
168 }
169
170 static void text_editmenu_markermenu(bContext *C, uiMenuItem *head, void *arg_unused)
171 {
172         uiMenuItemO(head, 0, "TEXT_OT_clear_all_markers");
173         uiMenuItemO(head, 0, "TEXT_OT_next_marker");
174         uiMenuItemO(head, 0, "TEXT_OT_previous_marker");
175 }
176
177 static void text_formatmenu(bContext *C, uiMenuItem *head, void *arg_unused)
178 {
179         uiMenuItemO(head, 0, "TEXT_OT_indent");
180         uiMenuItemO(head, 0, "TEXT_OT_unindent");
181
182         uiMenuSeparator(head);
183
184         uiMenuItemO(head, 0, "TEXT_OT_comment");
185         uiMenuItemO(head, 0, "TEXT_OT_uncomment");
186
187         uiMenuSeparator(head);
188
189         uiMenuLevelEnumO(head, "TEXT_OT_convert_whitespace", "type");
190 }
191
192 static void text_editmenu_to3dmenu(bContext *C, uiMenuItem *head, void *arg_unused)
193 {
194         uiMenuItemBooleanO(head, "One Object", 0, "TEXT_OT_to_3d_object", "split_lines", 0);
195         uiMenuItemBooleanO(head, "One Object Per Line", 0, "TEXT_OT_to_3d_object", "split_lines", 1);
196 }
197
198 static void text_editmenu(bContext *C, uiMenuItem *head, void *arg_unused)
199 {
200         uiMenuItemO(head, 0, "ED_OT_undo");
201         uiMenuItemO(head, 0, "ED_OT_redo");
202
203         uiMenuSeparator(head);
204
205         uiMenuItemO(head, 0, "TEXT_OT_cut");
206         uiMenuItemO(head, 0, "TEXT_OT_copy");
207         uiMenuItemO(head, 0, "TEXT_OT_paste");
208
209         uiMenuSeparator(head);
210
211         uiMenuLevel(head, "View", text_editmenu_viewmenu);
212         uiMenuLevel(head, "Select", text_editmenu_selectmenu);
213         uiMenuLevel(head, "Markers", text_editmenu_markermenu);
214
215         uiMenuSeparator(head);
216
217         uiMenuItemO(head, 0, "TEXT_OT_jump");
218         uiMenuItemO(head, 0, "TEXT_OT_find_and_replace");
219
220         uiMenuSeparator(head);
221
222         uiMenuLevel(head, "Text to 3D Object", text_editmenu_to3dmenu);
223 }
224
225 static void text_filemenu(bContext *C, uiMenuItem *head, void *arg_unused)
226 {
227         SpaceText *st= (SpaceText*)CTX_wm_space_data(C);
228         Text *text= st->text;
229
230         uiMenuItemO(head, 0, "TEXT_OT_new");
231         uiMenuItemO(head, 0, "TEXT_OT_open");
232         
233         if(text) {
234                 uiMenuItemO(head, 0, "TEXT_OT_reload");
235                 
236                 uiMenuSeparator(head);
237                 
238                 uiMenuItemO(head, 0, "TEXT_OT_save");
239                 uiMenuItemO(head, 0, "TEXT_OT_save_as");
240                 
241                 if(text->name)
242                         uiMenuItemO(head, 0, "TEXT_OT_make_internal");
243
244                 uiMenuSeparator(head);
245                 
246                 uiMenuItemO(head, 0, "TEXT_OT_run_script");
247
248 #ifndef DISABLE_PYTHON
249                 if(BPY_is_pyconstraint(text))
250                         uiMenuItemO(head, 0, "TEXT_OT_refresh_pyconstraints");
251 #endif
252         }
253
254 #ifndef DISABLE_PYTHON
255         // XXX uiMenuSeparator(head);
256
257         // XXX uiDefIconTextBlockBut(block, text_template_scriptsmenu, NULL, ICON_RIGHTARROW_THIN, "Script Templates", 0, yco-=20, 120, 19, "");
258         // XXX uiDefIconTextBlockBut(block, text_plugin_scriptsmenu, NULL, ICON_RIGHTARROW_THIN, "Text Plugins", 0, yco-=20, 120, 19, "");
259 #endif
260 }
261
262 /*********************** datablock browse *************************/
263
264 static void text_unlink(Main *bmain, Text *text)
265 {
266         bScreen *scr;
267         ScrArea *area;
268         SpaceLink *sl;
269
270         /* XXX this ifdef is in fact dangerous, if python is
271          * disabled it will leave invalid pointers in files! */
272
273 #ifndef DISABLE_PYTHON
274         // XXX BPY_clear_bad_scriptlinks(text);
275         // XXX BPY_free_pyconstraint_links(text);
276         // XXX free_text_controllers(text);
277
278         /* check if this text was used as script link:
279          * this check function unsets the pointers and returns how many
280          * script links used this Text */
281         if(0) // XXX BPY_text_check_all_scriptlinks (text))
282                 ; // XXX notifier: allqueue(REDRAWBUTSSCRIPT, 0);
283
284         /* equivalently for pynodes: */
285         if(0) // XXX nodeDynamicUnlinkText ((ID*)text))
286                 ; // XXX notifier: allqueue(REDRAWNODE, 0);
287 #endif
288         
289         for(scr= bmain->screen.first; scr; scr= scr->id.next) {
290                 for(area= scr->areabase.first; area; area= area->next) {
291                         for(sl= area->spacedata.first; sl; sl= sl->next) {
292                                 if(sl->spacetype==SPACE_TEXT) {
293                                         SpaceText *st= (SpaceText*) sl;
294                                         
295                                         if(st->text==text) {
296                                                 st->text= NULL;
297                                                 st->top= 0;
298                                                 
299                                                 if(st==area->spacedata.first)
300                                                         ED_area_tag_redraw(area);
301                                         }
302                                 }
303                         }
304                 }
305         }
306
307         free_libblock(&bmain->text, text);
308 }
309
310 static void text_idpoin_handle(bContext *C, ID *id, int event)
311 {
312         SpaceText *st= (SpaceText*)CTX_wm_space_data(C);
313         Text *text;
314
315         switch(event) {
316                 case UI_ID_BROWSE:
317                         st->text= (Text*)id;
318                         st->top= 0;
319
320                         text_update_edited(st->text);
321                         WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, st->text);
322
323                         ED_undo_push(C, "Browse Text");
324                         break;
325                 case UI_ID_DELETE:
326                         text= st->text;
327
328                         /* make the previous text active, if its not there make the next text active */
329                         if(text->id.prev) {
330                                 st->text = text->id.prev;
331                                 WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, st->text);
332                         }
333                         else if(text->id.next) {
334                                 st->text = text->id.next;
335                                 WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, st->text);
336                         }
337
338                         text_unlink(CTX_data_main(C), text);
339                         WM_event_add_notifier(C, NC_TEXT|NA_REMOVED, text);
340
341                         ED_undo_push(C, "Delete Text");
342                         break;
343                 case UI_ID_RENAME:
344                         break;
345                 case UI_ID_ADD_NEW:
346                         WM_operator_name_call(C, "TEXT_OT_new", WM_OP_INVOKE_REGION_WIN, NULL);
347                         break;
348                 case UI_ID_OPEN:
349                         WM_operator_name_call(C, "TEXT_OT_open", WM_OP_INVOKE_REGION_WIN, NULL);
350                         break;
351         }
352 }
353
354 /********************** header buttons ***********************/
355
356 void text_header_buttons(const bContext *C, ARegion *ar)
357 {
358         bScreen *sc= CTX_wm_screen(C);
359         SpaceText *st= (SpaceText*)CTX_wm_space_data(C);
360         PointerRNA spaceptr;
361         Text *text= st->text;
362         ScrArea *sa= CTX_wm_area(C);
363         uiBlock *block;
364         int xco, yco= 3, xmax, oldcol;
365         
366         RNA_pointer_create(&sc->id, &RNA_SpaceTextEditor, st, &spaceptr);
367
368         block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS, UI_HELV);
369         
370         xco= ED_area_header_standardbuttons(C, block, yco);
371         
372         if((sa->flag & HEADER_NO_PULLDOWN)==0) {
373                 /* pull down menus */
374                 uiBlockSetEmboss(block, UI_EMBOSSP);
375                 
376                 xmax= GetButStringLength("Text");
377                 uiDefMenuBut(block, text_filemenu, NULL, "Text", xco, yco-2, xmax-3, 24, "");
378                 xco+=xmax;
379         
380                 if(text) {
381                         xmax= GetButStringLength("Edit");
382                         uiDefMenuBut(block, text_editmenu, NULL, "Edit", xco, yco-2, xmax-3, 24, "");
383                         xco+=xmax;
384                         
385                         xmax= GetButStringLength("Format");
386                         uiDefMenuBut(block, text_formatmenu, NULL, "Format", xco, yco-2, xmax-3, 24, "");
387                         xco+=xmax;
388                 }
389         }
390         
391         uiBlockSetEmboss(block, UI_EMBOSS);
392
393         uiBlockBeginAlign(block);
394         uiDefIconButR(block, ICONTOG, 0, ICON_LINENUMBERS_OFF, xco, yco,XIC,YIC, &spaceptr, "line_numbers", 0, 0, 0, 0, 0, NULL);
395         uiDefIconButR(block, ICONTOG, 0, ICON_WORDWRAP_OFF, xco+=XIC, yco,XIC,YIC, &spaceptr, "word_wrap", 0, 0, 0, 0, 0, NULL);
396         uiDefIconButR(block, ICONTOG, 0, ICON_SYNTAX_OFF, xco+=XIC, yco,XIC,YIC, &spaceptr, "syntax_highlight", 0, 0, 0, 0, 0, NULL);
397         // uiDefIconButR(block, ICONTOG, 0, ICON_SCRIPTPLUGINS, xco+=XIC, yco,XIC,YIC, &spaceptr, "do_python_plugins", 0, 0, 0, 0, 0, "Enables Python text plugins");
398         uiBlockEndAlign(block);
399         
400         /* warning button if text is out of date */
401         if(text && text_file_modified(text)) {
402                 xco+= XIC;
403
404                 oldcol= uiBlockGetCol(block);
405                 uiBlockSetCol(block, TH_REDALERT);
406                 uiDefIconButO(block, BUT, "TEXT_OT_resolve_conflict", WM_OP_INVOKE_DEFAULT, ICON_HELP,  xco+=XIC,yco,XIC,YIC, "External text is out of sync, click for options to resolve the conflict");
407                 uiBlockSetCol(block, oldcol);
408         }
409         
410         /* browse text datablock */
411         xco+= 2*XIC;
412         xco= uiDefIDPoinButs(block, CTX_data_main(C), NULL, (ID*)st->text, ID_TXT, NULL, xco, yco,
413                 text_idpoin_handle, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_OPEN|UI_ID_DELETE);
414         xco+=XIC;
415         
416         /*
417         if(st->text) {
418                 if(st->text->flags & TXT_ISDIRTY && (st->text->flags & TXT_ISEXT || !(st->text->flags & TXT_ISMEM)))
419                         uiDefIconBut(block, BUT,0, ICON_ERROR, xco+=XIC,yco,XIC,YIC, 0, 0, 0, 0, 0, "The text has been changed");
420                 if(st->text->flags & TXT_ISEXT) 
421                         uiDefBut(block, BUT,B_TEXTSTORE, ICON(),        xco+=XIC,yco,XIC,YIC, 0, 0, 0, 0, 0, "Stores text in project file");
422                 else 
423                         uiDefBut(block, BUT,B_TEXTSTORE, ICON(),        xco+=XIC,yco,XIC,YIC, 0, 0, 0, 0, 0, "Disables storing of text in project file");
424                 xco+=10;
425         }
426         */              
427         
428         /* display settings */
429         if(st->font_id>1) st->font_id= 0;
430         uiDefButR(block, MENU, 0, NULL, xco,yco,100,YIC, &spaceptr, "font_size", 0, 0, 0, 0, 0, NULL);
431         xco+=105;
432         
433         uiDefButR(block, NUM, 0, "Tab:", xco,yco,XIC+50,YIC, &spaceptr, "tab_width", 0, 0, 0, 0, 0, NULL);
434         xco+= XIC+50;
435
436         /* file info */
437         if(text) {
438                 char fname[HEADER_PATH_MAX], headtxt[HEADER_PATH_MAX+17];
439                 int len;
440
441                 if(text->name) {
442                         len = strlen(text->name);
443                         if(len > HEADER_PATH_MAX-1)
444                                 len = HEADER_PATH_MAX-1;
445                         strncpy(fname, text->name, len);
446                         fname[len]='\0';
447                         if(text->flags & TXT_ISDIRTY)
448                                 sprintf(headtxt, "File: *%s (unsaved)", fname);
449                         else
450                                 sprintf(headtxt, "File: %s", fname);
451                 }
452                 else
453                         sprintf(headtxt, text->id.lib? "Text: External": "Text: Internal");
454
455                 UI_ThemeColor(TH_MENU_TEXT);
456                 UI_RasterPos(xco+=XIC, yco+6);
457
458                 UI_DrawString(G.font, headtxt, 0);
459                 xco += UI_GetStringWidth(G.font, headtxt, 0);
460         }
461
462         uiEndBlock(C, block);
463         uiDrawBlock(C, block);
464
465         /* always as last  */
466         UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
467 }
468
469 /************************* find & replace ***************************/
470
471 void text_find_buttons(const bContext *C, ARegion *ar)
472 {
473         bScreen *sc= CTX_wm_screen(C);
474         SpaceText *st= CTX_wm_space_text(C);
475         PointerRNA spaceptr;
476         uiBlock *block;
477         int xco= 5, yco= 3;
478         
479         RNA_pointer_create(&sc->id, &RNA_SpaceTextEditor, st, &spaceptr);
480
481         block= uiBeginBlock(C, ar, "find buttons", UI_EMBOSS, UI_HELV);
482
483         /* find */
484         uiBlockBeginAlign(block);
485         uiDefButR(block, TEX, 0, "Find: ", xco, yco,220,20, &spaceptr, "find_text", 0, 0, 0, 0, 0, NULL);
486         xco += 220;
487         uiDefIconButO(block, BUT, "TEXT_OT_find_set_selected", WM_OP_INVOKE_DEFAULT, ICON_TEXT, xco,yco,20,20, "Copy from selection");
488         xco += 20+XIC;
489         uiBlockEndAlign(block);
490
491         /* replace */
492         uiBlockBeginAlign(block);
493         uiDefButR(block, TEX, 0, "Replace: ", xco, yco,220,20, &spaceptr, "replace_text", 0, 0, 0, 0, 0, NULL);
494         xco += 220;
495         uiDefIconButO(block, BUT, "TEXT_OT_replace_set_selected", WM_OP_INVOKE_DEFAULT, ICON_TEXT, xco,yco,20,20, "Copy from selection");
496         xco += 20+XIC;
497         uiBlockEndAlign(block);
498
499         uiBlockBeginAlign(block);
500         uiDefButR(block, TOG, 0, "Wrap", xco, yco,60,20, &spaceptr, "find_wrap", 0, 0, 0, 0, 0, NULL);
501         xco += 60;
502         uiDefButR(block, TOG, 0, "All", xco, yco,60,20, &spaceptr, "find_all", 0, 0, 0, 0, 0, NULL);
503         xco += 50+XIC;
504         uiBlockEndAlign(block);
505
506         uiBlockBeginAlign(block);
507         uiDefButO(block, BUT, "TEXT_OT_find", WM_OP_INVOKE_REGION_WIN, "Find", xco,yco,50,20, "Find next.");
508         xco += 50;
509         uiDefButO(block, BUT, "TEXT_OT_replace", WM_OP_INVOKE_REGION_WIN, "Replace", xco,yco,70,20, "Replace then find next.");
510         xco += 70;
511         uiDefButO(block, BUT, "TEXT_OT_mark_all", WM_OP_INVOKE_REGION_WIN, "Mark All", xco,yco,80,20, "Mark each occurrence to edit all from one");
512         xco += 80;
513         uiBlockEndAlign(block);
514         
515         uiEndBlock(C, block);
516         uiDrawBlock(C, block);
517
518         /* always as last  */
519         UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
520 }
521
522 ARegion *text_has_find_region(ScrArea *sa)
523 {
524         ARegion *ar, *arnew;
525         
526         for(ar= sa->regionbase.first; ar; ar= ar->next)
527                 if(ar->regiontype==RGN_TYPE_UI)
528                         return ar;
529         
530         /* add subdiv level; after header */
531         for(ar= sa->regionbase.first; ar; ar= ar->next)
532                 if(ar->regiontype==RGN_TYPE_HEADER)
533                         break;
534         
535         /* is error! */
536         if(ar==NULL) return NULL;
537         
538         arnew= MEM_callocN(sizeof(ARegion), "find and replace region");
539         
540         BLI_insertlinkafter(&sa->regionbase, ar, arnew);
541         arnew->regiontype= RGN_TYPE_UI;
542         arnew->alignment= RGN_ALIGN_BOTTOM;
543         
544         arnew->flag = RGN_FLAG_HIDDEN;
545         
546         return arnew;
547 }
548
549 static int find_and_replace_poll(bContext *C)
550 {
551         SpaceText *st= CTX_wm_space_text(C);
552         Text *text= CTX_data_edit_text(C);
553
554         return (st && text);
555 }
556
557 static int find_and_replace_exec(bContext *C, wmOperator *op)
558 {
559         ScrArea *sa= CTX_wm_area(C);
560         ARegion *ar= text_has_find_region(sa);
561         
562         if(ar) {
563                 ar->flag ^= RGN_FLAG_HIDDEN;
564                 ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */
565                 
566                 ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
567                 ED_area_tag_redraw(sa);
568         }
569
570         return OPERATOR_FINISHED;
571 }
572
573 void TEXT_OT_find_and_replace(wmOperatorType *ot)
574 {
575         /* identifiers */
576         ot->name= "Find and Replace";
577         ot->idname= "TEXT_OT_find_and_replace";
578         
579         /* api callbacks */
580         ot->exec= find_and_replace_exec;
581         ot->poll= find_and_replace_poll;
582 }
583
584 /******************** XXX popup menus *******************/
585
586 #if 0
587 {
588         // RMB
589
590         uiMenuItem *head;
591
592         if(text) {
593                 head= uiPupMenuBegin("Text", 0);
594                 if(txt_has_sel(text)) {
595                         uiMenuItemO(head, 0, "TEXT_OT_cut");
596                         uiMenuItemO(head, 0, "TEXT_OT_copy");
597                 }
598                 uiMenuItemO(head, 0, "TEXT_OT_paste");
599                 uiMenuItemO(head, 0, "TEXT_OT_new");
600                 uiMenuItemO(head, 0, "TEXT_OT_open");
601                 uiMenuItemO(head, 0, "TEXT_OT_save");
602                 uiMenuItemO(head, 0, "TEXT_OT_save_as");
603                 uiMenuItemO(head, 0, "TEXT_OT_run_script");
604                 uiPupMenuEnd(C, head);
605         }
606         else {
607                 head= uiPupMenuBegin("File", 0);
608                 uiMenuItemO(head, 0, "TEXT_OT_new");
609                 uiMenuItemO(head, 0, "TEXT_OT_open");
610                 uiPupMenuEnd(C, head);
611         }
612 }
613
614 {
615         // Alt+Shift+E
616
617         uiMenuItem *head;
618
619         head= uiPupMenuBegin("Edit", 0);
620         uiMenuItemO(head, 0, "TEXT_OT_cut");
621         uiMenuItemO(head, 0, "TEXT_OT_copy");
622         uiMenuItemO(head, 0, "TEXT_OT_paste");
623         uiPupMenuEnd(C, head);
624 }
625
626 {
627         // Alt+Shift+F
628
629         uiMenuItem *head;
630
631         if(text) {
632                 head= uiPupMenuBegin("Text", 0);
633                 uiMenuItemO(head, 0, "TEXT_OT_new");
634                 uiMenuItemO(head, 0, "TEXT_OT_open");
635                 uiMenuItemO(head, 0, "TEXT_OT_save");
636                 uiMenuItemO(head, 0, "TEXT_OT_save_as");
637                 uiMenuItemO(head, 0, "TEXT_OT_run_script");
638                 uiPupMenuEnd(C, head);
639         }
640         else {
641                 head= uiPupMenuBegin("File", 0);
642                 uiMenuItemO(head, 0, "TEXT_OT_new");
643                 uiMenuItemO(head, 0, "TEXT_OT_open");
644                 uiPupMenuEnd(C, head);
645         }
646 }
647
648 {
649         // Alt+Shift+V
650
651         uiMenuItem *head;
652
653         head= uiPupMenuBegin("Text", 0);
654         uiMenuItemEnumO(head, "Top of File", 0, "TEXT_OT_move", "type", FILE_TOP);
655         uiMenuItemEnumO(head, "Bottom of File", 0, "TEXT_OT_move", "type", FILE_BOTTOM);
656         uiMenuItemEnumO(head, "Page Up", 0, "TEXT_OT_move", "type", PREV_PAGE);
657         uiMenuItemEnumO(head,  "Page Down", 0, "TEXT_OT_move", "type", NEXT_PAGE);
658         uiPupMenuEnd(C, head);
659 }
660 #endif
661