{"id":7397,"date":"2026-02-14T00:01:47","date_gmt":"2026-02-14T08:01:47","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=7397"},"modified":"2026-02-21T10:18:51","modified_gmt":"2026-02-21T18:18:51","slug":"where-is-the-mouse","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=7397","title":{"rendered":"Where is the Mouse?"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701-300x167.jpg\" alt=\"\" width=\"300\" height=\"167\" class=\"alignnone size-medium wp-image-7374\" srcset=\"https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701-300x167.jpg 300w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701-1024x569.jpg 1024w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701-768x427.jpg 768w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701-1536x853.jpg 1536w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701-500x278.jpg 500w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701.jpg 2000w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><br \/>\nMonitoring the mouse in a terminal window happens thanks to various ANSI commands. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7378\">Last week&#8217;s Lesson<\/a> demonstrated how mouse clicks are detected. By issuing another ANSI command, the mouse&#8217;s location data is obtained, but doing so carelessly can create a horrid mess.<br \/>\n<!--more--><br \/>\nThe ANSI command to report the mouse&#8217;s location is <code>\\e[?1003h<\/code>, which I&#8217;ve assigned to the <em>mouse_motion()<\/em> macro. This macro is demonstrated in my <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7363\">original mouse monitoring post<\/a>. If you ran the code back then, you saw the program barf data all over the screen as you whip around the mouse.<\/p>\n<p>The following code is an update to the original mouse monitoring example. In this code, I borrow the terminal modification routines presented in last week&#8217;s Lesson. The main difference in the output is that <em>all<\/em> mouse activity is reported and output.<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2026_02_14-Lesson.c\" rel=\"noopener\" target=\"_blank\">2026_02_14-Lesson.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;termios.h&gt;\r\n#include &lt;unistd.h&gt;\r\n\r\n#define mouse_enable() printf(\"\\e[?1000h\")\r\n#define mouse_extended() printf(\"\\e[?1006h\")\r\n#define mouse_motion() printf(\"\\e[?1003h\")\r\n#define mouse_disable() printf(\"\\e[?1000l\")\r\n\r\nint main()\r\n{\r\n    struct termios original,noecho;\r\n    char buffer[12];\r\n    int key;\r\n\r\n    <span class=\"comments\">\/* obtain terminal configuration *\/<\/span>\r\n    tcgetattr(fileno(stdin),&amp;original);\r\n    noecho = original;        <span class=\"comments\">\/* duplicate *\/<\/span>\r\n        <span class=\"comments\">\/* enable raw input *\/<\/span>\r\n    noecho.c_lflag = noecho.c_lflag ^ ICANON;\r\n        <span class=\"comments\">\/* disable full duplex *\/<\/span>\r\n    noecho.c_lflag = noecho.c_lflag ^ ECHO;\r\n        <span class=\"comments\">\/* update terminal definition *\/<\/span>\r\n    tcsetattr(fileno(stdin), TCSANOW, &amp;noecho);\r\n\r\n    <span class=\"comments\">\/* enable mouse reporting *\/<\/span>\r\n    mouse_enable();\r\n    mouse_motion();\r\n    mouse_extended();\r\n    <span class=\"comments\">\/* remove line buffering *\/<\/span>\r\n    setvbuf(stdin,NULL,_IONBF,0);\r\n\r\n    <span class=\"comments\">\/* read stdin *\/<\/span>\r\n    puts(\"Play with the mouse; press Enter to end\");\r\n    while( (key=getchar()) != '\\n' )\r\n    {\r\n        read(fileno(stdin),buffer,12);\r\n        write(fileno(stdout),buffer,12);\r\n        putchar('\\n');\r\n    }\r\n\r\n    <span class=\"comments\">\/* clean-up *\/<\/span>\r\n    mouse_disable();    <span class=\"comments\">\/* disable mouse reporting *\/<\/span>\r\n    tcsetattr(fileno(stdin), TCSANOW, &amp;original);\r\n    return 0;\r\n}<\/pre>\n<p>This code adds the <em>mouse_motion()<\/em> macro to the code presented last week. It&#8217;s effect is that all mouse movement appears in the output. And moving the mouse while the program runs generates a lot of output, as you can see in the following sample output:<\/p>\n<pre>Play with the mouse; press Enter to end\r\n[<35;71;19M\r\n[<35;70;19M\r\n[<35;70;20M\r\n[<35;69;20M\r\n[<35;68;20M\r\n[<35;67;20M\r\n[<35;67;21M\r\n[<35;66;21M\r\n[<35;65;21M\r\n[<35;65;20M\r\n...<\/pre>\n<p>The first value, 35, indicates mouse movement. The next two values are column and row values. Each time the mouse changes a character position, new data is output.<\/p>\n<p>Clicking the mouse results in output like this:<\/p>\n<pre>[<0;37;14MM\r\n[<0;37;14mM<\/pre>\n<p>The value zero represents the left mouse button. Big M means that the button is pressed and little M means that the button is released. But you see extra garbage in the buffer, leftover characters from the previous call: The big M at the end of the data. This residue is only part of the problem when it comes to capturing this data.<\/p>\n<blockquote><p>The program reads terminal input directly. The data recorded is saved in a character buffer; it's not a string.<\/p><\/blockquote>\n<p>While outputting the mouse data is interesting, it's only useful when the data can be stored. I provide this update in <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7411\">next week's Lesson<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Monitoring mouse movement is possible, but presents some ugly problems. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7397\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-7397","post","type-post","status-publish","format-standard","hentry","category-main"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7397","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7397"}],"version-history":[{"count":5,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7397\/revisions"}],"predecessor-version":[{"id":7438,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7397\/revisions\/7438"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7397"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7397"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7397"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}