English Amiga Board

English Amiga Board (http://eab.abime.net/index.php)
-   Coders. C/C++ (http://eab.abime.net/forumdisplay.php?f=118)
-   -   Problems trying to output text to a simple window (http://eab.abime.net/showthread.php?t=88110)

chocsplease 01 August 2017 13:34

[Solved] Problems trying to output text to a simple window
 
Hello all,

I am trying to output text to a window and have run into a number of issues.

I had assumed that the Amiga would be nice and if I set up a window with drag bars and resize etc gadgets it would take care of text that was larger than the size of the window.

It looks like I was wrong.

I am defining my window thus
Code:

int open_window(int scrnwidth,int scrnheight)
{
    int topleftx=0,toplefty=0;
    int width=200,height=200;
    int tempw=0,temph=0;
/*calculate 1 quarter of screen width*/

    if (mywindow)
        return 0; /*opened already*/

    tempw=scrnwidth/4;

/*calculate 1 5th screen height*/

    temph=scrnheight/5;

    topleftx=tempw;
    toplefty=temph;

    width=scrnwidth-(tempw*2);
    height=scrnheight-(temph*2);

    mywindow = OpenWindowTags(NULL, WA_Left, topleftx, WA_Top, toplefty, WA_Width,width, WA_Height,height,\
        WA_IDCMP,IDCMP_CLOSEWINDOW, WA_Flags, WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_ACTIVATE,\
        WA_Title, "Info64", WA_PubScreenName, "WorkBench", TAG_DONE);

    if (mywindow)
    {
        myIText.FrontPen    = myTEXTPEN;
                myIText.BackPen    = myBACKGROUNDPEN;
                myIText.DrawMode    = JAM2;
                myIText.LeftEdge    = MYTEXT_LEFT;
                myIText.TopEdge    = MYTEXT_TOP;
                myIText.ITextFont  = &myTextAttr;
                myIText.IText      = "Hello, World.  ;-)";
                myIText.NextText    = NULL;
        mywindowrastport=mywindow->RPort;
        return 0;
    }
    else
        return 1;
}

You'll see that I am also setting up a structure to output some text in the same function. myIText is a global defined as - struct IntuiText myIText;

Later on in the code I replace my simple hello world text with what I want to display -

Code:

if (mywindow)
    {
        sprintf(buffer,"%s%s      %s%s    %s%s      %s%s      %s%s  %s%s  %s%s    %s%s%s\n",messages[9],tabs_ptr[0],\
            messages[10],tabs_ptr[1],messages[11],tabs_ptr[2],messages[12],\
            tabs_ptr[3],messages[13],tabs_ptr[4],messages[14],tabs_ptr[5],messages[15],\
            tabs_ptr[6],messages[16],tabs_ptr[7],messages[17]);
        myIText.IText = buffer;
        PrintIText(mywindow->RPort,&myIText,10,10);
    }

buffer is simply a char array 500 long.

However this text is larger than the window so I had assumed that the Amiga would only display what it could and keep the rest hidden 'somewhere' for when the window was resized.

Nope doesn't do that.

Instead it dumps out the text and overwrites the right most edge of the window.

I've obviously missed something fundamental here but I am struggling to find out what.

Is there a way of confining text output in the way I have described? I don't really want to attach a console to the window, which is the only way I have discovered so far.

Here's hoping, and as always many many thanks in advance.

Cylon 01 August 2017 15:32

Easy way is to use GimmeZeroZero (GZZ) flags on your window, which results in a different Rastport for the window's borders - the system (Intuition) will handle clipping at the edges, or,
you install your own clipping regions.
Third option:
you determine the pixel width of the text and cut the string accordingly.

chocsplease 03 August 2017 17:31

Quote:

Originally Posted by Cylon (Post 1175450)
Easy way is to use GimmeZeroZero (GZZ) flags on your window, which results in a different Rastport for the window's borders - the system (Intuition) will handle clipping at the edges, or,
you install your own clipping regions.
Third option:
you determine the pixel width of the text and cut the string accordingly.

Many thanks for the reply - I'll check out the gzz option. I have been working on the 3rd, and wrote a function to count the number of chars I was going to output in preparation. Thing is it doesn't work :(

This is the code
Code:

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <proto/dos.h> 
#include <proto/exec.h> 



long count_chars(char *format, ...) /* variable number of args*/
{
    va_list valist;
    unsigned int i,longcount=0,spcfound=1,nosign=0,ok=0,ii=0,error=0;
    long count=0;
    long long number;
/*    char *format;*/
    char letter1,letter2,letter3;
    char* string;

    va_start(valist,format);

/*    if (num<1)/
    {
        error=-2;
        va_end(valist);
        return error;   
    }*/

    /*format=(char*)va_arg(valist,char);*/ /*get format string*/

    if (strlen(format)==0) /*if dud format string*/
    {
        va_end(valist); /*free memory*/
        return -3;    /*quit*/
    }

    printf("format is %d long\n",strlen(format));

    /*now parse format string, counting normal chars and calulating size of numbers*/

    for (i=0;i<strlen(format);i++)
    {

        printf("i=%d char=%c\n",i,(char)format[i]);

        if (CheckSignal (SIGBREAKF_CTRL_C))
        {
            printf("*BREAK main loop*\n");
            break;
        }
                   

        letter1=(char)format[i];
        if (letter1 !='%')
        {
            if (letter1==' ')
                spcfound=1;

            if (spcfound==1)    /*normal character ie not in format% <something>*/
                count++;
        }
        else if ((i+1) <(strlen(format)))
        {
            letter2=(char)format[i+1];
            spcfound=0;        /*now we hunt for a space or %*/
   
            if (letter2=='%') /*want to output a percent sign*/
            {
                count++;    /*just add to count*/
                i++;        /*inc place*/
                spcfound=1;    /*now looking for a space*/
            }
            else if (letter2=='u')    /*signifies unsigned so set flag*/
            {
                nosign=1;
                i++;
            }
           
            else if (letter2=='l')    /*long integer so add to longcount*/
            {
                longcount++;
                i++;
            }

            else if ((letter2=='d') ||(letter2=='x'))    /*work out number of chars in dec or hex number*/
            {
                ok=0;
                i++;
                if (nosign)
                {
                    if (longcount==0)
                    {
                        ok=1;
                        number=va_arg(valist,unsigned int);
                    }
                    if (longcount==1)
                    {
                        ok=1;
                        number=va_arg(valist,unsigned long int);
                    }
                    if (longcount==2)
                    {
                        ok=1;
                        number=va_arg(valist,unsigned long long int);
                    }
                    if (longcount>2)
                    {
                        error=-1;    /*formatting error too many l's*/
                        break;
                    }
               
       
                    if (ok)        /* have something in number*/
                    {
                        while (number!=0)
                        {
                            printf("unsigned  number %d\n",number);
                            if (CheckSignal (SIGBREAKF_CTRL_C))
                            {
                                printf("*BREAK unsigned loop*\n");
                                break;
                            }
   
                            if (letter2=='d')
                                number=number/10;
                            else
                                number=number/16;

                            count++;
                        }
                    }
                    longcount=0;    /*clear count of l's*/
                               
                }
                else    /*signed*/
                {
                    printf("signed longcount=%d\n",longcount);
                    if (longcount==0)
                    {
                        ok=1;
                        printf("int\n");
                        number=va_arg(valist, int);
                    }
                    if (longcount==1)
                    {
                        ok=1;
                        printf("long int\n");

                        number=(long long int)va_arg(valist, long int);
                    }
                    if (longcount==2)
                    {
                        ok=1;
                        printf("long long int\n");

                        number=(long long int)va_arg(valist, long long int);
                    }
                    if (longcount>2)
                    {
                        error=-1;    /*formatting error too many l's*/
                        break;
                    }
               
                    if(ok)
                    {
                        printf("number starts %d\n",number);
                        if (number<0)    /*negetive number so allow for sign*/
                            count++;
                        while (number!=0)
                        {
                            printf("signed number %d\n",number);

                            if (CheckSignal (SIGBREAKF_CTRL_C))
                            {
                                printf("*BREAK signed loop*\n");
                                break;
                            }
                   
                            if (letter2=='d')
                                number=number/10;
                            else
                                number=number/16;
                           
                            count++;
                        }

                    }
                    longcount=0;    /*clear count of l's*/
                }
            }    /*end of if (letter1=='d')*/
           
            else if(letter2=='s') /*string*/
            {
                string =va_arg(valist,char*);
                count=count+strlen(string);
            }
        }
        else    /* % at end of string - dud format*/
        {
            printf("dud string\n");
            error=-1;
            break;
        }
    }    /* end for*/

    va_end(valist);    /*clear va memory*/

printf("error=%d\n",error);

    if (error!=0)
        return error;

    return count;
}

int main()
{
    int num1=-500;
    unsigned int num2 =45;
    long int num3 = -5087654;
    unsigned long int num4 = 3637363783;
    long long int num5= -82344826482342;
    unsigned long long int num6 =88268966344;

    long result=0;

    result=count_chars("This is a test %d",num1);

    printf("The number of chars is %d\n",result);
return 0;
}

What I am trying to do is parse a format string like "this is a number %d" in the 1st argument have the actual number, or numbers in subsequent arguments and spit out the total number of characters.

However the line -

number=va_arg(valist, int);

is always setting number to -1. I have tried casting as - number=(long long int)va_arg(valist, int); but this also returns -1.

I'm using this page - https://en.wikibooks.org/wiki/C%2B%2...nctions/va_arg

for my inspiration, but this is C++ and appears to be defining the vars used to pull the arguments out on the fly (eg -
int d = va_arg( argptr, int ); )

Once
again I am stuck. What really baffles me is the loop -

Code:

while (number!=0)                       
{
      printf("signed number %d\n",number);                             
      if (CheckSignal (SIGBREAKF_CTRL_C))                           
      {                                 
              printf("*BREAK signed loop*\n");                               
            break;                           
      }                                                 
      if (letter2=='d')                               
            number=number/10;                           
      else                               
            number=number/16;                                                         
      count++;                       
}

Actually works and loops 3 times for the number -500. Even though number is printf-ing as -1 and changing the %d to %ld in my printfs has no effect it still spits out -1.:confused

Can anyone see where I am going wrong?

alkis 03 August 2017 18:10

what exactly are you trying to do? :)

sprintf should return the 'number of chars' that went into the buffer. If it didn't/doesn't, you can always return strlen(buffer)

Cylon 03 August 2017 20:06

No no, just use TextLength() and if the returned amount of pixels is to high then eat a few chars from the end.

alkis 03 August 2017 21:04

Let me try again, what does the function count_chars() supposed to do?
It returns a long. What is the long supposed to represent?

chocsplease 08 August 2017 13:09

Many thanks for the replies, I'll look into TextLength.

Quote:

Originally Posted by alkis (Post 1176005)
Let me try again, what does the function count_chars() supposed to do?
It returns a long. What is the long supposed to represent?

count_chars takes a format string, similar to that used in printf and counts all the characters plus any from numbers and additional strings.

If you give it "Test number %d test string %s",number,string it will count the chars in the text (25) and then work out the number of digits in number and then add the length of string to the result before returning the result.

So if number is 50 and string is "Hello" the total would be 32.

There is some very simple format checking and the function will return a negative number if it has hit a problem.

I think I've stumbled on what's going wrong - its to do with the way my version of gcc handles long longs , or rather does not.

64 bit maths is implemented (you can add, subtract etc long longs) as are shifts (<< and >>) and boolean ops ( x &y and x | y work). But printf breaks if you give it a long long. printf ("%lld",number) just returns %lld and printf("%ld",number) returns -1 if the number is a long long. I can cast the number to a long and then printf works.

The other issue is that va_arg() can't handle long longs so I have had to break these into two longs and shift the high bytes after they have been retrieved by va_arg().

I did think about just using sprintf, but this requires a buffer and I do not know the maximum size the resulting string is going to be.

mark_k 08 August 2017 16:45

How about using fprintf() instead of sprintf()?

It's kind of a hack, but can you open NIL: then call fprintf() outputting to NIL: to discard the output since you're just interested in the return value?

chocsplease 12 August 2017 14:09

Quote:

Originally Posted by mark_k (Post 1176938)
How about using fprintf() instead of sprintf()?

It's kind of a hack, but can you open NIL: then call fprintf() outputting to NIL: to discard the output since you're just interested in the return value?

Many thanks for the suggestion, it may be a hack(ish) but it works. the only problem I have is that the resulting executable is 7.7K for something that is tiny. So I tried to 'Amigaise' it - this is my code.

Code:

#include <proto/dos.h>
#include <proto/exec.h>
#include <ctype.h>
int main()
{
    BPTR *fh;
    long result;
    int number =57;
    fh = Open("NIL:", MODE_NEWFILE);
    if (fh) /*if file opened*/
    {
        result=VFPrintf(fh,"This is a test %ld",(long)number);
        Close(fh);
    }

    Printf("the result is %ld\n",result);
}

I have a problem
  • I am getting a warning on the VFPrintf line (Initialisation makes integer for a pointer without a cast)
The executable is 2.2 k and it works, but I've had problems finding info on VFPrintf so suspect I've got the args wrong, can someone point out where?


Many thanks.

a/b 12 August 2017 20:12

You generally don't use v-printf style functions with individual arguments, you use them with a variable length argument list. Something like:
Code:

int some_function(int first, const char* format, ...)  // variable number of arguments
{
va_list list;
va_start(list,format); // format is the last non-variable argument
vfprintf(stdout,format,list);
va_end(list);
}

You should use fprintf instead.

mark_k 13 August 2017 15:33

Quote:

Originally Posted by chocsplease (Post 1177693)
Many thanks for the suggestion, it may be a hack(ish) but it works. the only problem I have is that the resulting executable is 7.7K for something that is tiny. So I tried to 'Amigaise' it - this is my code.
...
I have a problem
  • I am getting a warning on the VFPrintf line (Initialisation makes integer for a pointer without a cast)
The executable is 2.2 k and it works, but I've had problems finding info on VFPrintf so suspect I've got the args wrong, can someone point out where?

I think you're almost there. Check the VFPrintf autodoc.

VFPrintf takes a fixed number of arguments (3). The third argument is a pointer to an array of formatting values. That's unlike the C fprintf() function which takes a variable number of arguments. However as mentioned in the autodoc you can use FPrintf which does take a variable number of arguments. You'll need to link your program with amiga.lib if you don't already. So do something like
Code:

result=FPrintf(fh,"This is a test %ld",(long)number);

Another alternative, which is cleaner in a sense because you don't need to open a file, would be to use the Exec function RawDoFmt(). With that, you could pass &result for the 4th argument (PutChData). Your PutChProc function would look like this:
Code:

PutChProc:  addq.l #1,(A3)
            rts


mark_k 13 August 2017 15:48

No guarantee this is correct. In fact it probably isn't... :)
Code:

long result = 0;
long PutChProc = 0x52934E75;  /* 68000 opcodes for addq.l #1,(A3) then rts */
RawDoFmt("This is a test %ld", &number, &PutChProc, &result);


mark_k 13 August 2017 16:05

Another idea... If you wanted to write portable code, it looks like using snprintf() could be neater than fprintf() with NIL: (and of course NIL: is Amiga-specific).
Code:

char dummy = 0;
result = snprintf(&dummy, 1, "This is a test %ld", number);


chocsplease 13 August 2017 16:46

Many thanks for the replies.

I wanted to try and keep the executable small, and using fprintf (with fopen, fclose etc) gave one that was over 10k. The Amiga version I posted gave 2.9k however I had completely missed the existence of FPrintf which is exactly what I need.

I tried using VFPrintf with va_start etc, but for some reason it would only output the basic text, 0 for any number and nothing at all for strings. No idea why.

I'm writing for the Amiga so thankfully portability is not an issue.

Many thanks once again.

chocsplease 23 August 2017 13:57

OOOkay,

I am (I think) almost there.
  • I now have a linked list of the text, line by line I want to display.
  • I know the length (in characters of each line)
  • I know the width and height of the window I want to put the text in.
  • I know the width etc of the font I'm using
What I cannot find is how to use Textlength (or whatever) to find the number of pixels each line will use, my idea is to take this divide it by the number of chars, to give an average, leave a bit of leeway and then work put how many chars will fit per line into the window and I guess how many lines.


Can someone point me at the right command to use, or better still a code chunk to learn from? I confess that the limited stuff I have found on the net has left me somewhat confused.


Thanks in advance.

chocsplease 29 August 2017 03:31

Hi All,

Well almost there but not quite. I am having an odd problem when lining up columns in a window. I am basically outputting an updated version of the info command but things are not quite lining up correctly.

This is the output straight to the shell window:

Code:

Unit      DOS    Size      Used      Free  Full  Errors    Status        Name
SMBFS0:    DOS0  488Gb      223Gb      264Gb  45%    0      Read & Write  PCbackup
PC0:      MSD0  720Kb      11Kb      709Kb    1%    0      Read only    EMPTY
CF0:      No disk in drive
RAM:      DOS0  686Kb      686Kb      121Mb    0%    0      Read & Write  Ram Disk
DH0:      PFS3    94Mb      93Mb      654Kb  99%    0      Read & Write  WB
DF0:      PC Disk
CC0:      No disk in drive
DF1:      DOS0  837Kb      789Kb      48Kb  94%    0      Read & Write  EdWordPro_2
DH1:      PFS3  3471Mb    3353Mb      117Mb  96%    0      Read & Write  Games
DH2:      PFS3  3567Mb    3487Mb      80Mb  97%    0      Read & Write  Apps

Available Volumes:
PCbackup    Mounted
EMPTY      Mounted
Ram Disk    Mounted
Apps        Mounted
Games      Mounted
EdWordPro_2 Mounted

In order to get this onto a window I am building a linked list with this structure
Code:

struct window_keeper
{
        struct window_keeper *next;
        char* line;
        int body;
        int linetype;
        unsigned int lineno;
};

*next points to the next line
line is the line of text eg -DH2: PFS3 3567Mb 3487Mb 80Mb 97% 0 Read & Write Apps
body is unused at pres
linetype is 1 for the 1st heading, 2 for the device list, 3 for the Volumes heading and 4 for the volumes list
lineno is the line's number starting at 1.

This structure is the var winhead in the below code.

This is the code I am using to output to the window.
Code:

int write_win()
{
/*        struct textattr TextAttr;*/
        long win_width=0,win_height=0;
        long line_len=0,doscol=0,currentdoscol;
        long numpix=0, avpix=0, fitchar=0,tempfitchar=0;
        struct window_keeper *currentline=NULL;
        unsigned char *buffer;        /*used for lines*/
        unsigned char *buffer_part; /*used for colours*/
        unsigned int charpos=0, percentpos=0;
int zz=0;


        win_width=mywindow->Width-mywindow->BorderRight;
        win_height=mywindow->Height-mywindow->BorderBottom;

        /*dirty way to find how may chars will fit into window*/

        myIText.IText="M";
        numpix=IntuiTextLength(&myIText);

        fitchar=(win_width/numpix) -4; /* -4 for safety*/

        printf("number of pix %d width %d max=%d\n",numpix,win_width,fitchar);


        if (fitchar==0) /*cant get any so give up*/
                return 0;

        if (winhead)        /*if we have something*/
        {

                if (currentline==NULL)
                        currentline=winhead;
        }
        else
                return 0; /*nothing saved!*/

        buffer=malloc((maxlinelen+1)*sizeof(char)); /*make memory buffers for line plus null char*/
        buffer_part=malloc((maxlinelen+1)*sizeof(char));


        while ((currentline) && ((10*currentline->lineno)<win_height)) /*now dump saved text rough attempt stopping at end of data or window*/
        {

/*                printf("BUFFER is %d\n",&buffer);
                printf("Line -%s-\n",currentline->line);        */
                if (fitchar>strlen(currentline->line))
                {
                       
                        memcpy(buffer, (char *)currentline->line, strlen(currentline->line));
                        (char)buffer[strlen(currentline->line)]='\0';        /*teminate string*/
                }
                else
                {       

                        memcpy(buffer, (char *)currentline->line,fitchar );
                        (char)buffer[fitchar]='\0';        /*terminate string*/
                }

                switch (currentline->linetype)
                {
                        case 1:
                                myIText.FrontPen = white;
                                doscol=finddoscol(buffer);
                                break;

                        case 2:
                                charpos=findchar(buffer,':');
                                currentdoscol=finddoscol(buffer);
                                if (charpos!=-1)
                                {
                                       
                                        myIText.FrontPen = white;
                                        leftstr(buffer_part,currentline->line,charpos);
                                        myIText.IText=buffer_part;
                                        PrintIText(mywindow->RPort,&myIText,10,10*currentline->lineno);

                                        /*now the rest*/

                                        /*but can it fit?*/

                                        tempfitchar=(win_width/numpix) -4;/* - (strlen(buffer_part)); -4 for safety*/
                                       
                                        if (tempfitchar>0)
                                        {
                                                myIText.FrontPen = black;
                                                midstr(buffer,currentline->line,currentdoscol,tempfitchar-(currentdoscol));




                                                /*now look for %*/
                                               
                                                percentpos=findchar(currentline->line,'%');
                                                if (percentpos!=-1)
                                                {
                                                        percentpos=percentpos-3;
                                                        /*dump up to percent*/

                                                        midstr(buffer_part,currentline->line,currentdoscol,percentpos);
                                                        myIText.IText=buffer_part;

                                        printf("doscol=%d currentdoscol=%d buffer-%s-\n",doscol,currentdoscol,buffer_part);

                                                        PrintIText(mywindow->RPort,&myIText,10+(10*(doscol-3)),10*currentline->lineno);  /*<<<<< why do I have to subtract 3????*/

                                                        /*colour for percent*/
                                                        myIText.FrontPen = white;
                                                        midstr(buffer_part,currentline->line,percentpos,percentpos+3);
                                                        myIText.IText=buffer_part;

                                                        printf("PERCENT BUFFER -%s- %d\n",buffer_part,percentpos);

                                                        [B]PrintIText(mywindow->RPort,&myIText,10+(10*(percentpos-9)),10*currentline->lineno); /*<<<<<< no idea why i need to subtract 9*/[/B]
       
                                                        myIText.FrontPen = black;
                                                        /*set up to print remainder - do we need to check size?*/

                                                        midstr(buffer,currentline->line,percentpos+4,tempfitchar);
                                                        myIText.IText=buffer;

                                                        charpos=percentpos+3;

                                                        PrintIText(mywindow->RPort,&myIText,10+(10*(charpos-9)),10*currentline->lineno);


                                                }
                                                else
                                                {
                                                        /*now print out*/
                                               
                                                        myIText.IText=buffer;
                                                        PrintIText(mywindow->RPort,&myIText,10+(10*charpos),10*currentline->lineno);
                                                }
                                        }
                                }
                                else /* cant find so dump*/
                                {
                                        myIText.FrontPen = black;
                                        myIText.IText=buffer;

                                        PrintIText(mywindow->RPort,&myIText,10,10*currentline->lineno);
                                }
                                break;

                        case 3:
                                myIText.FrontPen = white;
                                break;

                        default:
                                myIText.FrontPen = black;
                                break;
                }

                if (currentline->linetype!=2)
                {
                        myIText.IText=buffer;

                        PrintIText(mywindow->RPort,&myIText,10,10*currentline->lineno);
                }

                currentline=currentline->next;

        }
        free(buffer);        /*clear the buffers*/
        free(buffer_part);

                        printf("waiting press space\n");
                                zz=0;
                                while ((zz!=32) && (zz!='a'))
                                {
                                        zz=getchar();
                                        if (zz=='a')
                                                return 1;
                                        putchar(zz);
                                }

return 0;
}

This takes the info from the linked list in a while loop and using a couple of buffers (I need these as I do not know how long the lines could be) outputs the header, device name and percentage used in white and the rest of the text in black.
The 4 functions, findchar, midstr, leftstr and finddoscol are below:
Code:

int findchar(char string[], char letter)
{
        int result=-1;
        int i=0;
        while (string[i]!='\0')
        {
                if (string[i]==letter)
                        result=i;
                i++;
        }
        return result;
}

int midstr(char str1[], char str2[],int start,int last)
{
        int count,count2;
        count=start;count2=0;
        if (last!=NULL)
        {
                while ((str2[count]!='\0') && (count<=last))
                {
                        str1[count2]=str2[count];
                        count++;
                        count2++;
                }
        }
        else
        {
                while ((str2[count]!='\0'))
                {
                        str1[count2]=str2[count];
                        count++;
                        count2++;
                }
               
        }
        str1[count2]='\0';
        return count2;
}

int leftstr(char str1[],char str2[],int last)
{
        return midstr(str1,str2,0,last);
}

long finddoscol(char str[])
{
        int i=0;

        while((str[i]!='\0') && (str[i]!=' '))
                i++;

        if (str[i]=='\0')
                return i;

        while ((str[i]==' ') && (str[i]!='\0'))
                i++;

        return i;
}

The problem lines in write_win are marked, and below for clarity..
.
.
myIText.IText=buffer_part;

printf("doscol=%d currentdoscol=%d buffer-%s-\n",doscol,currentdoscol,buffer_part);

PrintIText(mywindow->RPort,&myIText,10+(10*(doscol-3)),10*currentline->lineno); /*<<<<< why do I have to subtract 3????*/

/*colour for percent*/
.
.

and
.
.
myIText.IText=buffer_part;

printf("PERCENT BUFFER -%s- %d\n",buffer_part,percentpos);

PrintIText(mywindow->RPort,&myIText,10+(10*(percentpos-9)),10*currentline->lineno); /*<<<<<< no idea why i need to subtract 9*/

myIText.FrontPen = black;
/*set up to print remainder - do we need to check size?*/
.
.
.
If I don't subtract 3 and 9 then the dos columns are 3 chars to the right of the header and the errors, status etc are 9 chars to the right of their cols.

Sorry this is such a long post, but could someone suggest where I have gone wrong? The values for doscol and currentdoscol are correct at 11, but the dos column etc is outputting starting 140 pixels from the left of the window (10+(currentdoscol*10)) should be 110! (I'm counting as the 1st char being 0)

I have no idea why :confused

alkis 29 August 2017 21:28

I still don't get what you are trying to do! :)

Are you doing all this to avoid clipping? So, that PrintIText doesn't (over)write on window borders?

if that's the case all you need to do is

Code:

    struct Region *reg;
    struct Region *oldreg;
    struct Rectangle rect;
   
    rect.MinX = myWindow->BorderLeft;
    rect.MinY = myWindow->BorderTop;
    rect.MaxX = myWindow->Width-myWindow->BorderRight-1;
    rect.MaxY = myWindow->Height-myWindow->BorderBottom-1;
    if (reg = NewRegion()) {
      OrRectRegion(reg, &rect);
      oldreg = InstallClipRegion(myWindow->WLayer, reg);
    }

and then you can use PrintIText and not worry about the borders.


full example code follows:
Code:

#include <intuition/intuition.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/exec.h>
#include <proto/gadtools.h>
#include <proto/layers.h>

#include <stdio.h>

int main(int argc, char *argv[])
{
  struct Window *myWindow;
  int closewin = FALSE;      /* Flag used to end program */
  struct IntuiMessage *msg;  /* Structure to store Intuition message data */
  ULONG msgClass;            /* Class value */
  /* For printing in Window */
  UBYTE result[255];
  struct IntuiText WinText = {1, 0, JAM1, 0, 0, NULL, &result[0], NULL};
  int x,y;

  if (myWindow = OpenWindowTags(NULL,
                          WA_Left,  100,
                          WA_Top,    100,
                          WA_Width,  100,
                          WA_Height, 100,
                          WA_MaxWidth, 600,
                          WA_MaxHeight, 400,
                          WA_Activate, TRUE,
                          WA_IDCMP,  IDCMP_CLOSEWINDOW | IDCMP_MOUSEMOVE | IDCMP_NEWSIZE,
                          WA_Flags,  WFLG_SMART_REFRESH | WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET    | WFLG_ACTIVATE | WFLG_REPORTMOUSE,
                          TAG_END))
  {
    struct Region *reg;
    struct Region *oldreg;
    struct Rectangle rect;
   
    rect.MinX = myWindow->BorderLeft;
    rect.MinY = myWindow->BorderTop;
    rect.MaxX = myWindow->Width-myWindow->BorderRight-1;
    rect.MaxY = myWindow->Height-myWindow->BorderBottom-1;
    if (reg = NewRegion()) {
      OrRectRegion(reg, &rect);
      oldreg = InstallClipRegion(myWindow->WLayer, reg);
    }   
    while (closewin == FALSE) { /* Run program until window is closed */
      Wait(1L << myWindow->UserPort->mp_SigBit);    /* Wait for an event! */
      msg = GT_GetIMsg(myWindow->UserPort);
      msgClass = msg->Class;
      GT_ReplyIMsg(msg);

      switch (msgClass) {
        case IDCMP_CLOSEWINDOW: /* Close window? */
          closewin = TRUE;
          break;
        case IDCMP_MOUSEMOVE: /* Mouse moved? */
          x = msg->MouseX;
          y = msg->MouseY;
          /* Print selection in window */
          sprintf(result, "X-coord: %d Y-coord: %d", x, y);
          SetRast(myWindow->RPort, 0);
          PrintIText(myWindow->RPort, &WinText, x, y);

          break;
        case IDCMP_NEWSIZE:
          if (reg) {
            InstallClipRegion(myWindow->WLayer, oldreg);
            DisposeRegion(reg);

            rect.MinX = myWindow->BorderLeft;
            rect.MinY = myWindow->BorderTop;
            rect.MaxX = myWindow->Width-myWindow->BorderRight-1;
            rect.MaxY = myWindow->Height-myWindow->BorderBottom-1;
            if (reg = NewRegion()) {
              OrRectRegion(reg, &rect);
              oldreg = InstallClipRegion(myWindow->WLayer, reg);
            }
          }
          break;
        }
    }
    if (reg) {
      InstallClipRegion(myWindow->WLayer, oldreg);
      DisposeRegion(reg);
    }
    CloseWindow(myWindow);
  }
  return 0;
}


chocsplease 31 August 2017 13:52

Quote:

Originally Posted by alkis (Post 1181206)
I still don't get what you are trying to do! :)

Are you doing all this to avoid clipping? So, that PrintIText doesn't (over)write on window borders?
<snip>


Well not just that but it is my current problem :).

I had no idea that you could set up a clip region like this, though it will take me a while to read though and understand the code you've so kindly posted.

Will this also work with SetRast(&rastPort, 0);? I'm hoping to use this to clear the window when someone swaps a disk.

Many thanks once again for such a great reply. :)

<edit>

Having looked at your code I'm a bit confused about the very last part ....

Code:

if (reg) {
      InstallClipRegion(myWindow->WLayer, oldreg);
      DisposeRegion(reg);
    }

It looks like you are creating a new region just before you close the window? Or have I got the loops wrong? Could you explain this bit please?

Many thanks.

alkis 31 August 2017 19:23

Yes, it will work with clearing the window, my example code actually does that in the MOUSEMOVE case.

Now, about the last part. Actually there I install the oldregion (oldreg always hold the region that was installed before any new clipregion is installed. So, think of it as 'restoring the old clip region'.

Reading the documentation might clear things better http://amigadev.elowar.com/read/ADCD.../node0399.html

PS: Also note, that whenever the size of the window changes, I dispose the new clip region, restore the old clip region, change the rect to the new window width and height and install a new clip region.

chocsplease 01 September 2017 01:09

Hi,

Many thanks for the explanation, I'll read the link.

At the moment my code sort of works but somehow kills Intuition, or I suspect it does.

Everything is fine the 1st time through and the window displays the correct info and clips correctly.

However the Amiga freezes solid as soon as I try and move the window or resize it. It never gets to the message handler (I've checked with printfs) and its not a Guru, it just locks.

I'm not at all sure how to debug this. This is the code I use to open the window, maybe there is something in this?

Code:

int open_window(int scrnwidth,int scrnheight)
{
    int topleftx=0,toplefty=0;
    int width=200,height=200;
    int tempw=0,temph=0;

    unsigned long maxchars=0;

    struct TextFont *font;
    UWORD font_width=0;

/*calculate 1 quarter of screen width*/

    if (mywindow)
        return 0; /*opened already*/

    tempw=scrnwidth/4;

/*calculate 1 5th screen height*/

    temph=scrnheight/5;

    topleftx=tempw;
    toplefty=temph;

    width=scrnwidth-(tempw*2);
    height=scrnheight-(temph*2);

    mywindow = OpenWindowTags(NULL, WA_Left, topleftx, WA_Top, toplefty,\
        WA_InnerWidth, width,  WA_InnerHeight, height,\
        WA_MinWidth,90,WA_MinHeight, 40, WA_MaxWidth, scrnwidth-20, WA_MaxHeight, scrnheight-20,\
        WA_IDCMP,IDCMP_CLOSEWINDOW  | IDCMP_DISKINSERTED | IDCMP_DISKREMOVED | IDCMP_NEWSIZE | IDCMP_REFRESHWINDOW,\
        WA_Flags, WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_ACTIVATE,\
        WA_Title, (ULONG)"Info64", WA_PubScreenName, (ULONG)"WorkBench", TAG_DONE);

    if (mywindow)
    {
        myIText.FrontPen    = myTEXTPEN;
                myIText.BackPen    = myBACKGROUNDPEN;
                myIText.DrawMode    = JAM2;
                myIText.LeftEdge    = MYTEXT_LEFT;
                myIText.TopEdge    = MYTEXT_TOP;
                myIText.ITextFont  = &myTextAttr;
                myIText.IText      = "Hello, World.  ;-)";
                myIText.NextText    = NULL;
        mywindowrastport=mywindow->RPort;

        oldwin_width=mywindow->Width;
        oldwin_height=mywindow->Height;

        /*open line buffers*/

        font=mywindow->RPort->Font;
        font_width=font->tf_XSize;

        maxchars=(scrnwidth/font_width)+1;

        win_buffer=malloc((maxchars+2)*sizeof(char)); /*make memory buffers for line plus null char*/
        win_buffer_part=malloc((maxchars+2)*sizeof(char));
        win_buffer_len=maxchars;

        win_rect.MinX = mywindow->BorderLeft;
        win_rect.MinY = mywindow->BorderTop;
        win_rect.MaxX = mywindow->Width-mywindow->BorderRight-1;
        win_rect.MaxY = mywindow->Height-mywindow->BorderBottom-1;
        if (win_reg = NewRegion())
            {
            OrRectRegion(win_reg, &win_rect);
            win_oldreg = InstallClipRegion(mywindow->WLayer, win_reg);
        }   
        return 0;
    }
    else
        return 1;
}

Here's hoping anyway


All times are GMT +2. The time now is 16:51.

Powered by vBulletin® Version 3.8.8 Beta 1
Copyright ©2000 - 2017, vBulletin Solutions, Inc.

Page generated in 0.14485 seconds with 10 queries