Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Console bug
#1
Running this program is Windows and Linux/macOS gives differing results. It appears that the functions CSRLIN and POS(0) only work correctly in Windows, when using $CONSOLE:ONLY.
Code: (Select All)
'CSRLIN and POS(0) bug
$CONSOLE:ONLY
LOCATE 10, 10
x = CSRLIN: y = POS(0)
PRINT "Cursor position :"; x; ", "; y

In Windows it reports the location as 10,10. In Linux/macOS it reports 1,1

I have found a workaround, so no big deal. I figured I'd bring it to your attention.
Reply
#2
Does it actually LOCATE in Linux?  I thought those were only Windows console commands.  I remember adding a lot of stuff like LOCATE into the console for us back a few years ago, but I had no clue how to implement them for Linux/Mac.  It may be that it's reporting the location properly for you just because it's not moving the print location from 1,1.
Reply
#3
(02-21-2026, 09:06 PM)SMcNeill Wrote: Does it actually LOCATE in Linux?  I thought those were only Windows console commands.  I remember adding a lot of stuff like LOCATE into the console for us back a few years ago, but I had no clue how to implement them for Linux/Mac.  It may be that it's reporting the location properly for you just because it's not moving the print location from 1,1.
LOCATE does work as you would expect in all three platforms. CLS and COLOR even work. 

The only way I have found to get the position in Linux/macOS is to use the escape sequence ESC[6n through a shell script and copy that to the clipboard, which is a bit of a hassle. If someones interested, I can post the code for that. Its not pretty.
Reply
#4
Well, I can confirm it wasn't a bug.  What you're seeing is the intended behavior here for unimplemented command usage.  It was like I suspected -- I don't know squat about Linux/Mac and when I expanded the console commands a while back, I could only expand them for Windows users.   Here's the source from libqb.cpp:

Code: (Select All)
int32 func_pos(int32 ignore) {
#ifdef QB64_WINDOWS
    if (write_page->console) { // qb64 console CSRLIN
        CONSOLE_SCREEN_BUFFER_INFO cl_bufinfo;
        SECURITY_ATTRIBUTES SecAttribs = {sizeof(SECURITY_ATTRIBUTES), 0, 1};
        HANDLE cl_conout = CreateFileA("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &SecAttribs, OPEN_EXISTING, 0, 0);
        GetConsoleScreenBufferInfo(cl_conout, &cl_bufinfo);
        return cl_bufinfo.dwCursorPosition.X + 1;
    }
#endif
    if (write_page->holding_cursor)
        return 1;
    return write_page->cursor_x;
}

If you're dealing with Windows and you're using POS and such with the console, it uses the windows funcrion GetConsoleScreenBufferInfo to return that information to you.

Otherwise it basically returns 1.   (Which is what you got as an answer.)

It's definitely nor a bug if it's doing exactly what it's told to do.  It's just an unimplemented command for Linux/Mac users with console.  Sorry there's no better news, but unless someone with more Linux/Mac experience than me wants to write a handler for the console to get that information back for us, it's just always going to return 1 for you.
Reply
#5
Well I'll go ahead and post a snippet of how I worked around that. The shell script was gleaned from Stackoverflow. The results are copied to the clipboard and then accessed by you program. Of course the snippet was bracketed by a meta condition of it being Linux.

Code: (Select All)
    'In linux, there is no easy way to get output of the
    'cursor position query "ESC[6n". One has to resort to
    'dirty tricks to get the output.
    DIM AS STRING script, clipboardTemp
    clipboardTemp = _CLIPBOARD$
    'If shell script doesn't exist create it
    IF NOT _FILEEXISTS("rc.sh") THEN
      f = FREEFILE
      script = script + "#!/bin/sh" + CHR$(10)
      script = script + "if [ -t 0 ] && [ -t 1 ]; then" + CHR$(10)
      'Save the terminal setting into a temp variable
      script = script + "  old_settings=$(stty -g) || exit" + CHR$(10)
      'In case of problem, restore settings
      script = script + "  trap 'stty " + CHR$(34) + "$(old_settings)" + CHR$(34) + "' INT TERM QUIT ALRM" + CHR$(10)
      'Set the terminal settings to receive the output of the query
      script = script + "  stty -icanon -echo min 0 time 3 || exit" + CHR$(10)
      'Make the query
      script = script + "  printf '\033[6n'" + CHR$(10)
      'Perform black magic to get the results of query
      script = script + "  pos=$(dd count=1 2> /dev/null)" + CHR$(10)
      script = script + "  pos=${pos%R*}" + CHR$(10)
      script = script + "  pos=${pos##*\[}" + CHR$(10)
      script = script + "  x=${pos##*;} y=${pos%%;*}" + CHR$(10)
      'Restore terminal state
      script = script + "  stty " + CHR$(34) + "$old_settings" + CHR$(34) + CHR$(10)
      script = script + "  trap - INT TERM QUIT ALRM" + CHR$(10)
      script = script + "fi" + CHR$(10)
      'Spit results to clipboard
      $IF MAC THEN
      script = script + "echo " + CHR$(34) + "$x:$y" + CHR$(34) + " | pbcopy" + CHR$(10)
      $ELSE
        script = script + "echo " + CHR$(34) + "$x:$y" + CHR$(34) + " | xclip -selection clipboard" + CHR$(10)
      $END IF
      OPEN "rc.sh" FOR OUTPUT AS f
      PRINT #f, script;
      CLOSE f
      'Make the script executable
      SHELL _HIDE "chmod +x rc.sh"
    END IF

    SHELL "./rc.sh"
    c$ = _CLIPBOARD$
    _CLIPBOARD$ = clipboardTemp
    y$ = LEFT$(c$, INSTR(c$, ":"))
    x$ = MID$(c$, INSTR(c$, ":") + 1)
    y = VAL(y$): x = VAL(x$)

There is also a way to do it in C. This is not my code, but I tested it and it does work.


Code: (Select All)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <string.h>

int getCursorPosition(int *x, int *y) {
    struct termios old_termios;
    char response[32];
    int i = 0;
    char c;
   
    // Save current terminal settings
    tcgetattr(STDIN_FILENO, &old_termios);
   
    // Set terminal to non-canonical mode
    struct termios new_termios = old_termios;
    new_termios.c_lflag &= ~(ICANON | ECHO);
    new_termios.c_cc[VMIN] = 0;
    new_termios.c_cc[VTIME] = 0;
    tcsetattr(STDIN_FILENO, TCSANOW, &new_termios);
   
    // Send cursor position request
    printf("\033[6n");
    fflush(stdout);
   
    // Read the response
    while (i < sizeof(response) - 1) {
        if (read(STDIN_FILENO, &c, 1) > 0) {
            response[i++] = c;
            if (c == 'R') break;
        }
    }
   
    response[i] = '\0';
   
    // Restore terminal settings
    tcsetattr(STDIN_FILENO, TCSANOW, &old_termios);
   
    // Parse response: ESC[<row>;<col>R
    if (i > 3 && response[0] == '\033' && response[1] == '[') {
        char *ptr = response + 2;
        char *end;
       
        *y = strtol(ptr, &end, 10);
        if (*end == ';') {
            *x = strtol(end + 1, NULL, 10);
            return 1;
        }
    }
   
    return 0;
}

int main() {
    int x, y;
   
    printf("Current cursor position:\n");
   
    if (getCursorPosition(&x, &y)) {
        printf("X = %d, Y = %d\n", x, y);
    } else {
        printf("Could not determine cursor position\n");
    }
   
    return 0;
}
Reply
#6
We have had talks of unifying the whole console experience by replacing all those custom implementations with something like PDCurses or a cross-platform conio.h implementation.

I've done some research on this, and I think it is doable. We just need to sort out a few other things first that are a bit more critical at this moment. But I'll add this to the GitHub issue tracker shortly.
Reply
#7
Curses in QB64PE would be absolutely killer @a740g

I am happy to help with this! Testing, whatever.
grymmjack (gj!)
GitHubYouTube | Soundcloud | 16colo.rs
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Setting Focus between console and terminal cage 4 1,380 09-01-2024, 02:44 AM
Last Post: cage
  Possible Bug SpriggsySpriggs 1 722 04-06-2024, 12:33 AM
Last Post: a740g
Bug D notation bug bplus 13 2,771 08-26-2023, 05:12 PM
Last Post: Jack

Forum Jump:


Users browsing this thread: 2 Guest(s)