2.50: svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r19323...
[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_scene.h"
60 #include "BKE_screen.h"
61 #include "BKE_text.h"
62
63 #include "ED_screen.h"
64 #include "ED_types.h"
65 #include "ED_util.h"
66
67 #include "WM_api.h"
68 #include "WM_types.h"
69
70 #include "BIF_gl.h"
71 #include "BIF_glutil.h"
72
73 #include "UI_interface.h"
74 #include "UI_resources.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 static 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);
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 static 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);
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 int text_menu_edit_poll(bContext *C)
199 {
200         return (CTX_data_edit_text(C) != NULL);
201 }
202
203 static void text_editmenu(bContext *C, uiMenuItem *head, void *arg_unused)
204 {
205         uiMenuItemO(head, 0, "ED_OT_undo");
206         uiMenuItemO(head, 0, "ED_OT_redo");
207
208         uiMenuSeparator(head);
209
210         uiMenuItemO(head, 0, "TEXT_OT_cut");
211         uiMenuItemO(head, 0, "TEXT_OT_copy");
212         uiMenuItemO(head, 0, "TEXT_OT_paste");
213
214         uiMenuSeparator(head);
215
216         uiMenuLevel(head, "View", text_editmenu_viewmenu);
217         uiMenuLevel(head, "Select", text_editmenu_selectmenu);
218         uiMenuLevel(head, "Markers", text_editmenu_markermenu);
219
220         uiMenuSeparator(head);
221
222         uiMenuItemO(head, 0, "TEXT_OT_jump");
223         uiMenuItemO(head, 0, "TEXT_OT_properties");
224
225         uiMenuSeparator(head);
226
227         uiMenuLevel(head, "Text to 3D Object", text_editmenu_to3dmenu);
228 }
229
230 static void text_filemenu(bContext *C, uiMenuItem *head, void *arg_unused)
231 {
232         SpaceText *st= (SpaceText*)CTX_wm_space_data(C);
233         Text *text= st->text;
234
235         uiMenuItemO(head, 0, "TEXT_OT_new");
236         uiMenuItemO(head, 0, "TEXT_OT_open");
237         
238         if(text) {
239                 uiMenuItemO(head, 0, "TEXT_OT_reload");
240                 
241                 uiMenuSeparator(head);
242                 
243                 uiMenuItemO(head, 0, "TEXT_OT_save");
244                 uiMenuItemO(head, 0, "TEXT_OT_save_as");
245                 
246                 if(text->name)
247                         uiMenuItemO(head, 0, "TEXT_OT_make_internal");
248
249                 uiMenuSeparator(head);
250                 
251                 uiMenuItemO(head, 0, "TEXT_OT_run_script");
252
253 #ifndef DISABLE_PYTHON
254                 if(BPY_is_pyconstraint(text))
255                         uiMenuItemO(head, 0, "TEXT_OT_refresh_pyconstraints");
256 #endif
257         }
258
259 #ifndef DISABLE_PYTHON
260         // XXX uiMenuSeparator(head);
261
262         // XXX uiDefIconTextBlockBut(block, text_template_scriptsmenu, NULL, ICON_RIGHTARROW_THIN, "Script Templates", 0, yco-=20, 120, 19, "");
263         // XXX uiDefIconTextBlockBut(block, text_plugin_scriptsmenu, NULL, ICON_RIGHTARROW_THIN, "Text Plugins", 0, yco-=20, 120, 19, "");
264 #endif
265 }
266
267 /*********************** datablock browse *************************/
268
269 static void text_unlink(Main *bmain, Text *text)
270 {
271         bScreen *scr;
272         ScrArea *area;
273         SpaceLink *sl;
274
275         /* XXX this ifdef is in fact dangerous, if python is
276          * disabled it will leave invalid pointers in files! */
277
278 #ifndef DISABLE_PYTHON
279         // XXX BPY_clear_bad_scriptlinks(text);
280         // XXX BPY_free_pyconstraint_links(text);
281         // XXX free_text_controllers(text);
282         // XXX free_dome_warp_text(text);
283
284         /* check if this text was used as script link:
285          * this check function unsets the pointers and returns how many
286          * script links used this Text */
287         if(0) // XXX BPY_text_check_all_scriptlinks (text))
288                 ; // XXX notifier: allqueue(REDRAWBUTSSCRIPT, 0);
289
290         /* equivalently for pynodes: */
291         if(0) // XXX nodeDynamicUnlinkText ((ID*)text))
292                 ; // XXX notifier: allqueue(REDRAWNODE, 0);
293 #endif
294         
295         for(scr= bmain->screen.first; scr; scr= scr->id.next) {
296                 for(area= scr->areabase.first; area; area= area->next) {
297                         for(sl= area->spacedata.first; sl; sl= sl->next) {
298                                 if(sl->spacetype==SPACE_TEXT) {
299                                         SpaceText *st= (SpaceText*) sl;
300                                         
301                                         if(st->text==text) {
302                                                 st->text= NULL;
303                                                 st->top= 0;
304                                                 
305                                                 if(st==area->spacedata.first)
306                                                         ED_area_tag_redraw(area);
307                                         }
308                                 }
309                         }
310                 }
311         }
312
313         free_libblock(&bmain->text, text);
314 }
315
316 static void text_idpoin_handle(bContext *C, ID *id, int event)
317 {
318         SpaceText *st= (SpaceText*)CTX_wm_space_data(C);
319         Text *text;
320
321         switch(event) {
322                 case UI_ID_BROWSE:
323                         st->text= (Text*)id;
324                         st->top= 0;
325
326                         text_update_edited(st->text);
327                         WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, st->text);
328
329                         ED_undo_push(C, "Browse Text");
330                         break;
331                 case UI_ID_DELETE:
332                         text= st->text;
333
334                         /* make the previous text active, if its not there make the next text active */
335                         if(text->id.prev) {
336                                 st->text = text->id.prev;
337                                 WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, st->text);
338                         }
339                         else if(text->id.next) {
340                                 st->text = text->id.next;
341                                 WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, st->text);
342                         }
343
344                         text_unlink(CTX_data_main(C), text);
345                         WM_event_add_notifier(C, NC_TEXT|NA_REMOVED, text);
346
347                         ED_undo_push(C, "Delete Text");
348                         break;
349                 case UI_ID_RENAME:
350                         break;
351                 case UI_ID_ADD_NEW:
352                         WM_operator_name_call(C, "TEXT_OT_new", WM_OP_INVOKE_REGION_WIN, NULL);
353                         break;
354                 case UI_ID_OPEN:
355                         WM_operator_name_call(C, "TEXT_OT_open", WM_OP_INVOKE_REGION_WIN, NULL);
356                         break;
357         }
358 }
359
360 /********************** header buttons ***********************/
361
362 static void text_header_draw(const bContext *C, Header *header)
363 {
364         bScreen *sc= CTX_wm_screen(C);
365         SpaceText *st= (SpaceText*)CTX_wm_space_data(C);
366         PointerRNA spaceptr;
367         Text *text= st->text;
368         uiLayout *layout= header->layout;
369         
370         RNA_pointer_create(&sc->id, &RNA_SpaceTextEditor, st, &spaceptr);
371
372         uiTemplateHeaderMenus(layout);
373         uiItemM(layout, "Text", 0, text_filemenu);
374         if(text) {
375                 uiItemM(layout, "Edit", 0, text_editmenu);
376                 uiItemM(layout, "Format", 0, text_formatmenu);
377         }
378
379         /* warning button if text is out of date */
380         if(text && text_file_modified(text)) {
381                 uiTemplateHeaderButtons(layout);
382                 uiTemplateSetColor(layout, TH_REDALERT);
383                 uiItemO(layout, "", ICON_HELP, "TEXT_OT_resolve_conflict");
384         }
385
386         uiTemplateHeaderButtons(layout);
387         uiItemR(layout, "", ICON_LINENUMBERS_OFF, &spaceptr, "line_numbers", 0);
388         uiItemR(layout, "", ICON_WORDWRAP_OFF, &spaceptr, "word_wrap", 0);
389         uiItemR(layout, "", ICON_SYNTAX_OFF, &spaceptr, "syntax_highlight", 0);
390         // XXX uiItemR(layout, "", ICON_SCRIPTPLUGINS, &spaceptr, "do_python_plugins", 0);
391
392         uiTemplateHeaderID(layout, &spaceptr, "text",
393                 UI_ID_BROWSE|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_OPEN|UI_ID_DELETE,
394                 text_idpoin_handle);
395
396         /* file info */
397         if(text) {
398                 char fname[HEADER_PATH_MAX];
399                 static char headtxt[HEADER_PATH_MAX+17];
400                 int len;
401
402                 if(text->name) {
403                         len = strlen(text->name);
404                         if(len > HEADER_PATH_MAX-1)
405                                 len = HEADER_PATH_MAX-1;
406                         strncpy(fname, text->name, len);
407                         fname[len]='\0';
408                         if(text->flags & TXT_ISDIRTY)
409                                 sprintf(headtxt, "File: *%s (unsaved)", fname);
410                         else
411                                 sprintf(headtxt, "File: %s", fname);
412                 }
413                 else
414                         sprintf(headtxt, text->id.lib? "Text: External": "Text: Internal");
415
416                 uiTemplateHeaderButtons(layout);
417                 uiItemL(layout, headtxt, 0);
418         }
419 }
420
421 void text_header_register(ARegionType *art)
422 {
423         HeaderType *ht;
424
425         /* header */
426         ht= MEM_callocN(sizeof(HeaderType), "spacetype text header");
427         strcpy(ht->idname, "TEXT_HT_header");
428         ht->draw= text_header_draw;
429         BLI_addhead(&art->headertypes, ht);
430 }
431
432 /************************** properties ******************************/
433
434 static void text_properties_panel_draw(const bContext *C, Panel *panel)
435 {
436         bScreen *sc= CTX_wm_screen(C);
437         SpaceText *st= CTX_wm_space_text(C);
438         uiLayout *layout= panel->layout;
439         PointerRNA spaceptr;
440         
441         RNA_pointer_create(&sc->id, &RNA_SpaceTextEditor, st, &spaceptr);
442
443         uiLayoutColumn(layout);
444         uiItemR(layout, NULL, ICON_LINENUMBERS_OFF, &spaceptr, "line_numbers", 0);
445         uiItemR(layout, NULL, ICON_WORDWRAP_OFF, &spaceptr, "word_wrap", 0);
446         uiItemR(layout, NULL, ICON_SYNTAX_OFF, &spaceptr, "syntax_highlight", 0);
447
448         uiLayoutColumn(layout);
449         uiItemR(layout, NULL, 0, &spaceptr, "font_size", 0);
450         uiItemR(layout, NULL, 0, &spaceptr, "tab_width", 0);
451 }
452
453 static void text_find_panel_draw(const bContext *C, Panel *panel)
454 {
455         bScreen *sc= CTX_wm_screen(C);
456         SpaceText *st= CTX_wm_space_text(C);
457         uiLayout *layout= panel->layout;
458         PointerRNA spaceptr;
459         
460         RNA_pointer_create(&sc->id, &RNA_SpaceTextEditor, st, &spaceptr);
461
462         /* find */
463         uiLayoutRow(layout);
464         uiItemR(layout, "", 0, &spaceptr, "find_text", 0);
465         uiItemO(layout, "", ICON_TEXT, "TEXT_OT_find_set_selected");
466         uiLayoutColumn(layout);
467         uiItemO(layout, NULL, 0, "TEXT_OT_find");
468
469         /* replace */
470         uiLayoutRow(layout);
471         uiItemR(layout, "", 0, &spaceptr, "replace_text", 0);
472         uiItemO(layout, "", ICON_TEXT, "TEXT_OT_replace_set_selected");
473         uiLayoutColumn(layout);
474         uiItemO(layout, NULL, 0, "TEXT_OT_replace");
475
476         /* mark */
477         uiLayoutColumn(layout);
478         uiItemO(layout, NULL, 0, "TEXT_OT_mark_all");
479
480         /* settings */
481         uiLayoutColumnFlow(layout, 0);
482         uiItemR(layout, "Wrap", 0, &spaceptr, "find_wrap", 0);
483         uiItemR(layout, "All", 0, &spaceptr, "find_all", 0);
484 }
485
486 void text_properties_register(ARegionType *art)
487 {
488         PanelType *pt;
489
490         /* panels: properties */
491         pt= MEM_callocN(sizeof(PanelType), "spacetype text panel");
492         strcpy(pt->idname, "TEXT_PT_properties");
493         strcpy(pt->label, "Properties");
494         pt->draw= text_properties_panel_draw;
495         BLI_addtail(&art->paneltypes, pt);
496
497         /* panels: find */
498         pt= MEM_callocN(sizeof(PanelType), "spacetype text panel");
499         strcpy(pt->idname, "TEXT_PT_find");
500         strcpy(pt->label, "Find");
501         pt->draw= text_find_panel_draw;
502         BLI_addtail(&art->paneltypes, pt);
503 }
504
505 ARegion *text_has_properties_region(ScrArea *sa)
506 {
507         ARegion *ar, *arnew;
508         
509         for(ar= sa->regionbase.first; ar; ar= ar->next)
510                 if(ar->regiontype==RGN_TYPE_UI)
511                         return ar;
512         
513         /* add subdiv level; after header */
514         for(ar= sa->regionbase.first; ar; ar= ar->next)
515                 if(ar->regiontype==RGN_TYPE_HEADER)
516                         break;
517         
518         /* is error! */
519         if(ar==NULL) return NULL;
520         
521         arnew= MEM_callocN(sizeof(ARegion), "properties region");
522         
523         BLI_insertlinkafter(&sa->regionbase, ar, arnew);
524         arnew->regiontype= RGN_TYPE_UI;
525         arnew->alignment= RGN_ALIGN_LEFT;
526         
527         arnew->flag = RGN_FLAG_HIDDEN;
528         
529         return arnew;
530 }
531
532 static int properties_poll(bContext *C)
533 {
534         SpaceText *st= CTX_wm_space_text(C);
535         Text *text= CTX_data_edit_text(C);
536
537         return (st && text);
538 }
539
540 static int properties_exec(bContext *C, wmOperator *op)
541 {
542         ScrArea *sa= CTX_wm_area(C);
543         ARegion *ar= text_has_properties_region(sa);
544         
545         if(ar) {
546                 ar->flag ^= RGN_FLAG_HIDDEN;
547                 ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */
548                 
549                 ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
550                 ED_area_tag_redraw(sa);
551         }
552
553         return OPERATOR_FINISHED;
554 }
555
556 void TEXT_OT_properties(wmOperatorType *ot)
557 {
558         /* identifiers */
559         ot->name= "Properties";
560         ot->idname= "TEXT_OT_properties";
561         
562         /* api callbacks */
563         ot->exec= properties_exec;
564         ot->poll= properties_poll;
565 }
566
567 /******************** XXX popup menus *******************/
568
569 #if 0
570 {
571         // RMB
572
573         uiMenuItem *head;
574
575         if(text) {
576                 head= uiPupMenuBegin("Text", 0);
577                 if(txt_has_sel(text)) {
578                         uiMenuItemO(head, 0, "TEXT_OT_cut");
579                         uiMenuItemO(head, 0, "TEXT_OT_copy");
580                 }
581                 uiMenuItemO(head, 0, "TEXT_OT_paste");
582                 uiMenuItemO(head, 0, "TEXT_OT_new");
583                 uiMenuItemO(head, 0, "TEXT_OT_open");
584                 uiMenuItemO(head, 0, "TEXT_OT_save");
585                 uiMenuItemO(head, 0, "TEXT_OT_save_as");
586                 uiMenuItemO(head, 0, "TEXT_OT_run_script");
587                 uiPupMenuEnd(C, head);
588         }
589         else {
590                 head= uiPupMenuBegin("File", 0);
591                 uiMenuItemO(head, 0, "TEXT_OT_new");
592                 uiMenuItemO(head, 0, "TEXT_OT_open");
593                 uiPupMenuEnd(C, head);
594         }
595 }
596
597 {
598         // Alt+Shift+E
599
600         uiMenuItem *head;
601
602         head= uiPupMenuBegin("Edit", 0);
603         uiMenuItemO(head, 0, "TEXT_OT_cut");
604         uiMenuItemO(head, 0, "TEXT_OT_copy");
605         uiMenuItemO(head, 0, "TEXT_OT_paste");
606         uiPupMenuEnd(C, head);
607 }
608
609 {
610         // Alt+Shift+F
611
612         uiMenuItem *head;
613
614         if(text) {
615                 head= uiPupMenuBegin("Text", 0);
616                 uiMenuItemO(head, 0, "TEXT_OT_new");
617                 uiMenuItemO(head, 0, "TEXT_OT_open");
618                 uiMenuItemO(head, 0, "TEXT_OT_save");
619                 uiMenuItemO(head, 0, "TEXT_OT_save_as");
620                 uiMenuItemO(head, 0, "TEXT_OT_run_script");
621                 uiPupMenuEnd(C, head);
622         }
623         else {
624                 head= uiPupMenuBegin("File", 0);
625                 uiMenuItemO(head, 0, "TEXT_OT_new");
626                 uiMenuItemO(head, 0, "TEXT_OT_open");
627                 uiPupMenuEnd(C, head);
628         }
629 }
630
631 {
632         // Alt+Shift+V
633
634         uiMenuItem *head;
635
636         head= uiPupMenuBegin("Text", 0);
637         uiMenuItemEnumO(head, "Top of File", 0, "TEXT_OT_move", "type", FILE_TOP);
638         uiMenuItemEnumO(head, "Bottom of File", 0, "TEXT_OT_move", "type", FILE_BOTTOM);
639         uiMenuItemEnumO(head, "Page Up", 0, "TEXT_OT_move", "type", PREV_PAGE);
640         uiMenuItemEnumO(head,  "Page Down", 0, "TEXT_OT_move", "type", NEXT_PAGE);
641         uiPupMenuEnd(C, head);
642 }
643 #endif
644