Changed "*4" in "*sizeof(APTR)" for x86_64.
[AROS-Contrib.git] / dopus / Library / simplerequest.c
blob24f03dbdfdec7cc0e4580b15fb59173f884bfb3b
1 /*
3 Directory Opus 4
4 Original GPL release version 4.12
5 Copyright 1993-2000 Jonathan Potter
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 All users of Directory Opus 4 (including versions distributed
22 under the GPL) are entitled to upgrade to the latest version of
23 Directory Opus version 5 at a reduced price. Please see
24 http://www.gpsoft.com.au for more information.
26 The release of Directory Opus 4 under the GPL in NO WAY affects
27 the existing commercial status of Directory Opus 5.
31 #include "dopuslib.h"
33 const static char *contstring[]={"_Continue"};
35 char * __regargs get_uscore_text(struct DOpusRemember **key,char *text,int pos)
37 char *newtext;
38 int a,len,cp;
40 len=strlen(text);
41 if (!(newtext=DoAllocRemember(key,len+2,0))) return(text);
42 for (a=0,cp=0;a<len;a++) {
43 if (cp==pos) newtext[cp++]='_';
44 newtext[cp++]=text[a];
46 newtext[cp]=0;
47 return(newtext);
50 int __saveds DoDoSimpleRequest(register struct Window *window __asm("a0"),
51 register struct DOpusSimpleRequest *simple __asm("a1"))
53 int
54 textlen,a,b,c,cw,cy,cb,sw,height,maxlen,llen,num,gwidth=0,gspace,gx,ty,ac,ogy,
55 gadgetid,ls,gy,last,gnum,lines,dl,strgad,sfy,hnum,rows=1,macc,ogx,
56 maxwidth,winwidth,winheight,xoffset,yoffset,d;
57 struct NewWindow *newwindow;
58 struct DOpusRemember *key;
59 struct Gadget *gadgets,*contgad,*gad,*glassgad=NULL;
60 struct Screen *screen;
61 struct Window *Window;
62 struct RastPort *rp,testrp;
63 struct TextFont *fnt,*tfnt;
64 struct StringInfo *sinfo;
65 struct IntuiMessage *Msg;
66 struct StringExtend *extend;
67 char *text,*keys,*buf,ch,*strbuf,**gadptr;
68 ULONG class;
69 UWORD code;
71 if (!simple) return(0);
72 if (!window) {
73 screen=IntuitionBase->FirstScreen;
74 fnt=GfxBase->DefaultFont;
76 else {
77 screen=window->WScreen;
78 fnt=window->RPort->Font;
80 if (simple->font) fnt=simple->font;
81 /*if (IntuitionBase->LibNode.lib_Version>36)*/ tfnt=fnt;
82 // else tfnt=screen->RastPort.Font;
83 InitRastPort(&testrp);
84 SetFont(&testrp,fnt);
86 if (simple->flags&SRF_BORDERS) maxwidth=screen->Width-screen->WBorLeft-screen->WBorRight;
87 else maxwidth=screen->Width;
89 ac=macc=0;
90 for (a=0,num=0,hnum=0;;a++) {
91 if (!simple->gads[a]) break;
92 if (simple->gads[a][0]) {
93 if (simple->gads[a][0]=='\n') {
94 ++rows;
95 ++hnum;
96 if (ac>macc) macc=ac;
97 ac=0;
99 else {
100 if ((b=TextLength(&testrp,simple->gads[a],strlen(simple->gads[a]))+fnt->tf_XSize)>gwidth)
101 gwidth=b;
102 ++num; ++ac;
105 else {
106 ++hnum;
107 ++ac;
110 gnum=num;
111 if (simple->strbuf) ++num;
112 if (ac>macc) macc=ac;
114 key=NULL; textlen=strlen(simple->text);
116 cw=fnt->tf_XSize; cy=fnt->tf_YSize; cb=fnt->tf_Baseline;
117 sw=(maxwidth/cw)-2; sfy=tfnt->tf_YSize;
119 if (!(text=(char *)DoAllocRemember(&key,textlen+2,MEMF_CLEAR)) ||
120 !(keys=(char *)DoAllocRemember(&key,gnum,MEMF_CLEAR)) ||
121 !(newwindow=(struct NewWindow *)DoAllocRemember(&key,sizeof(struct NewWindow),MEMF_CLEAR)) ||
122 !(gadgets=(struct Gadget *)DoAllocRemember(&key,sizeof(struct Gadget)*(num+1),MEMF_CLEAR)) ||
123 !(contgad=(struct Gadget *)DoAllocRemember(&key,sizeof(struct Gadget),MEMF_CLEAR)) ||
124 !(gadptr=(char **)DoAllocRemember(&key,(num+hnum+1)*sizeof(APTR),MEMF_CLEAR)) ||
125 !(buf=(char *)DoAllocRemember(&key,sw+2,0))) {
126 DoFreeRemember(&key);
127 return(0);
130 if (simple->strbuf) {
131 if (!(sinfo=(struct StringInfo *)DoAllocRemember(&key,sizeof(struct StringInfo),MEMF_CLEAR)) ||
132 !(extend=(struct StringExtend *)DoAllocRemember(&key,sizeof(struct StringExtend),MEMF_CLEAR)) ||
133 !(strbuf=(char *)DoAllocRemember(&key,simple->strlen+1,MEMF_CLEAR))) {
134 DoFreeRemember(&key);
135 return(0);
137 LStrCpy(strbuf,simple->strbuf);
138 if (simple->flags&SRF_GLASS)
139 glassgad=DoAllocRemember(&key,sizeof(struct Gadget),MEMF_CLEAR);
142 CopyMem(simple->text,text,textlen);
143 if (text[textlen-1]!=10) {
144 text[textlen]=10;
145 ++textlen;
148 height=maxlen=llen=ls=0;
149 for (a=0;a<textlen;a++) {
150 if (text[a]==10 || llen==sw) {
151 b=a;
152 if (llen==sw) {
153 while (a>ls) {
154 if (text[a]==' ' || text[a]=='.' || text[a]==',') {
155 llen=a-ls;
156 text[a]=10;
157 break;
159 --a; --llen;
161 if (a==ls) {
162 a=b;
163 llen=a-ls;
166 height+=cy+1;
167 if ((llen=TextLength(&testrp,&text[ls],llen)+fnt->tf_XSize)>maxlen)
168 maxlen=llen;
169 llen=0; ls=a;
171 else ++llen;
174 if (gwidth<100) gwidth=100;
175 if (gwidth*macc>maxwidth) {
176 hnum=0;
177 gwidth=(gnum)?maxwidth/gnum:0;
180 newwindow->DetailPen=255;
181 newwindow->BlockPen=255;
182 newwindow->IDCMPFlags=IDCMP_GADGETUP|IDCMP_VANILLAKEY|IDCMP_MOUSEBUTTONS;
183 newwindow->Flags=WFLG_ACTIVATE|WFLG_BORDERLESS|WFLG_RMBTRAP;
184 newwindow->Type=CUSTOMSCREEN;
186 if (simple->flags&SRF_BORDERS) {
187 xoffset=screen->WBorLeft;
188 yoffset=screen->WBorTop+screen->Font->ta_YSize+1;
189 newwindow->Title=simple->title;
191 else {
192 xoffset=0;
193 yoffset=0;
196 newwindow->Width=maxlen+8;
197 a=(gwidth*macc)+((macc+2)*10);
198 if (simple->strbuf && a<((42*tfnt->tf_XSize)+20)) a=(42*tfnt->tf_XSize)+20;
199 if (simple->flags&SRF_BORDERS) {
200 newwindow->Width+=screen->WBorLeft+screen->WBorRight;
201 a+=screen->WBorLeft+screen->WBorRight;
202 newwindow->Flags=WFLG_ACTIVATE|WFLG_RMBTRAP|WFLG_DRAGBAR|WFLG_DEPTHGADGET;
204 if (newwindow->Width<a) newwindow->Width=a;
205 if (newwindow->Width>screen->Width) newwindow->Width=screen->Width;
207 newwindow->Height=height+16+(num?((cy+5)*rows):0);
208 if (simple->flags&SRF_BORDERS) newwindow->Height+=yoffset+screen->WBorBottom;
209 if (simple->strbuf) newwindow->Height+=sfy+4;
210 if (newwindow->Height>screen->Height) newwindow->Height=screen->Height;
212 if (window) {
213 newwindow->LeftEdge=window->LeftEdge+((window->Width-newwindow->Width)/2);
214 newwindow->TopEdge=window->TopEdge+((window->Height-newwindow->Height)/2);
216 else {
217 newwindow->LeftEdge=(screen->Width-newwindow->Width)/2;
218 newwindow->TopEdge=(screen->Height-newwindow->Height)/2;
221 if (newwindow->LeftEdge+newwindow->Width>screen->Width)
222 newwindow->LeftEdge=screen->Width-newwindow->Width;
223 if (newwindow->TopEdge+newwindow->Height>screen->Height)
224 newwindow->TopEdge=screen->Height-newwindow->Height;
225 if (newwindow->LeftEdge<0) newwindow->LeftEdge=0;
226 if (newwindow->TopEdge<0) newwindow->TopEdge=0;
228 newwindow->Screen=screen;
230 winwidth=newwindow->Width;
231 winheight=newwindow->Height;
233 if (simple->flags&SRF_BORDERS) {
234 winwidth-=screen->WBorLeft+screen->WBorRight;
235 winheight-=yoffset+screen->WBorBottom;
238 ogx=gx=(winwidth-(gwidth*macc))/(macc+1);
239 gspace=gx+gwidth;
241 ogy=gy=winheight-4-(num?((cy+5)*rows):0);
242 if (simple->strbuf) lines=(gy-(sfy+8)-(7+cb))/(cy+1);
243 else lines=(gy-(7+cb))/(cy+1);
245 last=a=0; strgad=1;
246 for (b=0;b<(num+hnum);b++) {
247 if (last && simple->strbuf) {
248 gadgets[a].LeftEdge=10+cw+xoffset; // GA_Left
249 c=cb+7+(lines*cy);
250 gadgets[a].TopEdge=c+(((ogy-c)-sfy)/2)+yoffset+1; // GA_Top
251 gadgets[a].Width=winwidth-20-(cw*2); // GA_Width
252 gadgets[a].Height=sfy; // GA_Height
253 gadgets[a].Flags=GFLG_GADGHCOMP|GFLG_STRINGEXTEND; // GA_Highlight
254 gadgets[a].Activation=GACT_RELVERIFY|GACT_TOGGLESELECT; // GA_RelVerify, GA_ToggleSelect
255 if (simple->flags&SRF_LONGINT) gadgets[a].Activation|=LONGINT; // STRINGA_LongInt
256 if (simple->flags&SRF_CENTJUST) gadgets[a].Activation|=STRINGCENTER; // STRINGA_Justification,GACT_STRINGCENTER
257 if (simple->flags&SRF_RIGHTJUST) gadgets[a].Activation|=STRINGRIGHT; // STRINGA_Justification,GACT_STRINGRIGHT
258 gadgets[a].GadgetType=GTYP_STRGADGET;
259 gadgets[a].GadgetID=65535; // GA_ID
260 gadgets[a].SpecialInfo=(APTR)sinfo; // GA_SpecialInfo
261 sinfo->Buffer=strbuf;
262 sinfo->UndoBuffer=DoAllocRemember(&key,simple->strlen+2,MEMF_CLEAR);
263 sinfo->MaxChars=simple->strlen+1;
265 if (simple->flags&SRF_EXTEND)
266 CopyMem((char *)simple->value,(char *)extend,sizeof(struct StringExtend));
267 else {
268 extend->Font=fnt;
269 extend->Pens[0]=simple->fg;
270 extend->Pens[1]=simple->bg;
271 extend->ActivePens[0]=simple->fg;
272 extend->ActivePens[1]=simple->bg;
274 sinfo->Extension=extend;
276 strgad=a;
277 if (glassgad) {
278 gadgets[a].LeftEdge+=24;
279 gadgets[a].Width-=24;
281 glassgad->LeftEdge=4+cw+xoffset;
282 glassgad->TopEdge=gadgets[a].TopEdge-2;
283 glassgad->Width=24;
284 glassgad->Height=sfy+4;
285 glassgad->Flags=GFLG_GADGHCOMP;
286 glassgad->Activation=GACT_RELVERIFY;
287 glassgad->GadgetType=GTYP_BOOLGADGET;
288 glassgad->GadgetID=65534;
291 else if (simple->gads[b][0]) {
292 if (simple->gads[b][0]=='\n') {
293 gy+=cy+6;
294 gx=ogx-gspace;
296 else if (a<gnum) {
297 gadgets[a].LeftEdge=gx+xoffset;
298 gadgets[a].TopEdge=gy+yoffset;
299 gadgets[a].Width=gwidth;
300 gadgets[a].Height=cy+5;
301 gadgets[a].Flags=GADGHCOMP;
302 gadgets[a].Activation=RELVERIFY;
303 gadgets[a].GadgetType=GTYP_BOOLGADGET;
304 gadgets[a].GadgetID=simple->rets[a];
305 /* JRZ: begin
306 d=0;
307 keys[a]=LToLower(simple->gads[b][0]);
308 for (c=0;c<a;c++) {
309 if (keys[c]==keys[a]) {
310 keys[a]=LToLower(simple->gads[b][1]);
311 d=1;
312 break;
315 gadptr[a]=get_uscore_text(&key,simple->gads[b],(simple->strbuf)?-1:d);
317 for (d=0; simple->gads[b][d]; d++)
318 if (simple->gads[b][d] == '_')
320 keys[a] = LToLower(simple->gads[b][d+1]);
321 break;
323 gadptr[a]=simple->gads[b];
324 // JRZ: end
325 if (last) break;
326 if (a==gnum-1 && simple->strbuf) last=1;
327 ++a;
330 if ((gx+=gspace)>winwidth) {
331 num=a+1;
332 if (simple->strbuf) {
333 last=1;
334 ++num;
336 else if (a<num) break;
340 for (a=0;a<num;a++) gadgets[a].NextGadget=(a<num-1)?&gadgets[a+1]:NULL;
342 contgad->Width=(cw*10)<100?100:cw*10;
343 contgad->LeftEdge=(newwindow->Width-contgad->Width)/2;
344 contgad->TopEdge=gy+yoffset;
345 contgad->Height=cy+4;
346 contgad->Flags=GFLG_GADGHCOMP;
347 contgad->Activation=GACT_RELVERIFY;
348 contgad->GadgetType=GTYP_BOOLGADGET;
350 if (num && (simple->flags&SRF_RECESSHI))
351 DoAddGadgetBorders(&key,contgad,1,simple->hi,simple->lo);
353 if (!(Window=OpenWindow(newwindow))) {
354 DoFreeRemember(&key);
355 return(0);
357 rp=Window->RPort;
358 SetFont(rp,fnt);
360 if ((screen->Flags&15)==CUSTOMSCREEN)
361 ModifyIDCMP(Window,GADGETUP|VANILLAKEY|INACTIVEWINDOW|MOUSEBUTTONS);
363 if (simple->hi==-1) simple->hi=2;
364 if (simple->lo==-1) simple->lo=1;
365 if (simple->fg==-1) simple->fg=1;
366 if (simple->bg==-1) simple->bg=0;
368 if (!(simple->flags&SRF_BORDERS))
369 Do3DBox(rp,2,1,Window->Width-4,Window->Height-2,simple->hi,simple->lo);
371 SetAPen(rp,simple->bg);
372 RectFill(rp,xoffset+2,yoffset+1,xoffset+winwidth-3,yoffset+winheight-2);
373 SetAPen(rp,simple->fg); SetBPen(rp,simple->bg);
375 ty=7+cb+yoffset;
376 llen=dl=0;
377 for (a=0;a<textlen;a++) {
378 buf[llen]=text[a];
379 if (text[a]==10 || llen==sw) {
380 if (simple->flags&SRF_NOCENTER) Move(rp,Window->BorderLeft+6,ty);
381 else Move(rp,(Window->Width-(TextLength(rp,buf,llen)))/2,ty);
382 Text(rp,buf,llen);
383 llen=0; ty+=cy+1; ++dl;
384 if (dl>lines && a<textlen-1) {
385 dl=0;
386 if (num) DoAddGadgets(Window,contgad,&(string_table[STR_CONTINUE])/*contstring*/,1,simple->hi,simple->lo,1);
387 c=0;
388 FOREVER {
389 Wait(1<<Window->UserPort->mp_SigBit);
390 while (Msg=(struct IntuiMessage *)GetMsg(Window->UserPort)) {
391 class=Msg->Class; code=Msg->Code;
392 if (class==IDCMP_GADGETUP)
393 gadgetid=((struct Gadget *)Msg->IAddress)->GadgetID;
394 ReplyMsg((struct Message *)Msg);
395 if (class==IDCMP_INACTIVEWINDOW) {
396 if (IntuitionBase->ActiveScreen==screen) ActivateWindow(Window);
398 else if (num) {
399 if (class==IDCMP_VANILLAKEY) {
400 ch=LToLower(code);
401 if (ch=='\r' || ch=='c') {
402 c=1;
403 DoSelectGadget(Window,contgad);
404 break;
406 if (ch=='\e') {
407 CloseWindow(Window);
408 DoFreeRemember(&key);
409 return(0);
412 else if (class==IDCMP_GADGETUP) {
413 c=1;
414 break;
417 else if (!num && class==IDCMP_MOUSEBUTTONS && code==SELECTDOWN) c=1;
419 if (c) break;
421 if (num) RemoveGList(Window,contgad,1);
422 SetAPen(rp,simple->bg);
423 RectFill(rp,xoffset+2,yoffset+1,xoffset+winwidth-3,yoffset+winheight-2);
424 SetAPen(rp,simple->fg);
425 SetBPen(rp,simple->bg);
426 ty=7+cb+yoffset;
429 else ++llen;
432 if (num) {
433 if (simple->flags&SRF_RECESSHI)
434 DoAddGadgetBorders(&key,gadgets,num,simple->hi,simple->lo);
435 DoAddGadgets(Window,gadgets,gadptr,num,simple->hi,simple->lo,1);
437 if (simple->strbuf) {
438 SetAPen(rp,0);
439 RectFill(rp,gadgets[strgad].LeftEdge,gadgets[strgad].TopEdge,
440 gadgets[strgad].LeftEdge+gadgets[strgad].Width-1,
441 gadgets[strgad].TopEdge+gadgets[strgad].Height-1);
442 Delay(5);
443 ActivateStrGad(&gadgets[strgad],Window);
444 if (glassgad) {
445 if (simple->flags&SRF_RECESSHI)
446 DoAddGadgetBorders(&key,glassgad,1,simple->hi,simple->lo);
447 DoAddGadgets(Window,glassgad,NULL,1,simple->hi,simple->lo,1);
448 DoDoGlassImage(rp,glassgad,simple->hi,simple->lo,0);
452 FOREVER {
453 Wait(1<<Window->UserPort->mp_SigBit);
454 while (Msg=(struct IntuiMessage *)GetMsg(Window->UserPort)) {
455 class=Msg->Class; code=Msg->Code;
456 if (class==GADGETUP) {
457 gad=(struct Gadget *)Msg->IAddress;
458 gadgetid=gad->GadgetID;
460 ReplyMsg((struct Message *)Msg);
461 switch (class) {
462 case MOUSEBUTTONS:
463 if (!num && (code==MENUDOWN || code==SELECTDOWN)) {
464 CloseWindow(Window);
465 DoFreeRemember(&key);
466 return(1);
468 if (simple->strbuf) ActivateStrGad(&gadgets[strgad],Window);
469 break;
470 case INACTIVEWINDOW:
471 if (IntuitionBase->ActiveScreen==screen) {
472 ActivateWindow(Window);
473 if (simple->strbuf) {
474 Delay(5);
475 ActivateStrGad(&gadgets[strgad],Window);
478 break;
479 case VANILLAKEY:
480 ch=LToLower(code);
481 if (ch=='\e' || ch=='\r') {
482 if (ch=='\e') a=0;
483 else a=1;
484 for (gadgetid=0;gadgetid<gnum;gadgetid++)
485 if (simple->rets[gadgetid]==a) break;
486 if (simple->rets[gadgetid]!=a) break;
488 else {
489 for (gadgetid=0;gadgetid<gnum;gadgetid++)
490 if (ch==keys[gadgetid]) break;
491 if (ch!=keys[gadgetid]) break;
493 if (gadgetid>=gnum) gadgetid=gnum-1;
494 if (gadgets[gadgetid].Activation&TOGGLESELECT) {
495 HiliteGad(&gadgets[gadgetid],rp);
496 gadgetid=gad->GadgetID;
498 else {
499 DoSelectGadget(Window,&gadgets[gadgetid]);
500 gadgetid=simple->rets[gadgetid];
502 case GADGETUP:
503 if (simple->strbuf && gadgetid==65534) {
504 struct DOpusFileReq filereq;
505 char dirbuf[256],filebuf[FILEBUF_SIZE],*ptr;
507 filereq.dirbuf=dirbuf;
508 filereq.filebuf=filebuf;
509 filereq.window=Window;
510 filereq.x=-2;
511 filereq.y=-2;
512 filereq.lines=15;
513 if (simple->flags&SRF_DIRGLASS)
515 filereq.flags=DFRF_DIRREQ;
516 filereq.title=string_table[STR_SELECT_DIR];
518 else
520 filereq.flags=0;
521 filereq.title=string_table[STR_SELECT_FILE];
523 filereq.filearraykey=NULL;
525 LStrCpy(dirbuf,strbuf);
526 if (!(simple->flags&SRF_DIRGLASS)) {
527 if ((ptr=DoBaseName(dirbuf))>dirbuf) {
528 LStrCpy(filebuf,ptr);
529 *ptr=0;
531 else if (DoCheckExist(dirbuf,NULL)<1) {
532 dirbuf[0]=0;
533 LStrCpy(filebuf,strbuf);
535 else filebuf[0]=0;
537 if (DoFileRequest(&filereq)) {
538 LStrCpy(strbuf,dirbuf);
539 if (!(simple->flags&SRF_DIRGLASS))
540 DoTackOn(strbuf,filebuf,256);
542 RefreshStrGad(&gadgets[strgad],Window);
543 ActivateStrGad(&gadgets[strgad],Window);
544 break;
546 CloseWindow(Window);
547 if (gadgetid && simple->strbuf) LStrCpy(simple->strbuf,strbuf);
548 DoFreeRemember(&key);
549 return(gadgetid);