home *** CD-ROM | disk | FTP | other *** search
/ Dream 48 / Amiga_Dream_48.iso / Atari / c / windial.lzh / WINDDIAL / WINDDIAL.C < prev    next >
C/C++ Source or Header  |  1993-04-11  |  10KB  |  379 lines

  1. /* Verwalten von Dialogbäumen in Fenstern */
  2. /* Version 1.0 */
  3. /* Erweiterungen in Form von Tastaturshortcuts usw. sind nicht direkt
  4.    vorgesehen, die Abarbeitung erfolgt mittels Let 'em fly */
  5.  
  6. /*
  7.    Nutzung der Routinen in eigenen Programmen uneingeschränkt erlaubt,
  8.    Erweiterungen erwünscht, ich möchte allerdings in Form von Quelltext
  9.    oder zur Not Objektfiles diese auch nutzten können.
  10.  
  11.    von J. Starzynski und T. Baade
  12. */
  13.  
  14. #include <tos.h>
  15.  
  16. #include "ltmf_lib.h"
  17. #include "ltmf_lib.c"
  18.  
  19. #include "winddial.h"
  20.  
  21. /* Fenster wird Titelzeile, Move-Balken und Schlie₧knopf haben */
  22. #define PROPS (NAME|MOVER|CLOSER)
  23.  
  24. /*    initialisieren und zeichnen des Fensterrahmens */
  25. /*    erste 4 Parameter: wie form_center
  26.     wind :    Zeiger auf zu bearbeitende Window-Struktur
  27.     title:  Titel des Fensters
  28.     return:    im Fehlerfall !=0 , sonst 0
  29. */
  30. int form_wind(OBJECT *ptr,int *center_x,int *center_y,
  31.                 int *center_w,int *center_h,wi_data *wind,char *title)
  32. {
  33. /* Desktop-Koordinaten */
  34.     int x_desk,y_desk,w_desk,h_desk;
  35. /* Gesamtgrö₧e des Windows, Fehlerflag */
  36.     int x,y,w,h,error=0;
  37. /* Keine Ausgaben erlauben */
  38.     wind_update(BEG_UPDATE);
  39. /* Fensterstruktur initialisieren */
  40. /* 1.: mit Object-Baumadresse */
  41.     wind->obj=ptr;
  42. /* 2.: gemalt-flag null setzen */
  43.     wind->flags.drawed=0;
  44. /* 3.: nur eigenes Fenster toppen */
  45.     wind->flags.auto_top=0;
  46. /* 4.: let 'em fly nutzen */
  47.     wind->flags.ltmf=1;
  48. /* 5.: übergebene Clipp-Koordinaten in Struktur übernehmen */
  49.     wind->m=center_x;
  50.     wind->n=center_y;
  51.     wind->o=center_w;
  52.     wind->p=center_h;
  53. /* Desktop-Grö₧e holen */
  54.     wind_get(0,WF_WORKXYWH,&x_desk,&y_desk,&w_desk,&h_desk);
  55. /* Window kreieren */
  56.     wind->wi_handle=wind_create(PROPS,x_desk,y_desk,w_desk,h_desk);
  57. /* Fehler? */
  58.     if(wind->wi_handle<0)
  59.     {
  60.         error=-1;
  61.     }
  62.     else
  63.     {
  64. /* Gesamtgrö₧e des Fensters berechnen */
  65.         wind_calc(WC_BORDER,PROPS,
  66.                   *center_x,*center_y,*center_w,*center_h,&x,&y,&w,&h);
  67. /* Test, ob Fenste über linken oder oberen Deskrand hinausgeht */
  68. /* wenn ja, Korrektur der Koordinaten */
  69.         if(x<x_desk)
  70.         {
  71.             int xdiff=x_desk-x;
  72.             x=xdiff;
  73.             ptr->ob_x+=xdiff;
  74.             *center_x+=xdiff;
  75.         }
  76.         if(y<y_desk)
  77.         {
  78.             int ydiff=y_desk-y;
  79.             y=ydiff;
  80.             ptr->ob_y+=ydiff;
  81.             *center_y+=ydiff;
  82.         }
  83. /* Titel eintragen */
  84.         wind_set(wind->wi_handle,WF_NAME,title);
  85. /* Fenster öffnen */
  86.         if(!wind_open(wind->wi_handle,x,y,w,h)) error=-1;
  87.     }
  88. /* fertig gemalt, der Rahmen steht */
  89.     wind_update(END_UPDATE);
  90. /* Fehler aufgetreten */
  91.     if(error)
  92.     {
  93. /* Handle zur Kennzeichnung negativ */
  94.         wind->wi_handle=-1;
  95. /* normalen Dialog ohne Fenster vorbereiten */
  96.         wind_update(BEG_MCTRL);
  97.         form_center(ptr,center_x,center_y,center_w,center_h);
  98.         form_dial(FMD_START,0,0,0,0,*center_x,*center_y,*center_w,*center_h);
  99.     }
  100.     return error;
  101. }
  102.  
  103. /* Dialog beenden, Fenster schlie₧en */
  104. int form_wclose(wi_data *wind)
  105. {
  106. /* es war kein Fenster offen */
  107.     if(wind->wi_handle<0)
  108.     {
  109. /* Bildschirm wieder freigeben */
  110.         wind_update(END_MCTRL);
  111. /* aktuelle Koordinaten der Box holen (Let 'em Fly!) */
  112.         form_center(wind->obj,wind->m,wind->n,wind->o,wind->p);
  113.         form_dial(FMD_FINISH,0,0,0,0,*wind->m,*wind->n,*wind->o,*wind->p);
  114.         return -1;
  115.     }
  116. /* Fenster schlie₧en und freigeben */
  117.     wind_close(wind->wi_handle);
  118.     wind_delete(wind->wi_handle);
  119.     wind->wi_handle=-1;
  120.     return 0;
  121. }
  122.  
  123. /* Fenster-Redraw in den angegebenen Koordinaten */
  124. void wi_redraw(wi_data *wind,int *buf)
  125. {
  126.     int x,y,w,h,xr=buf[4],yr=buf[5],xm,ym;
  127.  
  128. /* gä. T34 */
  129.     if(wind->wi_handle != buf[3])
  130.         return;
  131.     wind_update(BEG_UPDATE);
  132. /*    breite+höhe in koordinaten umrechnen */
  133.     xm=xr+buf[6];
  134.     ym=yr+buf[7];
  135. /* Begin der Rechteckliste */
  136.     wind_get(wind->wi_handle,WF_FIRSTXYWH,&x,&y,&w,&h);
  137. /* noch was zu tun */
  138.     while(w&&h)
  139.     {
  140. /* rc_intersect für aes */
  141.             w+=x;
  142.             h+=y;
  143.             if(xr>x) x=xr;
  144.             if(yr>y) y=yr;
  145.             if(xm>w) w-=x;
  146.             else w=xm-x;
  147.             if(ym>h) h-=y;
  148.             else h=ym-y;
  149. /* und malen */
  150.             if(h>0&&w>0)
  151.             {
  152. /*                vs_clip(int handle, int clip_flag, int *pxyarray ); */
  153.                 objc_draw(wind->obj, 0, MAX_DEPTH, x, y, w, h);
  154.             }
  155. /* nächste Rechteck */
  156.         wind_get(wind->wi_handle,WF_NEXTXYWH,&x,&y,&w,&h);
  157.     }
  158.     wind_update(END_UPDATE);
  159. }
  160.  
  161. /* ab jetzt bis zu wind_do() Original-Profibuch */
  162. #define FMD_BACKWARD -1
  163. #define FMD_FORWARD  -2
  164. #define FMD_DFLT     -3
  165.  
  166. #define TRUE 1
  167.  
  168. /* OBJECT best. Typs suchen */
  169. static int find_object(OBJECT *tree,int start_obj,int which)
  170. {
  171.     int object,flag,theflag,inc;
  172.     object=0;
  173.     flag=EDITABLE;
  174.     inc=1;
  175.     switch(which)
  176.     {
  177.         case FMD_BACKWARD:
  178.             inc=-1;
  179.         case FMD_FORWARD:
  180.             object=start_obj+inc;
  181.             break;
  182.         case FMD_DFLT:
  183.             flag=DEFAULT;
  184.             break;
  185.     }
  186.     while(object>=0)
  187.     {
  188.         theflag=tree[object].ob_flags;
  189.         if(theflag&flag) return object;
  190.         if(theflag&LASTOB) object=-1;
  191.         else object+=inc;
  192.     }
  193.     return start_obj;
  194. }
  195.  
  196. static int ini_field(OBJECT *tree,int start_field)
  197. {
  198.     if(start_field==0) start_field=find_object(tree,0,FMD_FORWARD);
  199.     return start_field;
  200. }
  201.  
  202. /* stellt Beziehung zwischen Mausclick und Cursor fest (T34) */
  203. /* Parameter:
  204.    obj        : Baum
  205.    No         : editierbares Object
  206.    mx         : x - Position des Mausclicks
  207.    return     : Cursorposition
  208. */
  209. static int find_position(OBJECT *obj, int No, int mx)
  210. {
  211.     int te_x= 0;    /* absolute Koordinaten des Textes */
  212.     int P_text= 0; /* Buchstaben im Text */
  213.     int P_mask= 0; /* Buchstaben in der Maske */
  214.     int size;        /* Buchstabenbreite */
  215.     int i, Child;
  216.  
  217.     size= obj[No].ob_spec.tedinfo->te_font==3 ? 8 : 6;    /* 6 od. 8 Punkt Font */
  218.     te_x= obj[No].ob_spec.tedinfo->te_just
  219.         ? obj[No].ob_width - (obj[No].ob_spec.tedinfo->te_tmplen-1) * size : 0;
  220.     if(obj[No].ob_spec.tedinfo->te_just==2)
  221.         te_x/= 2;
  222.     te_x+= obj[No].ob_x + size/2;        /* Start der Maske ohne Parent's */
  223. /* Parent suchen */
  224.     Child= No;
  225.     for(i= No-1; 0<=i; i--)
  226.     {
  227.         if((obj[i].ob_head <= Child) && (Child <= obj[i].ob_tail))
  228.         {
  229.             Child= i;        /* Parent found */
  230.             te_x+= obj[i].ob_x;
  231.         }
  232.     }
  233.     while((te_x < mx) && (P_mask < obj[No].ob_spec.tedinfo->te_tmplen - 1))
  234.     {
  235.         if(obj[No].ob_spec.tedinfo->te_ptmplt[P_mask++] == '_')
  236.             P_text++;
  237.         te_x+= size;
  238.     }
  239.     return P_text;
  240. }
  241.  
  242. /* form_do() in Fenstern: wind_do() */
  243. /* Parameter:
  244.    wind          : von form_wind() bearbeitetes wind-Objekt
  245.    start_field: Objektnummer, in dem sich der Textcursor zuerst
  246.                    befinden soll
  247.    buf[8]     : Messagepuffer
  248.    return     : Nummer des angesprochenen Objektes oder
  249.                    -1 Nach Eintreffen einer Message
  250. */
  251.  
  252. /* aus dem Profibuch (form_do()), erweitert um Message-Handling */
  253. int wind_do(wi_data *wind,int start_field,int *buf)
  254. {
  255.     OBJECT *tree=wind->obj;
  256.     int edit_object,next_object,which,cont;
  257.     int idx,mx= 0,my,mb,ks,kr,br,show_edit,first= 1;
  258. /* wenn kein Fenster offen: normales form_do()*/
  259.     if(wind->wi_handle<0) return form_do(wind->obj,start_field);
  260. /* Top Window holen */
  261.     wind_get(wind->wi_handle,WF_TOP,&show_edit);
  262.     show_edit=show_edit==wind->wi_handle?-1:0;
  263. /* Let 'em fly initialisieren */
  264.     if(show_edit&&wind->flags.ltmf) init_keys(tree);
  265.     next_object=ini_field(tree,start_field);
  266.     edit_object=0;
  267.  
  268.     cont=TRUE;
  269.  
  270.     while(cont)
  271.     {
  272.         if(next_object!=0)
  273.         {
  274.             edit_object=next_object;
  275.             next_object=0;
  276.             if(show_edit)
  277.             {
  278.                 /* Buchstabe, vor den der Cursor kommt */
  279.                 char    letter, *letterptr;
  280.  
  281.                 if(!first)
  282.                 {
  283.                     letter= *(letterptr=
  284.                         tree[edit_object].ob_spec.tedinfo->te_ptext
  285.                             + find_position(tree, edit_object, mx));
  286.                     *letterptr= '\000';
  287.                     objc_edit(tree,edit_object,0,&idx,ED_INIT);
  288.                     *letterptr= letter;
  289.                 } else
  290.                     objc_edit(tree,edit_object,0,&idx,ED_INIT);
  291.                 first= 0;
  292.             }
  293.         }
  294.  
  295.         which=evnt_multi(MU_KEYBD|MU_BUTTON|MU_MESAG,0x02,0x01,
  296.             0x01,0,0,0,0,0,0,0,0,0,0,buf,
  297.             0,0,&mx,&my,&mb,&ks,&kr,&br);
  298. /* interssierende Änderung: Message ist angekommen */
  299.         if(which&MU_MESAG)
  300.         {
  301. /* Cursor ausschalten */
  302.             wind_get(wind->wi_handle,WF_TOP,&show_edit);
  303.             show_edit=show_edit==wind->wi_handle?-1:0;
  304. /* Cursor aus */
  305.             if((edit_object!=0) && show_edit)
  306.                 objc_edit(tree,edit_object,0,&idx,ED_END);
  307.             switch(buf[0])
  308.             {
  309. /* Fenster wurde bewegt */
  310.             case WM_MOVED:
  311.             {
  312. /* alte Koordinaten zur Offsetberechnung speichern */
  313.                 int x=*wind->m,y=*wind->n;
  314. /* Rahmen verschieben */
  315.                 wind_set(buf[3],WF_CURRXYWH,buf[4],buf[5],buf[6],buf[7]);
  316. /* Holen, bzw. Errechnen der neuen Koordinaten der Arbeitsfläche
  317.    und des Object-Baumes */
  318.                 wind_get(buf[3],WF_WORKXYWH,wind->m,wind->n,wind->o,wind->p);
  319.                 tree->ob_x+=*wind->m-x;
  320.                 tree->ob_y+=*wind->n-y;
  321.                 break;
  322.             }
  323.             case WM_REDRAW:
  324. /* Redraw nötig */
  325.                     if(wind->flags.drawed) wi_redraw(wind,buf);
  326.                     wind->flags.drawed=1;
  327.                 break;
  328. /* falls Accessory: beim Anklicken des Slots Fenster toppen */
  329.             case AC_OPEN:
  330.                 wind_set(wind->wi_handle,WF_TOP,wind->wi_handle);
  331.                 break;
  332. /* bei dieser Message sowieso */
  333.             case WM_TOPPED:
  334.                 if(wind->flags.auto_top||wind->wi_handle==buf[3])
  335.                     wind_set(buf[3],WF_TOP,buf[3]);
  336.                 break;
  337.             }
  338. /* und zurück */
  339.             return -1;
  340.         }
  341.         if(which&MU_KEYBD)
  342.         {
  343. /* in Let 'em fly nach Taste suchen */
  344.             int kb_obj=0;
  345.             if(wind->flags.ltmf)
  346.             {
  347.                 kb_obj=lookup_key(kr, ks);
  348.                 if(kb_obj)
  349.                     cont = form_button(tree, kb_obj, 0x01, &next_object);
  350.             }
  351.             if(!kb_obj)
  352.             {
  353.                 cont=form_keybd(tree,edit_object,next_object,kr,&next_object,
  354.                                 &kr);
  355.                 if(kr)    objc_edit(tree,edit_object,kr,&idx,ED_CHAR);
  356.             }
  357.         }
  358.         if(which&MU_BUTTON)
  359.         {
  360.             next_object=objc_find(tree,0,MAX_DEPTH,mx,my);
  361.  
  362.             if(next_object==-1)
  363.             {
  364.                 Bconout(2,7);
  365.                 next_object=0;
  366.             }
  367.             else
  368.                 cont=form_button(tree,next_object,br,&next_object);
  369.         }
  370.         if(!cont||(next_object!=0))
  371.         {
  372.             if(show_edit) objc_edit(tree,edit_object,0,&idx,ED_END);
  373.         }
  374.     }
  375.     return next_object;
  376. }
  377.  
  378. /* das war's schon, kaum zu glauben, das ich dafür 3 Tage rumprobiert habe */
  379.