- use clear, set, add, enable, disable and toggle as a prefix in operator names
[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_markers_clear");
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_properties");
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 static void header_buttons(const bContext *C, uiLayout *layout)
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         
363         RNA_pointer_create(&sc->id, &RNA_SpaceTextEditor, st, &spaceptr);
364
365         uiTemplateHeaderMenus(layout);
366         uiItemMenu(layout, UI_TSLOT_HEADER, "Text", 0, text_filemenu);
367         if(text) {
368                 uiItemMenu(layout, UI_TSLOT_HEADER, "Edit", 0, text_editmenu);
369                 uiItemMenu(layout, UI_TSLOT_HEADER, "Format", 0, text_formatmenu);
370         }
371
372         /* warning button if text is out of date */
373         if(text && text_file_modified(text)) {
374                 uiTemplateHeaderButtons(layout);
375                 uiTemplateSetColor(layout, TH_REDALERT);
376                 uiItemO(layout, UI_TSLOT_HEADER, "", ICON_HELP, "TEXT_OT_resolve_conflict");
377         }
378
379         uiTemplateHeaderButtons(layout);
380         uiItemR(layout, UI_TSLOT_HEADER, "", ICON_LINENUMBERS_OFF, &spaceptr, "line_numbers");
381         uiItemR(layout, UI_TSLOT_HEADER, "", ICON_WORDWRAP_OFF, &spaceptr, "word_wrap");
382         uiItemR(layout, UI_TSLOT_HEADER, "", ICON_SYNTAX_OFF, &spaceptr, "syntax_highlight");
383         // XXX uiItemR(layout, "", ICON_SCRIPTPLUGINS, &spaceptr, "do_python_plugins");
384
385         uiTemplateHeaderID(layout, &spaceptr, "text",
386                 UI_ID_BROWSE|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_OPEN|UI_ID_DELETE,
387                 text_idpoin_handle);
388
389         /* file info */
390         if(text) {
391                 char fname[HEADER_PATH_MAX];
392                 static char headtxt[HEADER_PATH_MAX+17];
393                 int len;
394
395                 if(text->name) {
396                         len = strlen(text->name);
397                         if(len > HEADER_PATH_MAX-1)
398                                 len = HEADER_PATH_MAX-1;
399                         strncpy(fname, text->name, len);
400                         fname[len]='\0';
401                         if(text->flags & TXT_ISDIRTY)
402                                 sprintf(headtxt, "File: *%s (unsaved)", fname);
403                         else
404                                 sprintf(headtxt, "File: %s", fname);
405                 }
406                 else
407                         sprintf(headtxt, text->id.lib? "Text: External": "Text: Internal");
408
409                 uiTemplateHeaderButtons(layout);
410                 uiItemLabel(layout, UI_TSLOT_HEADER, headtxt, 0);
411         }
412 }
413
414 void text_header_buttons(const bContext *C, ARegion *ar)
415 {
416         uiHeaderLayout(C, ar, header_buttons);
417 }
418
419 /************************** properties ******************************/
420
421 void properties_buttons(const bContext *C, uiLayout *layout)
422 {
423         bScreen *sc= CTX_wm_screen(C);
424         SpaceText *st= CTX_wm_space_text(C);
425         PointerRNA spaceptr;
426         
427         RNA_pointer_create(&sc->id, &RNA_SpaceTextEditor, st, &spaceptr);
428
429         uiTemplateColumn(layout);
430         uiItemR(layout, UI_TSLOT_COLUMN_1, NULL, ICON_LINENUMBERS_OFF, &spaceptr, "line_numbers");
431         uiItemR(layout, UI_TSLOT_COLUMN_1, NULL, ICON_WORDWRAP_OFF, &spaceptr, "word_wrap");
432         uiItemR(layout, UI_TSLOT_COLUMN_1, NULL, ICON_SYNTAX_OFF, &spaceptr, "syntax_highlight");
433
434         uiTemplateColumn(layout);
435         uiItemR(layout, UI_TSLOT_COLUMN_1, NULL, 0, &spaceptr, "font_size");
436         uiItemR(layout, UI_TSLOT_COLUMN_1, NULL, 0, &spaceptr, "tab_width");
437 }
438
439 void find_buttons(const bContext *C, uiLayout *layout)
440 {
441         bScreen *sc= CTX_wm_screen(C);
442         SpaceText *st= CTX_wm_space_text(C);
443         PointerRNA spaceptr;
444         
445         RNA_pointer_create(&sc->id, &RNA_SpaceTextEditor, st, &spaceptr);
446
447         /* find */
448         uiTemplateLeftRight(layout);
449         uiItemR(layout, UI_TSLOT_LR_LEFT, "", 0, &spaceptr, "find_text");
450         uiItemO(layout, UI_TSLOT_LR_RIGHT, "", ICON_TEXT, "TEXT_OT_find_set_selected");
451         uiTemplateColumn(layout);
452         uiItemO(layout, UI_TSLOT_COLUMN_1, NULL, 0, "TEXT_OT_find");
453
454         /* replace */
455         uiTemplateLeftRight(layout);
456         uiItemR(layout, UI_TSLOT_LR_LEFT, "", 0, &spaceptr, "replace_text");
457         uiItemO(layout, UI_TSLOT_LR_RIGHT, "", ICON_TEXT, "TEXT_OT_replace_set_selected");
458         uiTemplateColumn(layout);
459         uiItemO(layout, UI_TSLOT_COLUMN_1, NULL, 0, "TEXT_OT_replace");
460
461         /* mark */
462         uiTemplateColumn(layout);
463         uiItemO(layout, UI_TSLOT_COLUMN_1, NULL, 0, "TEXT_OT_mark_all");
464
465         /* settings */
466         uiTemplateColumn(layout);
467         uiItemR(layout, UI_TSLOT_COLUMN_1, "Wrap", 0, &spaceptr, "find_wrap");
468         uiItemR(layout, UI_TSLOT_COLUMN_2, "All", 0, &spaceptr, "find_all");
469 }
470
471 void text_properties_buttons(const bContext *C, ARegion *ar)
472 {
473         uiCompactPanelLayout(C, ar, "TEXT_OT_properties", "Properties", "Text", properties_buttons, 0);
474         uiCompactPanelLayout(C, ar, "TEXT_OT_find", "Find", "Text", find_buttons, 1);
475
476         uiDrawPanels(C, 1);
477         uiMatchPanelsView2d(ar);
478 }
479
480 ARegion *text_has_properties_region(ScrArea *sa)
481 {
482         ARegion *ar, *arnew;
483         
484         for(ar= sa->regionbase.first; ar; ar= ar->next)
485                 if(ar->regiontype==RGN_TYPE_UI)
486                         return ar;
487         
488         /* add subdiv level; after header */
489         for(ar= sa->regionbase.first; ar; ar= ar->next)
490                 if(ar->regiontype==RGN_TYPE_HEADER)
491                         break;
492         
493         /* is error! */
494         if(ar==NULL) return NULL;
495         
496         arnew= MEM_callocN(sizeof(ARegion), "properties region");
497         
498         BLI_insertlinkafter(&sa->regionbase, ar, arnew);
499         arnew->regiontype= RGN_TYPE_UI;
500         arnew->alignment= RGN_ALIGN_LEFT;
501         
502         arnew->flag = RGN_FLAG_HIDDEN;
503         
504         return arnew;
505 }
506
507 static int properties_poll(bContext *C)
508 {
509         SpaceText *st= CTX_wm_space_text(C);
510         Text *text= CTX_data_edit_text(C);
511
512         return (st && text);
513 }
514
515 static int properties_exec(bContext *C, wmOperator *op)
516 {
517         ScrArea *sa= CTX_wm_area(C);
518         ARegion *ar= text_has_properties_region(sa);
519         
520         if(ar) {
521                 ar->flag ^= RGN_FLAG_HIDDEN;
522                 ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */
523                 
524                 ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
525                 ED_area_tag_redraw(sa);
526         }
527
528         return OPERATOR_FINISHED;
529 }
530
531 void TEXT_OT_properties(wmOperatorType *ot)
532 {
533         /* identifiers */
534         ot->name= "Properties";
535         ot->idname= "TEXT_OT_properties";
536         
537         /* api callbacks */
538         ot->exec= properties_exec;
539         ot->poll= properties_poll;
540 }
541
542 /******************** XXX popup menus *******************/
543
544 #if 0
545 {
546         // RMB
547
548         uiMenuItem *head;
549
550         if(text) {
551                 head= uiPupMenuBegin("Text", 0);
552                 if(txt_has_sel(text)) {
553                         uiMenuItemO(head, 0, "TEXT_OT_cut");
554                         uiMenuItemO(head, 0, "TEXT_OT_copy");
555                 }
556                 uiMenuItemO(head, 0, "TEXT_OT_paste");
557                 uiMenuItemO(head, 0, "TEXT_OT_new");
558                 uiMenuItemO(head, 0, "TEXT_OT_open");
559                 uiMenuItemO(head, 0, "TEXT_OT_save");
560                 uiMenuItemO(head, 0, "TEXT_OT_save_as");
561                 uiMenuItemO(head, 0, "TEXT_OT_run_script");
562                 uiPupMenuEnd(C, head);
563         }
564         else {
565                 head= uiPupMenuBegin("File", 0);
566                 uiMenuItemO(head, 0, "TEXT_OT_new");
567                 uiMenuItemO(head, 0, "TEXT_OT_open");
568                 uiPupMenuEnd(C, head);
569         }
570 }
571
572 {
573         // Alt+Shift+E
574
575         uiMenuItem *head;
576
577         head= uiPupMenuBegin("Edit", 0);
578         uiMenuItemO(head, 0, "TEXT_OT_cut");
579         uiMenuItemO(head, 0, "TEXT_OT_copy");
580         uiMenuItemO(head, 0, "TEXT_OT_paste");
581         uiPupMenuEnd(C, head);
582 }
583
584 {
585         // Alt+Shift+F
586
587         uiMenuItem *head;
588
589         if(text) {
590                 head= uiPupMenuBegin("Text", 0);
591                 uiMenuItemO(head, 0, "TEXT_OT_new");
592                 uiMenuItemO(head, 0, "TEXT_OT_open");
593                 uiMenuItemO(head, 0, "TEXT_OT_save");
594                 uiMenuItemO(head, 0, "TEXT_OT_save_as");
595                 uiMenuItemO(head, 0, "TEXT_OT_run_script");
596                 uiPupMenuEnd(C, head);
597         }
598         else {
599                 head= uiPupMenuBegin("File", 0);
600                 uiMenuItemO(head, 0, "TEXT_OT_new");
601                 uiMenuItemO(head, 0, "TEXT_OT_open");
602                 uiPupMenuEnd(C, head);
603         }
604 }
605
606 {
607         // Alt+Shift+V
608
609         uiMenuItem *head;
610
611         head= uiPupMenuBegin("Text", 0);
612         uiMenuItemEnumO(head, "Top of File", 0, "TEXT_OT_move", "type", FILE_TOP);
613         uiMenuItemEnumO(head, "Bottom of File", 0, "TEXT_OT_move", "type", FILE_BOTTOM);
614         uiMenuItemEnumO(head, "Page Up", 0, "TEXT_OT_move", "type", PREV_PAGE);
615         uiMenuItemEnumO(head,  "Page Down", 0, "TEXT_OT_move", "type", NEXT_PAGE);
616         uiPupMenuEnd(C, head);
617 }
618 #endif
619