home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 15 / Amiga Plus Leser CD 15.iso / Tools / Development / MosaicSRC / src / TextEditField.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-03-13  |  37.3 KB  |  1,277 lines

  1. #include <proto/utility.h>
  2. #include <proto/intuition.h>
  3. #include <proto/graphics.h>
  4. #include <proto/layers.h>
  5. #include <proto/dos.h>
  6. #include <proto/muimaster.h>
  7.  
  8. #include <graphics/gfxmacros.h>
  9.  
  10. #include <exec/memory.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14.  
  15. #include "TextEditField.h"
  16. // #include "demo.h"
  17. static const char VersionTag[] = "\0$VER: TextEditField.c 1.0 (12.06.95)";
  18.  
  19. #define MUIA_Prop_Delta                 0x8042c5f4 /* is. LONG              */
  20. #define MUIA_Prop_DeltaFactor           0x80427c5e /* isg LONG              */
  21.  
  22. #define PreAlloc 256 /* Preallocate 256 bytes */
  23.  
  24. extern struct Library *MUIMasterBase;
  25. //struct MsgPort *FileNotifyPort;
  26. extern struct MsgPort *FileNotifyPort;
  27.  
  28. void fail(APTR,APTR);
  29. long kprintf(char *,...);
  30. ULONG __saveds __asm EditFunc(register __a0 struct Hook *hook,
  31.                register __a2 APTR          object,
  32.                register __a1 struct EditFuncMsg *msg);
  33.  
  34. #define IEQUALIFIER_SHIFT (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)
  35. #define IEQUALIFIER_ALT (IEQUALIFIER_LALT | IEQUALIFIER_RALT)
  36.  
  37. #define HIKEY_SHIFT    (0x100)
  38. #define HIKEY_ALT    (0x200)
  39. #define HIKEY_CTRL    (0x400)
  40.  
  41. static struct Hook EditHook={{0,0},(APTR)EditFunc,NULL,NULL};
  42.  
  43. /*
  44.  * Class data
  45.  */
  46.  
  47. static Class *TextFieldCl;
  48.  
  49. struct TextEditFieldClData
  50. {
  51.     Object *TextField;
  52.     Object *VBar;
  53.     Object *HBar;
  54.     Object *Space;
  55. };
  56.  
  57. struct TextFieldClData
  58. {
  59.     Object *VBar;
  60.     Object *HBar;
  61.  
  62.     LONG x_offset;
  63.     LONG y_offset;
  64. /*    LONG c_width;        /* In chars */
  65.     LONG c_height;        /* In chars */ */
  66.     LONG width;            /* In pixels */
  67.     LONG height;        /* In pixels */
  68.     LONG lines;            /* # of lines in the text */
  69.     LONG longest_line;
  70.     LONG text_width;    /* Max chars/line *tf_XSize */
  71.     LONG text_height;    /* Lines *tf_YSize */
  72.     char *text;            /* The actual text */
  73.     char **linearray;     /* For fast search in the text */
  74.     char *end_text;      /* The last char +1 in the text */
  75.     LONG cursor_x;        /* Chars offset from left text left */
  76.     LONG cursor_y;        /* Chars offset from top text top */
  77.     LONG s_cursor_x;    /* Offset from left border*/
  78.     LONG s_cursor_y;    /* Offset from top border */
  79.     LONG active;
  80.     UWORD font_width,font_height; /* For fast access */
  81.     struct NotifyRequest FileNotify;
  82.     LONG notifying;
  83.     LONG alloced_size;    /* Allocated space for text */
  84.     LONG text_size;        /* The size of the text */
  85.     LONG go_active;        /* Signal the gadget to go active 1= inactivate, 2= activate */
  86.     LONG visible_lines;
  87.     LONG visible_columns;
  88.     WORD p_l,p_r,p_t,p_b; /* The parrent group size */
  89.     Object *parent;
  90.     LONG icr_left,icr_top,icr_width,icr_height;
  91.     LONG icr_ncx,icr_ncy;
  92.     LONG FileNo;
  93.     char *FileName;
  94. };
  95.  
  96. /*
  97.  * Misc routines
  98.  */
  99.  
  100. static LONG LineLength(char *str)
  101. {
  102.     LONG l=(LONG)str;
  103.     for(;*str!='\n' && *str!=0;str++);
  104.     return (LONG)str-l;
  105. }
  106.  
  107. static LONG LongestLine(struct TextFieldClData *inst)
  108. {
  109.     char **lines;
  110.     LONG len,longlen=0;
  111.  
  112.     for(lines=inst->linearray;*lines;lines++){
  113.         if((len=LineLength(*lines))>longlen)
  114.             longlen=len;
  115.         }
  116.     return longlen;
  117. }
  118.  
  119. static ULONG CountLines(char *str)
  120. {
  121.     ULONG i=1;
  122.     for(;*str;str++)
  123.         if(*str=='\n')
  124.             i++;
  125.     return i;
  126. }
  127.  
  128. static void ParseText(struct TextFieldClData *inst)
  129. {
  130.     char **line,*text;
  131.     BOOL newline;
  132.     LONG longline;
  133.  
  134.     inst->lines=CountLines(inst->text);
  135.     if(inst->linearray) FreeVec(inst->linearray);
  136.     inst->linearray=(char **)AllocVec((inst->lines+25)<<2,MEMF_CLEAR);
  137.     inst->longest_line=0;
  138.     longline=0;
  139.     line=inst->linearray;
  140.     newline=TRUE;
  141.     for(text=inst->text;*text;text++){
  142.         if(newline){
  143.             newline=FALSE;
  144.             *line++=text;
  145.             if(inst->longest_line<longline) inst->longest_line=longline;
  146.             longline=0;
  147.             }
  148.         if(*text=='\n') newline=TRUE;
  149.         longline++;
  150.         }
  151.     if(newline){
  152.         *line++=text;
  153.         if(inst->longest_line<longline) inst->longest_line=longline;
  154.         }
  155.     inst->end_text=text;
  156.     *line=NULL;
  157. }
  158.  
  159. /*
  160.  * Cursor handling
  161.  */
  162.  
  163. static void ShowC (struct RastPort *rp,long col,long x,long y,BOOL active,long width,long height)
  164. {
  165.     static UWORD mask1[] = {0x5555,0xAAAA};
  166.     static UWORD mask2[] = {0xAAAA,0x5555}; /* Depending on the y pos */
  167.     BYTE DrMode;
  168.     DrMode=rp->DrawMode;
  169.     SetABPenDrMd(rp,col,0,COMPLEMENT);
  170.     if(!active){
  171.         if((x ^ y)&1)
  172.             {SetAfPt(rp,(UWORD *)&mask1,1);}
  173.         else
  174.             {SetAfPt(rp,(UWORD *)&mask2,1);}
  175.         }
  176.     RectFill(rp,x,y,x+width-1,y+height-1);
  177.     SetDrMd(rp,DrMode);
  178.     if(!active) SetAfPt(rp,NULL,0);
  179. }
  180.  
  181. static void ClipCursor(struct TextFieldClData *inst,Object *obj)
  182. {
  183.     if(inst->icr_ncx*inst->font_width<inst->x_offset){ /* Go left */
  184.  
  185.         inst->icr_left=_mleft(obj);
  186.         inst->icr_top=_mtop(obj);
  187.         inst->icr_width=_mwidth(obj);
  188.         inst->icr_height=_mheight(obj);
  189.  
  190.         inst->x_offset = inst->icr_ncx*inst->font_width;
  191.         nnset(inst->HBar,MUIA_Prop_First,inst->x_offset);
  192.         }
  193.     if(inst->icr_ncy*inst->font_height<inst->y_offset){ /* Go up */
  194.  
  195.         inst->icr_left=_mleft(obj);
  196.         inst->icr_top=_mtop(obj);
  197.         inst->icr_width=_mwidth(obj);
  198.         inst->icr_height=_mheight(obj);
  199.  
  200.         inst->y_offset = inst->icr_ncy*inst->font_height;
  201.         nnset(inst->VBar,MUIA_Prop_First,inst->y_offset);
  202.         }
  203.     if(((inst->icr_ncx+1)*inst->font_width)>inst->x_offset+_mwidth(obj)){
  204.         /* Go right */
  205.         inst->icr_left=_mleft(obj);
  206.         inst->icr_top=_mtop(obj);
  207.         inst->icr_width=_mwidth(obj);
  208.         inst->icr_height=_mheight(obj);
  209.  
  210.         inst->x_offset = ((inst->icr_ncx+1)*inst->font_width)-_mwidth(obj);
  211.         nnset(inst->HBar,MUIA_Prop_First,inst->x_offset);
  212.         }
  213.     if(((inst->icr_ncy+1)*inst->font_height)>inst->y_offset+_mheight(obj)){
  214.         /* Go down */
  215.  
  216.         inst->icr_left=_mleft(obj);
  217.         inst->icr_top=_mtop(obj);
  218.         inst->icr_width=_mwidth(obj);
  219.         inst->icr_height=_mheight(obj);
  220.  
  221.         inst->y_offset = ((inst->icr_ncy+1)*inst->font_height)-_mheight(obj);
  222.         nnset(inst->VBar,MUIA_Prop_First,inst->y_offset);
  223.         }    
  224. }
  225.  
  226. static void ClipCursor2(struct TextFieldClData *inst,Object *obj)
  227. {
  228.     inst->icr_ncx=inst->cursor_x;
  229.     inst->icr_ncy=inst->cursor_y;
  230.  
  231.     if(inst->cursor_x*inst->font_width<inst->x_offset)
  232.         inst->icr_ncx=(inst->x_offset+inst->font_width-1)/inst->font_width;
  233.     if(inst->cursor_y*inst->font_height<inst->y_offset)
  234.         inst->icr_ncy=(inst->y_offset+inst->font_height-1)/inst->font_height;
  235.     if(((inst->cursor_x+1)*inst->font_width)>inst->x_offset+_mwidth(obj))
  236.         inst->icr_ncx=(inst->x_offset+_mwidth(obj))/inst->font_width-1;
  237.     if(((inst->cursor_y+1)*inst->font_height)>inst->y_offset+_mheight(obj))
  238.         inst->icr_ncy=(inst->y_offset+_mheight(obj))/inst->font_height-1;
  239. }
  240. static void ShowCursor (struct TextFieldClData *inst,
  241.                         Object *obj)
  242. {
  243.     ShowC(_rp(obj),_dri(obj)->dri_Pens[HIGHLIGHTTEXTPEN],
  244.             _mleft(obj)+inst->s_cursor_x,_mtop(obj)+inst->s_cursor_y,inst->active&1,inst->font_width,inst->font_height);
  245. }
  246.  
  247. static void HideCursor (struct TextFieldClData *inst,
  248.                         Object *obj)
  249. {
  250.     ShowC(_rp(obj),_dri(obj)->dri_Pens[HIGHLIGHTTEXTPEN],
  251.             _mleft(obj)+inst->s_cursor_x,_mtop(obj)+inst->s_cursor_y,inst->active&1,inst->font_width,inst->font_height);
  252. }
  253.  
  254. /*
  255.  * Refresh routines
  256.  */
  257.  
  258. static void RefreshTextArea(struct Window *window,
  259.                             struct TextFieldClData *inst,
  260.                             Object *obj,
  261.                             long offs_x,long offs_y,
  262.                             long x,long y,
  263.                             long width,long height)
  264. {
  265.     LONG line,charpos,dx,dy,nchars,nwidth,ypos,nlines,nheight,rnchars;
  266.     LONG endcolumn;
  267.     char *linetext,*rtext;
  268.     struct Region *region;
  269.     BYTE DrMode;
  270.     APTR cliphandle;
  271.  
  272.     DrMode=_rp(obj)->DrawMode;
  273.     SetFont(_rp(obj),_font(obj));
  274.  
  275.     cliphandle=MUI_AddClipping(muiRenderInfo(obj),x,y,width,height);
  276.     endcolumn=x+width-1;
  277.  
  278.     line    = offs_y/inst->font_height;
  279. //    kprintf("Line: %ld\n",line);
  280.     if(line>inst->lines) line=inst->lines;
  281.     dy        = offs_y % inst->font_height;
  282.     ypos    = y-dy;
  283.     nlines    = 1;
  284.     if(dy) nlines++;
  285.     nheight    = height-dy;
  286.     if(nheight>0)
  287.         nlines+=nheight/inst->font_height;
  288.     if(nheight % inst->font_height)
  289.         nlines++;
  290.  
  291.     SetABPenDrMd(_rp(obj),1,0,JAM2);
  292. /*    kprintf("Lines %ld\n",nlines); */
  293.  
  294.     while(nlines--){
  295.         charpos    = offs_x/inst->font_width;
  296.         dx        = offs_x % inst->font_width;
  297.         linetext=inst->linearray[line];
  298.         if(linetext){
  299. //            kprintf("Linetext %08lx\n",linetext);
  300.             for(;*linetext!='\n' && *linetext!='\000' && charpos;linetext++,charpos--);
  301.             nchars=1;
  302.             if(dx) nchars++;
  303.             nwidth=width-dx;
  304.             if(nwidth>0)
  305.                 nchars+=nwidth/inst->font_width;
  306.             if(nwidth % inst->font_width)
  307.                 nchars++;
  308.  
  309.             for(rnchars=0,rtext=linetext;nchars-- && *rtext!='\000' && *rtext!='\n';rnchars++,rtext++);
  310.  
  311.             Move(_rp(obj),x-dx,ypos+_font(obj)->tf_Baseline);
  312.             Text(_rp(obj),linetext,rnchars);
  313.             if(_rp(obj)->cp_x<endcolumn){
  314.                 SetAPen(_rp(obj),0);
  315.                 RectFill(_rp(obj),_rp(obj)->cp_x,ypos,endcolumn,_rp(obj)->cp_y+_font(obj)->tf_YSize-1);
  316.                 SetAPen(_rp(obj),1);
  317.                 }
  318.             ypos+=_font(obj)->tf_YSize;
  319.             line++;
  320.             }
  321.         }
  322.     SetDrMd(_rp(obj),DrMode);
  323.     MUI_RemoveClipping(muiRenderInfo(obj),cliphandle);
  324. }
  325.  
  326. static UBYTE chartable[256]={ /* To filter 'illegal' chars */
  327. 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x0A,0x20,0x20,0x0A,0x20,0x20,
  328. 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
  329. 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
  330. 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
  331. 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
  332. 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
  333. 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
  334. 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x20,
  335. 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
  336. 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
  337. 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
  338. 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
  339. 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
  340. 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
  341. 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
  342. 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF};
  343.  
  344. static void SetText(struct TextFieldClData *inst,char *text)
  345. {
  346.     LONG length=strlen(text);
  347.     APTR oldmem=inst->text;
  348.     char *p1,*p2;
  349.  
  350. //    kprintf("(Re)allocating\n");
  351.  
  352.     inst->text=AllocVec(length+PreAlloc,0L);
  353.     for(p1=text,p2=inst->text;*p1;*p2++=chartable[(UBYTE)*p1++]);
  354.     *p2=0;
  355.     inst->text_size=length;
  356.     inst->alloced_size=length+PreAlloc;
  357.     if(oldmem) FreeVec(oldmem);
  358. }
  359.  
  360. static long cnt;
  361.  
  362. /* Return true if redraw is needed */
  363.  
  364. BOOL InsertChar(Object *obj,struct TextFieldClData *inst,long ascii)
  365. {
  366.     char *textpos,*currentpos,**lines=inst->linearray,*tpos;
  367.     long cursor_x,cursor_y;
  368.  
  369.     LONG i;
  370.     char str[]=" ";
  371.  
  372.     str[0]=(char)ascii;
  373.  
  374. //    kprintf("Getting char %s at %ld\n",str,cnt);
  375. //    return;
  376.  
  377.     cursor_x=inst->cursor_x;
  378.     cursor_y=inst->cursor_y;
  379.  
  380.     if((i=LineLength(lines[inst->cursor_y]))<inst->cursor_x){
  381.         inst->icr_ncx=i;
  382.         inst->icr_ncy=inst->cursor_y;
  383.         cursor_x=i;
  384.         } /* After this cursor_x may have changed */
  385.  
  386.     textpos=(char *)(lines[cursor_y]+cursor_x);
  387.  
  388. //    kprintf("Keycode: %ld\n",ascii);
  389.  
  390.     if((ascii>31) && (ascii!=127)){ /* Normal chars */
  391.         for(currentpos=inst->end_text,tpos=inst->end_text+1;currentpos>=textpos;*tpos--=*currentpos--);
  392.         for(i=cursor_y+1;lines[i];i++)
  393.             lines[i]++;
  394.         *++currentpos=ascii;
  395.         inst->end_text++;
  396.  
  397.         for(;*currentpos!=0 && *currentpos!='\n';currentpos++);
  398.         currentpos=(char *)((long)currentpos-(long)lines[cursor_y]+1); /* = line length */
  399.         if((long)currentpos>inst->longest_line){
  400.             inst->longest_line=(long)currentpos;
  401.             set(inst->HBar,MUIA_Prop_Entries,inst->longest_line*inst->font_width);
  402.             }
  403.  
  404.         inst->icr_ncx=cursor_x+1;
  405.  
  406.         inst->text_size++;
  407.  
  408.         if((inst->text_size+10)>inst->alloced_size){ /* Exceeding buffer */
  409.             SetText(inst,inst->text);
  410.             ParseText(inst);
  411.             }
  412.  
  413. //        RefreshTextArea(_window(obj),inst,obj,inst->x_offset,inst->font_height*cursor_y,_mleft(obj),_mtop(obj)+inst->font_height*cursor_y-inst->y_offset,_mwidth(obj),inst->font_height);
  414.         inst->icr_left=_mleft(obj);
  415.         inst->icr_top=_mtop(obj)+inst->font_height*cursor_y-inst->y_offset;
  416.         inst->icr_width=_mwidth(obj);
  417.         inst->icr_height=inst->font_height;
  418.         return TRUE;
  419.         }
  420.     else{ /* Ctrl chars (return del etc) */
  421.         if(ascii==13){ /* Return */
  422.             LONG len;
  423.             for(currentpos=inst->end_text,tpos=inst->end_text+1;currentpos>=textpos;*tpos--=*currentpos--);
  424.  
  425.             *++currentpos='\n';
  426.  
  427.             inst->icr_ncy=cursor_y+1;
  428.             inst->icr_ncx=0;
  429.             inst->lines++;
  430.  
  431.             inst->text_size++;
  432.  
  433.             len=inst->longest_line;
  434.             if((inst->text_size+10)>inst->alloced_size){ /* Exceeding buffer */
  435.                 SetText(inst,inst->text);
  436.                 ParseText(inst);
  437.                 }
  438.             else
  439.                 ParseText(inst);
  440.  
  441.             if(len>inst->longest_line)
  442.                 set(inst->HBar,MUIA_Prop_Entries,inst->longest_line*inst->font_width);
  443.             set(inst->VBar,MUIA_Prop_Entries,inst->lines*inst->font_height);
  444.  
  445.             inst->icr_left=_mleft(obj);
  446.             inst->icr_top=_mtop(obj);
  447.             inst->icr_width=_mwidth(obj);
  448.             inst->icr_height=_mheight(obj);
  449.             return TRUE;
  450.             }
  451.         else if(ascii==8){ /* Backspace */
  452.             if(cursor_x>0){
  453.                 inst->icr_ncx=cursor_x-1;
  454.                 textpos--;
  455.                 ascii=127;
  456.                 }
  457.             else if(cursor_y>0){
  458.                 textpos--;
  459.                 ascii=127;
  460.                 inst->icr_ncx=(LONG)inst->linearray[cursor_y]-(LONG)inst->linearray[cursor_y-1]-1;
  461.                 inst->icr_ncy=cursor_y-1;
  462.                 }
  463.             }
  464.         if(ascii==127){ /* Delete  (or a modified Backspace) */ 
  465.             LONG len;
  466.             if(*textpos!='\n'){ /* If _not_ deleting a \n */
  467.                 for(currentpos=textpos,tpos=currentpos+1;currentpos<inst->end_text;*currentpos++=*tpos++);
  468.                 for(i=cursor_y+1;lines[i];i++)
  469.                     lines[i]--;
  470.                 len=LineLength(inst->linearray[cursor_y])+1;
  471.  
  472.                 if((len+1)==inst->longest_line){
  473.                     len=LongestLine(inst)+1;
  474.                     if(len<inst->longest_line){
  475.                         inst->longest_line=len;
  476.                         set(inst->HBar,MUIA_Prop_Entries,inst->longest_line*inst->font_width);
  477.                         }
  478.                     }
  479.  
  480.                 inst->icr_left=_mleft(obj);
  481.                 inst->icr_top=_mtop(obj)+inst->font_height*cursor_y-inst->y_offset;
  482.                 inst->icr_width=_mwidth(obj);
  483.                 inst->icr_height=inst->font_height;
  484.  
  485.                 return TRUE;
  486.                 }
  487.             else{ /* If deleting a \n */
  488.                 for(currentpos=textpos,tpos=currentpos+1;currentpos<inst->end_text;*currentpos++=*tpos++);
  489.                 ParseText(inst);
  490.                 set(inst->VBar,MUIA_Prop_Entries,inst->lines*inst->font_height);
  491.                 inst->icr_left=_mleft(obj);
  492.                 inst->icr_top=_mtop(obj);
  493.                 inst->icr_width=_mwidth(obj);
  494.                 inst->icr_height=_mheight(obj);
  495.                 return TRUE;
  496.                 }
  497.             }
  498.         }
  499.     return FALSE;
  500. }
  501.  
  502. BOOL HandleSpecialKeys(struct TextFieldClData *inst,long key)
  503. {
  504. /*
  505.                     case 0x3E: /* Keypad 8 (up) */
  506.                     case 0x1E: /* Keypad 2 (down) */
  507.                     case 0x2D: /* Keypad 4 (left) */
  508.                     case 0x2F: /* Keypad 6 (right) */
  509.                     case 0x1F: /* Keypad 3 (PgDn) */
  510.                     case (0x1E | HIKEY_SHIFT): /* Shift Keypad 2 (down) */
  511.                     case (CURSORDOWN | HIKEY_SHIFT):
  512.                     case 0x40: /* Space */
  513.                     case 0x3F: /* Keypad 9 (PgUp) */
  514.                     case (0x3E | HIKEY_SHIFT): /* Shift Keypad 8 (up) */
  515.                     case (CURSORUP | HIKEY_SHIFT):
  516.                     case 0x41: /* Backspace */
  517.                     case (CURSORLEFT | HIKEY_SHIFT):
  518.                     case (0x2D | HIKEY_SHIFT): /* Shift Keypad 4 (left) */
  519.                     case (0x2F | HIKEY_SHIFT): /* Shift Keypad 6 (right) */
  520.                     case (CURSORRIGHT | HIKEY_SHIFT):
  521.                     case 0x3D: /* Keypad 7 (Home) */
  522.                     case (0x3E | HIKEY_CTRL): /* Ctrl Keypad 8 (up) */
  523.                     case (CURSORUP | HIKEY_CTRL):
  524.                     case 0x1D: /* Keypad 1 (End) */
  525.                     case (0x1E | HIKEY_CTRL): /* Ctrl Keypad 2 (down) */
  526.                     case (CURSORDOWN | HIKEY_CTRL):
  527.                     case (0x2D | HIKEY_CTRL): /* Ctrl Keypad 4 (left) */
  528.                     case (CURSORLEFT | HIKEY_CTRL):
  529.                     case (0x2F | HIKEY_CTRL): /* Ctrl Keypad 6 (right) */
  530.                     case (CURSORRIGHT | HIKEY_CTRL):
  531. */
  532.  
  533.     switch(key){
  534.         case CURSORLEFT:
  535.             if(inst->cursor_x>0){
  536.                 inst->icr_ncx=inst->cursor_x-1;
  537.                 inst->icr_ncy=inst->cursor_y;
  538.                 }
  539.             else if(inst->cursor_y>0){
  540.                 inst->icr_ncx=(LONG)inst->linearray[inst->cursor_y]-(LONG)inst->linearray[inst->cursor_y-1]-1;
  541.                 inst->icr_ncy=inst->cursor_y-1;
  542.                 }
  543.             return TRUE;
  544.             break;
  545.         case CURSORRIGHT:{
  546.             char ch= *(inst->linearray[inst->cursor_y]+inst->cursor_x);
  547.             if(ch=='\n'){
  548.                 inst->icr_ncy=inst->cursor_y+1;
  549.                 inst->icr_ncx=0;
  550.                 return TRUE;
  551.                 }
  552.             else if(ch==0);
  553.             else{
  554.                 inst->icr_ncy=inst->cursor_y;
  555.                 inst->icr_ncx=inst->cursor_x+1;
  556.                 return TRUE;
  557.                 }
  558.             }
  559.             break;
  560.         case CURSORUP:
  561.             if(inst->cursor_y>0){
  562.                 LONG len;
  563.                 inst->icr_ncy=inst->cursor_y-1;
  564.                 len=LineLength(inst->linearray[inst->icr_ncy]);
  565.                 if (len<inst->cursor_x) inst->icr_ncx=len;
  566.                 else inst->icr_ncx=inst->cursor_x;
  567.                 return TRUE;
  568.             }
  569.             break;
  570.         case CURSORDOWN:
  571.             if(inst->linearray[inst->cursor_y+1]){
  572.                 LONG len;
  573.                 inst->icr_ncy=inst->cursor_y+1;
  574.                 len=LineLength(inst->linearray[inst->icr_ncy]);
  575.                 if (len<inst->cursor_x) inst->icr_ncx=len;
  576.                 else inst->icr_ncx=inst->cursor_x;
  577.                 return TRUE;
  578.             }
  579.             break;
  580.         case (CURSORDOWN | HIKEY_SHIFT):{
  581.             LONG len;
  582.             inst->icr_ncy=inst->cursor_y+(inst->visible_lines*3)/4;
  583.             if(inst->icr_ncy>=inst->lines)
  584.                 inst->icr_ncy=inst->lines-1;
  585.  
  586.             len=LineLength(inst->linearray[inst->icr_ncy]);
  587.                 if (len<inst->cursor_x) inst->icr_ncx=len;
  588.                 else inst->icr_ncx=inst->cursor_x;
  589.  
  590.             return TRUE;}
  591.             break;
  592.         case (CURSORUP | HIKEY_SHIFT):{
  593.             LONG len;
  594.             inst->icr_ncy=inst->cursor_y-(inst->visible_lines*3)/4;
  595.             if(inst->icr_ncy<0) inst->icr_ncy=0;
  596.  
  597.             len=LineLength(inst->linearray[inst->icr_ncy]);
  598.                 if (len<inst->cursor_x) inst->icr_ncx=len;
  599.                 else inst->icr_ncx=inst->cursor_x;
  600.             return TRUE;}
  601.             break;
  602.         case (CURSORLEFT | HIKEY_SHIFT):
  603.             inst->icr_ncx=0;
  604.             inst->icr_ncy=inst->cursor_y;
  605.             return TRUE;
  606.             break;
  607.         case (CURSORRIGHT | HIKEY_SHIFT):
  608.             inst->icr_ncx=LineLength(inst->linearray[inst->cursor_y]);
  609.             inst->icr_ncy=inst->cursor_y;
  610.             return TRUE;
  611.             break;
  612. /*        case (CURSORUP | HIKEY_CTRL):
  613.             inst->new_cursor_x=inst->cursor_x;
  614.             inst->new_cursor_y=0;
  615.             return TRUE;
  616.             break;
  617.         case (CURSORDOWN | HIKEY_CTRL):
  618.             inst->new_cursor_x=inst->cursor_x;
  619.             inst->new_cursor_y=inst->lines-1;
  620.             return TRUE;
  621.             break;
  622.         case (CURSORLEFT | HIKEY_CTRL):
  623.         case (CURSORRIGHT | HIKEY_CTRL):
  624.             break; */
  625.         }
  626.     return FALSE;
  627. }
  628.  
  629. /*
  630.  * TextEditField methods
  631.  */
  632.  
  633. static ULONG mTextEditFieldNew(struct IClass *cl,Object *obj,struct opSet *msg)
  634. {
  635.     struct TextEditFieldClData *inst;
  636.  
  637.     if (!(obj = (Object *)DoSuperMethodA(cl,obj,(Msg)msg)))
  638.         return(0);
  639.  
  640.     inst = INST_DATA(cl,obj);
  641.  
  642.     inst->VBar = ScrollbarObject, End;
  643.     inst->HBar = ScrollbarObject, MUIA_Group_Horiz, TRUE, End;
  644.     inst->Space =SimpleButton("E");
  645.  
  646.     inst->TextField = NewObject(TextFieldCl,NULL,
  647.                 TextFrame,
  648.                 MUIA_Background, MUII_TextBack,
  649.                 MUIA_Font,MUIV_Font_Fixed,
  650.                 MUIA_TEF_VBar,inst->VBar,
  651.                 MUIA_TEF_HBar,inst->HBar,
  652.                 MUIA_TEF_Parent,obj,
  653.                 TAG_MORE,((struct opSet *)msg)->ops_AttrList,
  654.                 TAG_DONE);
  655.  
  656.     if (!inst->TextField || !inst->VBar || !inst->HBar || !inst->Space)
  657.     {
  658.         if(inst->TextField)
  659.             MUI_DisposeObject(inst->TextField);
  660.         if(inst->VBar)
  661.             MUI_DisposeObject(inst->VBar);
  662.         if(inst->HBar)
  663.             MUI_DisposeObject(inst->HBar);
  664.         if(inst->Space)
  665.             MUI_DisposeObject(inst->Space);
  666.         CoerceMethod(cl,obj,OM_DISPOSE);
  667.         return(0);
  668.     }
  669.  
  670.     DoMethod(inst->VBar,MUIM_Notify,MUIA_Prop_First,MUIV_EveryTime,inst->TextField,3,MUIM_Set,MUIA_TEF_FirstY,MUIV_TriggerValue);
  671.     DoMethod(inst->HBar,MUIM_Notify,MUIA_Prop_First,MUIV_EveryTime,inst->TextField,3,MUIM_Set,MUIA_TEF_FirstX,MUIV_TriggerValue);
  672.     DoMethod(inst->TextField,MUIM_Notify,MUIA_TEF_FirstY,MUIV_EveryTime,inst->VBar,3,MUIM_Set,MUIA_Prop_First,MUIV_TriggerValue);
  673.     DoMethod(inst->TextField,MUIM_Notify,MUIA_TEF_FirstX,MUIV_EveryTime,inst->HBar,3,MUIM_Set,MUIA_Prop_First,MUIV_TriggerValue);
  674.     DoMethod(inst->Space,MUIM_Notify,MUIA_Pressed,FALSE,inst->Space,4,MUIM_CallHook,&EditHook,TextFieldCl,inst->TextField);
  675.  
  676.     DoMethod(obj,OM_ADDMEMBER,inst->TextField);
  677.     DoMethod(obj,OM_ADDMEMBER,inst->VBar);
  678.     DoMethod(obj,OM_ADDMEMBER,inst->HBar);
  679.     DoMethod(obj,OM_ADDMEMBER,inst->Space);
  680.     set(obj,MUIA_Group_Columns,2);
  681.     set(obj,MUIA_Group_Spacing,1);
  682.  
  683.  
  684.  
  685.     msg->MethodID = OM_SET;     /* a little trick to parse taglist */
  686.     DoMethodA(obj, (Msg) msg);         /* and set attributes with OM_SET. */
  687.     msg->MethodID = OM_NEW;     /* restore method id           */
  688.  
  689.     return((ULONG)obj);
  690. }
  691.  
  692. static ULONG mTextEditFieldDispose(struct IClass *cl,Object *obj,Msg msg)
  693. {
  694.     return(DoSuperMethodA(cl,obj,msg));
  695. }
  696.  
  697. static ULONG mTextEditFieldShow(struct IClass *cl,Object *obj,Msg msg)
  698. {
  699.     ULONG res;
  700.     struct TextEditFieldClData *inst=INST_DATA(cl,obj);
  701.     struct TextFieldClData *inst2=INST_DATA(TextFieldCl,inst->TextField);
  702.  
  703.     DoSuperMethodA(cl,obj,(Msg)msg);
  704. //    if(DoSuperMethodA(cl,obj,(Msg)msg)){
  705. /*        SetAttrs(inst->TextField,MUIA_TEF_ParentL,_mleft(obj),
  706.                                 MUIA_TEF_ParentR,_mright(obj),
  707.                                 MUIA_TEF_ParentT,_mtop(obj),
  708.                                 MUIA_TEF_ParentB,_mbottom(obj),TAG_DONE); */
  709.         inst2->p_l=_mleft(obj); /* Faster, but uglier! */
  710.         inst2->p_r=_mright(obj);
  711.         inst2->p_t=_mtop(obj);
  712.         inst2->p_b=_mbottom(obj);
  713.  
  714. //        }
  715. //    return res;
  716.     return TRUE;
  717. }
  718.  
  719. static ULONG mTextEditFieldSet(struct IClass *cl,Object *obj,struct opSet *msg)
  720. {
  721.     struct Data *inst = INST_DATA(cl,obj);
  722.     struct TagItem *tags,*tag;
  723.  
  724.     for (tags=msg->ops_AttrList;tag=NextTagItem(&tags);)
  725.     {
  726.         switch (tag->ti_Tag)
  727.         {
  728.             case 0: break;
  729.         }
  730.     }
  731.     return(DoSuperMethodA(cl,obj,(Msg)msg));
  732. }
  733.  
  734.  
  735. static ULONG mTextEditFieldGet(struct IClass *cl,Object *obj,Msg msg)
  736. {
  737. //    struct TextFieldClData *inst = INST_DATA(cl,obj);
  738.  
  739.     switch (((struct opGet *)msg)->opg_AttrID)
  740.     {
  741.         case 0: break;
  742.     }
  743.  
  744.     return(DoSuperMethodA(cl,obj,msg));
  745. }
  746.  
  747.  
  748. static __saveds __asm ULONG TextEditFieldDispatcher(register __a0 struct IClass *cl,
  749.                    register __a2 Object *obj,
  750.                    register __a1 Msg msg)
  751. {
  752.     switch (msg->MethodID)
  753.     {
  754.         case OM_NEW            : return(mTextEditFieldNew     (cl,obj,(APTR)msg));
  755.         case OM_DISPOSE     : return(mTextEditFieldDispose (cl,obj,(APTR)msg));
  756.         case OM_GET            : return(mTextEditFieldGet     (cl,obj,(APTR)msg));
  757.         case OM_SET            : return(mTextEditFieldSet     (cl,obj,(APTR)msg));
  758.         case MUIM_Show        : return(mTextEditFieldShow    (cl,obj,(APTR)msg));
  759.         case MUIM_Notify    : if(((struct MUIP_Notify *)msg)->TrigAttr==MUIA_TEF_Active) return DoMethodA(((struct TextEditFieldClData *)INST_DATA(cl,obj))->TextField,msg);
  760.                                 else return DoSuperMethodA(cl,obj,msg);
  761.     }
  762.  
  763.     return(DoSuperMethodA(cl,obj,msg));
  764. }
  765.  
  766. /*
  767.  * The text area class
  768.  */
  769.  
  770. static ULONG mTextFieldNew(struct IClass *cl,Object *obj,struct opSet *msg)
  771. {
  772.     struct TextFieldClData *inst;
  773.     struct TagItem *tags,*tag;
  774.  
  775.     if (!(obj = (Object *)DoSuperMethodA(cl,obj,(Msg)msg)))
  776.         return(0);
  777.  
  778.     inst = INST_DATA(cl,obj);
  779.  
  780.     inst->icr_top=0x80000000;
  781.  
  782.     for (tags=msg->ops_AttrList;tag=NextTagItem(&tags);)
  783.     {
  784.         switch (tag->ti_Tag)
  785.         {
  786.             case MUIA_TEF_VBar:   inst->VBar=(Object *)tag->ti_Data; break;
  787.             case MUIA_TEF_HBar:   inst->HBar=(Object *)tag->ti_Data; break;
  788.             case MUIA_TEF_Width:  inst->width=tag->ti_Data; tag->ti_Tag=TAG_IGNORE; break;
  789.             case MUIA_TEF_Height: inst->height=tag->ti_Data; tag->ti_Tag=TAG_IGNORE; break;
  790.             case MUIA_TEF_Active: inst->active=tag->ti_Data; tag->ti_Tag=TAG_IGNORE; break;
  791.             case MUIA_TEF_Text:   SetText(inst,(char *)tag->ti_Data); tag->ti_Tag=TAG_IGNORE; break;
  792.             case MUIA_TEF_Parent: inst->parent=(Object *)tag->ti_Data; tag->ti_Tag=TAG_IGNORE; break;
  793.         }
  794.     }
  795.  
  796. //    kprintf("Text: %s\n",inst->text);
  797.  
  798.     ParseText(inst);
  799.  
  800.     return((ULONG)obj);
  801. }
  802.  
  803. static ULONG mTextFieldDispose(struct IClass *cl,Object *obj,Msg msg)
  804. {
  805.     struct TextFieldClData *inst=INST_DATA(cl,obj);
  806.  
  807.     if(inst->notifying){
  808.         EndNotify(&inst->FileNotify);
  809.         if(inst->FileName){
  810.             DeleteFile(inst->FileName);
  811.             free(inst->FileName);
  812.             }
  813.         }
  814.     if(inst->text)
  815.         FreeVec(inst->text);
  816.     if(inst->linearray)
  817.         FreeVec(inst->linearray);
  818.     return(DoSuperMethodA(cl,obj,msg));
  819. }
  820.  
  821.  
  822. static ULONG mTextFieldSet(struct IClass *cl,Object *obj,struct opSet *msg)
  823. {
  824.     struct TextFieldClData *inst = INST_DATA(cl,obj);
  825.     struct TagItem *tags,*tag;
  826.  
  827.     for (tags=msg->ops_AttrList;tag=NextTagItem(&tags);)
  828.     {
  829.         switch (tag->ti_Tag)
  830.         {
  831.             case MUIA_TEF_VBar:   inst->VBar=(Object *)tag->ti_Data; break;
  832.             case MUIA_TEF_HBar:   inst->HBar=(Object *)tag->ti_Data; break;
  833. /*            case MUIA_TEF_FirstX: inst->new_x_offset=tag->ti_Data; inst->new_dir=1; MUI_Redraw(obj,MADF_DRAWUPDATE); break;
  834.             case MUIA_TEF_FirstY: inst->new_y_offset=tag->ti_Data; inst->new_dir=2; MUI_Redraw(obj,MADF_DRAWUPDATE); break; */
  835.  
  836.             case MUIA_TEF_FirstX: inst->x_offset=tag->ti_Data; 
  837.                                     inst->icr_left=_mleft(obj);
  838.                                     inst->icr_top=_mtop(obj);
  839.                                     inst->icr_width=_mwidth(obj);
  840.                                     inst->icr_height=_mheight(obj);
  841.                                     ClipCursor2(inst,obj);
  842.                                     MUI_Redraw(obj,MADF_DRAWUPDATE);
  843.                                     break;
  844.             case MUIA_TEF_FirstY: inst->y_offset=tag->ti_Data;
  845.                                     inst->icr_left=_mleft(obj);
  846.                                     inst->icr_top=_mtop(obj);
  847.                                     inst->icr_width=_mwidth(obj);
  848.                                         inst->icr_height=_mheight(obj);
  849.                                     ClipCursor2(inst,obj);
  850.                                     MUI_Redraw(obj,MADF_DRAWUPDATE);
  851.                                     break;
  852.  
  853.             case MUIA_TEF_Width:  inst->width=tag->ti_Data; break;
  854.             case MUIA_TEF_Height: inst->height=tag->ti_Data; break;
  855.             case MUIA_TEF_Active: inst->go_active=tag->ti_Data+1; MUI_Redraw(obj,MADF_DRAWUPDATE); break;
  856.             case MUIA_TEF_Text:   SetText(inst,(char *)tag->ti_Data);
  857.                                     ParseText(inst);
  858.  
  859.                                     set(inst->VBar,MUIA_Prop_Entries,inst->lines*inst->font_height);
  860.                                     set(inst->VBar,MUIA_Prop_Visible,_mheight(obj));
  861.                                     set(inst->HBar,MUIA_Prop_Entries,inst->longest_line*inst->font_width);
  862.                                     set(inst->HBar,MUIA_Prop_Visible,_width(obj));
  863.  
  864.                                     MUI_Redraw(obj,MADF_DRAWOBJECT);
  865.                                     break;
  866.  
  867.  
  868.  
  869.  
  870.             case MUIA_TEF_ParentL: inst->p_l=tag->ti_Data; break;
  871.             case MUIA_TEF_ParentR: inst->p_r=tag->ti_Data; break;
  872.             case MUIA_TEF_ParentT: inst->p_t=tag->ti_Data; break;
  873.             case MUIA_TEF_ParentB: inst->p_b=tag->ti_Data; break;
  874.         }
  875.     }
  876.     return(DoSuperMethodA(cl,obj,(Msg)msg));
  877. }
  878.  
  879.  
  880. static ULONG mTextFieldGet(struct IClass *cl,Object *obj,Msg msg)
  881. {
  882.     struct TextFieldClData *inst = INST_DATA(cl,obj);
  883.     
  884.     switch (((struct opGet *)msg)->opg_AttrID)
  885.     {
  886.         case MUIA_TEF_Text:     *(((struct opGet *)msg)->opg_Storage) = (ULONG)(inst->text); break;
  887.         case MUIA_TEF_Active:    *(((struct opGet *)msg)->opg_Storage) = (ULONG)(inst->active); break;
  888.     }
  889.  
  890.     return(DoSuperMethodA(cl,obj,msg));
  891. }
  892.  
  893. static __saveds ULONG TextFieldAskMinMax(struct IClass *cl,Object *obj,struct MUIP_AskMinMax *msg)
  894. {
  895.     struct TextFieldClData *inst = INST_DATA(cl,obj);
  896.     DoSuperMethodA(cl,obj,(Msg)msg);
  897.  
  898.     msg->MinMaxInfo->MinWidth  += 16;
  899.     msg->MinMaxInfo->DefWidth  += inst->width*inst->font_width;
  900.     msg->MinMaxInfo->MaxWidth  += inst->width*inst->font_width;
  901. //    msg->MinMaxInfo->MaxWidth  += MUI_MAXMAX;
  902.  
  903.     msg->MinMaxInfo->MinHeight += 16;
  904.     msg->MinMaxInfo->DefHeight += inst->height*inst->font_height;
  905.     msg->MinMaxInfo->MaxHeight += inst->height*inst->font_height;
  906. //    msg->MinMaxInfo->MaxHeight += MUI_MAXMAX;
  907.  
  908. //    kprintf("Height :%ld\n",inst->height);
  909.  
  910.     return(0);
  911. }
  912.  
  913. static __saveds ULONG TextFieldDraw(struct IClass *cl,Object *obj,struct MUIP_Draw *msg)
  914. {
  915.     struct TextFieldClData *inst=INST_DATA(cl,obj);
  916.     LONG delta,tmp;
  917.     DoSuperMethodA(cl,obj,(Msg)msg);
  918.  
  919.     if (msg->flags & MADF_DRAWOBJECT){
  920. //        HideCursor(inst,obj); /* The cursor is erased after DoSuperMethodA */
  921.         RefreshTextArea(_window(obj),INST_DATA(cl,obj),obj,inst->x_offset,inst->y_offset,_mleft(obj),_mtop(obj),_mwidth(obj),_mheight(obj));
  922.         ShowCursor(inst,obj);
  923.         }
  924. //    if (MADF_DRAWUPDATE){
  925. //        if(!(inst->cursor_state&2))
  926. //            HideCursor(inst,obj);
  927. //        }
  928.     if (msg->flags & MADF_DRAWUPDATE){
  929.         HideCursor(inst,obj);
  930.  
  931. //        kprintf("Offset x: %ld y: %ld Top: %ld Left: %ld Width: %ld Height: %ld\n",inst->x_offset,inst->y_offset,inst->icr_left,inst->icr_top,inst->icr_width,inst->icr_height);
  932.  
  933.         if(inst->icr_top!=0x80000000){
  934.             RefreshTextArea(_window(obj),INST_DATA(cl,obj),obj,inst->x_offset+inst->icr_left-_mleft(obj),inst->y_offset+inst->icr_top-_mtop(obj),inst->icr_left,inst->icr_top,inst->icr_width,inst->icr_height);
  935.             inst->cursor_x=inst->icr_ncx;
  936.             inst->cursor_y=inst->icr_ncy;
  937.  
  938.             inst->s_cursor_x=inst->cursor_x*inst->font_width-inst->x_offset;
  939.             inst->s_cursor_y=inst->cursor_y*inst->font_height-inst->y_offset;
  940.  
  941.             inst->icr_top=0x80000000;
  942.             }
  943.         else
  944.             {
  945.             inst->cursor_x=inst->icr_ncx;
  946.             inst->cursor_y=inst->icr_ncy;
  947.  
  948.             inst->s_cursor_x=inst->cursor_x*inst->font_width-inst->x_offset;
  949.             inst->s_cursor_y=inst->cursor_y*inst->font_height-inst->y_offset;
  950.             }
  951.  
  952.  
  953.  
  954.         inst->active=inst->go_active-1;
  955.  
  956. /*        if (msg->flags & MADF_DRAWOBJECT || msg->flags & MADF_DRAWUPDATE){
  957.             ShowCursor(inst,obj);
  958. //            ShowCursor(inst,obj,TRUE);
  959.             } */
  960.         ShowCursor(inst,obj);
  961.  
  962.  
  963.  
  964. /*        if(inst->new_dir==1){
  965.             delta=inst->new_x_offset-inst->x_offset;
  966.             if(abs(delta)<_mwidth(obj))
  967.                 ScrollRaster(_rp(obj),delta,0,_mleft(obj),_mtop(obj),_mright(obj),_mbottom(obj));
  968.             else
  969.                 delta=-_mwidth(obj);
  970.             inst->x_offset=inst->new_x_offset;
  971.  
  972.             if(delta<0)
  973.                 RefreshTextArea(_window(obj),INST_DATA(cl,obj),obj,inst->x_offset,inst->y_offset,_mleft(obj),_mtop(obj),-delta,_mheight(obj));
  974.             else            
  975.                 RefreshTextArea(_window(obj),INST_DATA(cl,obj),obj,inst->x_offset+_mwidth(obj)-delta,inst->y_offset,_mright(obj)-delta+1,_mtop(obj),delta,_mheight(obj));
  976.             inst->new_dir=0;
  977.             }
  978.         else if(inst->new_dir==2){
  979.             delta=inst->new_y_offset-inst->y_offset;
  980.             if(abs(delta)<_mheight(obj))
  981.                 ScrollRaster(_rp(obj),0,delta,_mleft(obj),_mtop(obj),_mright(obj),_mbottom(obj));
  982.             else
  983.                 delta=-_mheight(obj);
  984.             inst->y_offset=inst->new_y_offset;
  985.             if(delta<0)
  986.                 RefreshTextArea(_window(obj),INST_DATA(cl,obj),obj,inst->x_offset,inst->y_offset,_mleft(obj),_mtop(obj),_mwidth(obj),-delta);
  987.             else            
  988.                 RefreshTextArea(_window(obj),INST_DATA(cl,obj),obj,inst->x_offset,inst->y_offset+_mheight(obj)-delta,_mleft(obj),_mbottom(obj)-delta+1,_mwidth(obj),delta);
  989.             inst->new_dir=0;
  990.             } */
  991.  
  992. /*        if(inst->new_cursor_x>=0){
  993.             LONG len;
  994.             if(inst->new_cursor_y>=inst->lines)
  995.                 inst->new_cursor_y=inst->lines-1;
  996.             if(inst->new_cursor_x>(len=LineLength(inst->linearray[inst->new_cursor_y])))
  997.                 inst->new_cursor_x=len;
  998.  
  999.             inst->cursor_x=inst->new_cursor_x;
  1000.             inst->cursor_y=inst->new_cursor_y;
  1001.         
  1002.             inst->new_cursor_x=-1;
  1003.         } */
  1004.     }
  1005.  
  1006.     return 0;
  1007. }
  1008.  
  1009. static ULONG TextFieldShow(struct IClass *cl,Object *obj,struct MUIP_Show *msg)
  1010. {
  1011.     struct TextFieldClData *inst=INST_DATA(cl,obj);
  1012.     DoSuperMethodA(cl,obj,(Msg)msg);
  1013.  
  1014. //    kprintf("TextField: Show VBar %08lx\n",inst->VBar);
  1015.  
  1016.     set(inst->VBar,MUIA_Prop_Entries,inst->lines*inst->font_height);
  1017.     set(inst->VBar,MUIA_Prop_Visible,_mheight(obj));
  1018.     set(inst->HBar,MUIA_Prop_Entries,inst->longest_line*inst->font_width);
  1019.     set(inst->HBar,MUIA_Prop_Visible,_mwidth(obj));
  1020.  
  1021.     inst->visible_lines=_mheight(obj)/inst->font_height;
  1022.     inst->visible_columns=_mwidth(obj)/inst->font_width;
  1023.  
  1024.     return TRUE;
  1025. }
  1026.  
  1027. static __saveds ULONG TextFieldSetup(struct IClass *cl,Object *obj,struct MUIP_Setup *msg){
  1028.     struct TextFieldClData *inst=INST_DATA(cl,obj);
  1029.  
  1030.     if (!(DoSuperMethodA(cl,obj,(Msg)msg)))
  1031.         return(FALSE);
  1032.     
  1033.     inst->font_width  = _font(obj)->tf_XSize;
  1034.     inst->font_height = _font(obj)->tf_YSize;
  1035.  
  1036.     set(inst->VBar,MUIA_Prop_DeltaFactor,inst->font_height);
  1037.     set(inst->HBar,MUIA_Prop_DeltaFactor,inst->font_width);
  1038.  
  1039. //    kprintf("Font width: %ld height: %ld\n",inst->font_width,inst->font_height);
  1040.  
  1041.     MUI_RequestIDCMP(obj,IDCMP_MOUSEBUTTONS|IDCMP_RAWKEY|IDCMP_VANILLAKEY);
  1042.     return TRUE;
  1043. }
  1044.  
  1045. static __saveds ULONG TextFieldCleanup(struct IClass *cl,Object *obj,struct MUIP_Setup *msg){
  1046.     MUI_RejectIDCMP(obj,IDCMP_MOUSEBUTTONS|IDCMP_RAWKEY|IDCMP_VANILLAKEY);
  1047.     return(DoSuperMethodA(cl,obj,(Msg)msg));
  1048. }
  1049.  
  1050. __saveds ULONG TextFieldHandleInput(struct IClass *cl,Object *obj,struct MUIP_HandleInput *msg)
  1051. {
  1052.     #define _between(a,x,b) ((x)>=(a) && (x)<=(b))
  1053.     #define _isinobject(x,y) (_between(_mleft(obj),(x),_mright(obj)) && _between(_mtop(obj),(y),_mbottom(obj)))
  1054.     #define _isinarea(x,y) (_between(inst->p_l,(x),inst->p_r) && _between(inst->p_t,(y),inst->p_b))
  1055.  
  1056.     struct TextFieldClData *inst = INST_DATA(cl,obj);
  1057.  
  1058.     DoSuperMethodA(cl,obj,(Msg)obj);
  1059.  
  1060.     if (msg->imsg)
  1061.     {
  1062.         switch (msg->imsg->Class)
  1063.         {
  1064.             case IDCMP_RAWKEY:
  1065.                 if(inst->active){
  1066.                     long key;
  1067.                     key=msg->imsg->Code;
  1068.                     if(msg->imsg->Qualifier & IEQUALIFIER_SHIFT)
  1069.                         key |= HIKEY_SHIFT;
  1070.                     if(msg->imsg->Qualifier & IEQUALIFIER_ALT)
  1071.                         key |= HIKEY_ALT;
  1072.                     if(msg->imsg->Qualifier & IEQUALIFIER_CONTROL)
  1073.                         key |= HIKEY_CTRL;
  1074.                     if(HandleSpecialKeys(inst,key)){
  1075.                         ClipCursor(inst,obj);
  1076.                         MUI_Redraw(obj,MADF_DRAWUPDATE);
  1077.                         }
  1078.                     }
  1079.                 break;
  1080.             case IDCMP_VANILLAKEY:
  1081.                 if(inst->active){
  1082.                     if(InsertChar(obj,inst,msg->imsg->Code)){
  1083.                         ClipCursor(inst,obj);
  1084.                         MUI_Redraw(obj,MADF_DRAWUPDATE);
  1085.                         }
  1086.                     }
  1087.                 break;
  1088.             case IDCMP_MOUSEBUTTONS:
  1089.                 if (msg->imsg->Code==SELECTDOWN){
  1090.                     LONG i;
  1091.                     if (_isinarea(msg->imsg->MouseX,msg->imsg->MouseY)){
  1092.                         if(!inst->active) set(inst->parent,MUIA_TEF_Active,TRUE);
  1093.                         if(_isinobject(msg->imsg->MouseX,msg->imsg->MouseY)){
  1094.                             inst->icr_ncx=(msg->imsg->MouseX-_mleft(obj)+inst->x_offset) / inst->font_width;
  1095.                             inst->icr_ncy=(msg->imsg->MouseY-_mtop(obj)+inst->y_offset) / inst->font_height;
  1096.                             MUI_RequestIDCMP(obj,IDCMP_MOUSEMOVE);
  1097.                             if(inst->icr_ncy>=inst->lines)
  1098.                                 inst->icr_ncy=inst->lines-1;
  1099.                             if((i=LineLength(inst->linearray[inst->icr_ncy]))<inst->icr_ncx)
  1100.                                 inst->icr_ncx=i;
  1101.                             ClipCursor(inst,obj);
  1102.                             MUI_Redraw(obj,MADF_DRAWUPDATE);
  1103.                             }
  1104.                         }
  1105.                         else if(inst->active) set(inst->parent,MUIA_TEF_Active,FALSE);
  1106.                     }
  1107.                 else if (msg->imsg->Code==SELECTUP)
  1108.                     MUI_RejectIDCMP(obj,IDCMP_MOUSEMOVE);
  1109.                 break;
  1110.  
  1111.             case IDCMP_MOUSEMOVE:
  1112.                 if (_isinobject(msg->imsg->MouseX,msg->imsg->MouseY)){
  1113.                     LONG i;
  1114.                     inst->icr_ncx=(msg->imsg->MouseX-_mleft(obj)+inst->x_offset) / inst->font_width;
  1115.                     inst->icr_ncy=(msg->imsg->MouseY-_mtop(obj)+inst->y_offset) / inst->font_height;
  1116.                     if(inst->icr_ncy>=inst->lines)
  1117.                         inst->icr_ncy=inst->lines-1;
  1118.                     if((i=LineLength(inst->linearray[inst->icr_ncy]))<inst->icr_ncx)
  1119.                         inst->icr_ncx=i;
  1120.                     ClipCursor(inst,obj);
  1121.                     MUI_Redraw(obj,MADF_DRAWUPDATE);
  1122.                     }
  1123.             break;
  1124.         }
  1125.     }
  1126.     return(0);
  1127. }
  1128.  
  1129. __saveds ULONG TextFieldFileChange(struct IClass *cl,Object *obj,struct MUIP_HandleInput *msg)
  1130. {
  1131.     struct TextFieldClData *inst=INST_DATA(cl,obj);
  1132.     APTR fh;
  1133.     APTR mem;
  1134.     ULONG size;
  1135. //    kprintf("Getting filenotification\n");
  1136.     if(inst->FileName)
  1137.         if(fh=fopen(inst->FileName,"r")){
  1138.             fseek(fh,0,SEEK_END);
  1139.             size=ftell(fh);
  1140.             fseek(fh,0,SEEK_SET);
  1141.             mem=AllocVec(size+1,MEMF_CLEAR);
  1142.             fread(mem,1,size,fh);
  1143.             fclose(fh);
  1144.             SetText(inst,mem);
  1145.             ParseText(inst);
  1146.             FreeVec(mem);
  1147.  
  1148.             set(inst->VBar,MUIA_Prop_Entries,inst->lines*inst->font_height);
  1149.             set(inst->VBar,MUIA_Prop_Visible,_mheight(obj));
  1150.             set(inst->HBar,MUIA_Prop_Entries,inst->longest_line*inst->font_width);
  1151.             set(inst->HBar,MUIA_Prop_Visible,_width(obj));
  1152.  
  1153.             MUI_Redraw(obj,MADF_DRAWOBJECT);
  1154.             }
  1155.     return 0;
  1156. }
  1157.  
  1158. static __saveds __asm ULONG TextFieldDispatcher(register __a0 struct IClass *cl,
  1159.                    register __a2 Object *obj,
  1160.                    register __a1 Msg msg)
  1161. {
  1162.     switch (msg->MethodID)
  1163.     {
  1164.         case MUIM_HandleInput: return(TextFieldHandleInput(cl,obj,(APTR)msg));
  1165.         case OM_NEW             : return(mTextFieldNew       (cl,obj,(APTR)msg));
  1166.         case OM_DISPOSE      : return(mTextFieldDispose   (cl,obj,(APTR)msg));
  1167.         case OM_GET             : return(mTextFieldGet       (cl,obj,(APTR)msg));
  1168.         case OM_SET             : return(mTextFieldSet       (cl,obj,(APTR)msg));
  1169.         case MUIM_AskMinMax  : return(TextFieldAskMinMax  (cl,obj,(APTR)msg));
  1170.         case MUIM_Draw       : return(TextFieldDraw       (cl,obj,(APTR)msg));
  1171.         case MUIM_Show       : return(TextFieldShow       (cl,obj,(APTR)msg));
  1172.         case MUIM_Setup      : return(TextFieldSetup      (cl,obj,(APTR)msg));
  1173.         case MUIM_Cleanup    : return(TextFieldCleanup    (cl,obj,(APTR)msg));
  1174.         case MUIM_TEF_FileChange : return(TextFieldFileChange    (cl,obj,(APTR)msg));
  1175.     }
  1176.  
  1177.     return(DoSuperMethodA(cl,obj,msg));
  1178. }
  1179.  
  1180. Class *TextEditFieldClInit(void)
  1181. {
  1182.   APTR SuperClass;
  1183.   Class *cl;
  1184.  
  1185.   if (!(SuperClass = MUI_GetClass(MUIC_Group)))
  1186.     fail(NULL, "Superclass for TextEditField class not found.");
  1187.   if (!(cl = MakeClass(NULL, NULL, SuperClass, sizeof(struct TextEditFieldClData), 0)))
  1188.     {
  1189.       MUI_FreeClass(SuperClass);
  1190.       fail(NULL, "Failed to create TextEditField class.");
  1191.     }
  1192.   cl->cl_Dispatcher.h_Entry = (APTR)TextEditFieldDispatcher;
  1193.   cl->cl_Dispatcher.h_SubEntry = NULL;
  1194.   cl->cl_Dispatcher.h_Data = NULL;
  1195.  
  1196.   if (!(SuperClass = MUI_GetClass(MUIC_Area)))
  1197.    {
  1198.     fail(NULL, "Superclass for TextEditField class not found.");
  1199.    }
  1200.   if (!(TextFieldCl = MakeClass(NULL, NULL, SuperClass, sizeof(struct TextFieldClData), 0)))
  1201.     {
  1202.       MUI_FreeClass(SuperClass);
  1203.       FreeClass(cl);
  1204.       fail(NULL, "Failed to create TextEditField class.");
  1205.     }
  1206.   TextFieldCl->cl_Dispatcher.h_Entry = (APTR)TextFieldDispatcher;
  1207.   TextFieldCl->cl_Dispatcher.h_SubEntry = NULL;
  1208.   TextFieldCl->cl_Dispatcher.h_Data = NULL;
  1209.  
  1210.   return cl;
  1211. }
  1212.  
  1213. BOOL TextEditFieldClFree(Class *cl)
  1214. {
  1215.  FreeClass(TextFieldCl);
  1216.  FreeClass(cl);
  1217.  return 0L;
  1218. }
  1219.  
  1220. struct EditFuncMsg
  1221. {
  1222.     struct IClass *cl;
  1223.     Object *obj;
  1224. };
  1225.  
  1226.  
  1227. ULONG __saveds __asm EditFunc(register __a0 struct Hook *hook,
  1228.                register __a2 APTR          object,
  1229.                register __a1 struct EditFuncMsg *msg)
  1230. {
  1231.     char buffer[256],buffer2[256]="run ";
  1232.     APTR fh;
  1233.     long res;
  1234.  
  1235.     struct TextFieldClData *inst=INST_DATA(msg->cl,msg->obj);
  1236.  
  1237.     if(!inst->FileName){
  1238.         inst->FileName=malloc(128);
  1239.  
  1240.         do{
  1241.             sprintf(inst->FileName,"t:TextEditFieldTemp.%d",inst->FileNo);
  1242.             if(fh=fopen(inst->FileName,"r")){
  1243.                 fclose(fh);
  1244.                 inst->FileNo++;
  1245.                 }
  1246.             }while(fh);
  1247.         }
  1248.  
  1249.     if(fh=fopen(inst->FileName,"w")){
  1250.         fputs(inst->text,fh);
  1251.         fclose(fh);
  1252. //        kprintf("String %s\n",inst->text);
  1253.  
  1254.         if(!inst->notifying){
  1255.             memset(&inst->FileNotify,0,sizeof(struct NotifyRequest));
  1256.             inst->FileNotify.nr_Name=inst->FileName;
  1257.             inst->FileNotify.nr_UserData=(ULONG)msg->obj; /* So that main knows what to call */
  1258.             inst->FileNotify.nr_Flags=NRF_SEND_MESSAGE;
  1259.             inst->FileNotify.nr_stuff.nr_Msg.nr_Port=FileNotifyPort;
  1260.             res=StartNotify(&inst->FileNotify);
  1261. //            kprintf("Starting notify. Result %ld\n",res);
  1262.             inst->notifying=1;
  1263.             }
  1264.  
  1265.  
  1266.         GetVar("editor",(char *)&buffer,256,0);
  1267.         if(*buffer==0x0)
  1268.             strcpy(buffer,"c:ed");
  1269.         strcat(buffer2,buffer);
  1270.         strcat(buffer2," ");
  1271.         strcat(buffer2,inst->FileName);
  1272.  
  1273.         Execute(buffer2,NULL,NULL);
  1274.     }
  1275.     return TRUE;
  1276. }
  1277.