diff --git a/console.c b/console.c index 35fd961..3fc65a4 100644 --- a/console.c +++ b/console.c @@ -16,6 +16,13 @@ #include "x86.h" #define INPUT_BUF 128 +// Proc title length + 3 for the console id + 2 for the left and right border + 2 for space between +#define MENUWIDTH 27 +// Number of max consoles + 1 for bottom border and another 2 for a space between top and bottom +#define MENUHEIGHT (MAXVCONSOLES + 3); + +static int currentmenuitem = 0; +static int menuactive = 0; struct kbdbuffer { @@ -54,7 +61,7 @@ struct vconsole* getvalidprocessconsoleptr(void); void clearconsole(ushort *bufferin); void loadscreenbuffer(ushort *bufferin); void savescreenbuffer(ushort *bufferin); -void clearscreen(void); +void clearscreen(int prelocked); static void consputc(int); @@ -73,6 +80,66 @@ static struct int locking; } vcons; +static int getcurrentactiveconsolecount(void) +{ + int resultcount = 0; + for (int i = 0; i < MAXVCONSOLES; i++) + { + if (consoles[i].active) + { + resultcount++; + } + } + + return resultcount; +} + +static int getconsolemenuindex(struct vconsole* consolein) +{ + int resultcount = 0; + for (int i = 0; i < MAXVCONSOLES; i++) + { + if (&consoles[i] == consolein && consoles[i].active) + { + break; + } + else + { + resultcount++; + } + } + + return resultcount; +} + +static int getmenuindexconsole(int menuindex) +{ + int resultcount = 0; + int resultconsoleindex = 0; + for (int i = 0; i < MAXVCONSOLES; i++) + { + if (consoles[i].active) + { + if (resultcount == menuindex) + { + resultconsoleindex = consoles[i].consoleindex; + break; + } + else + { + resultcount++; + } + } + } + + return resultconsoleindex; +} + +int getconsoleindex(struct vconsole* consolein) +{ + return consolein->consoleindex; +} + // Split the printint so we can just get the char out in draw title // itoa is the function in the c standard library (?) so i reused the name // since it does something similar @@ -248,9 +315,9 @@ void sprintf(char* strbuffer, char *fmt, ...) { s = "(null)"; } - for (; *s; s++) + for (int sli = 0; sli < strlen(s); sli++) { - strbuffer[si] = *s; + strbuffer[si] = s[sli]; si++; } break; @@ -328,66 +395,169 @@ struct vconsole* getvalidprocessconsoleptr(void) return inconsoleptr; } -void setconsoleproctitle(struct vconsole* consoleptr, char* newtitle) -{ - if (!consoleptr->titlelocked) - { - acquire(&consoleptr->lock); - //Clear the current buffer - memset(consoleptr->proctitle, 0, sizeof(consoleptr->proctitle)); - //Copy the new title into the console title buffer - safestrcpy(consoleptr->proctitle, newtitle, sizeof(consoleptr->proctitle)); - //Redraw the title since its been updated now - drawtitle(); - release(&consoleptr->lock); - } -} - #define BACKSPACE 0x100 #define CRTPORT 0x3d4 #define TITLEOFF (SCRWIDTH * 1) // Size of the offset we need for the title bar static ushort *crt = (ushort *)P2V(0xb8000); // CGA memory -void drawtitle(void) +static void drawmenu(void) { struct vconsole* inconsoleptr = getvalidprocessconsoleptr(); - - if (inconsoleptr->inuse) - { - int pos = 0; - char c = ' '; - char menutext[] = "(M)enu"; - char consoletitletext[10]; // + (inconsoleptr->consoleindex + 1); - sprintf(consoletitletext, "Console %d", inconsoleptr->consoleindex + 1); - - for (pos = 0; pos < SCRWIDTH; pos++) + int rows = getcurrentactiveconsolecount() + 3; + int pos = TITLEOFF; + uint c = 0; + char menulines[MAXVCONSOLES][24]; + + for (int i = 0; i < MAXVCONSOLES; i++) + { + if (consoles[i].active) + { + memset(menulines[i], 0, sizeof(menulines[i][0]) * sizeof(menulines[i])); + sprintf(menulines[i], "%d: %s", consoles[i].consoleindex, consoles[i].proctitle); + } + } + + for (int y = 0; y < rows; y++) + { + pos = TITLEOFF + (y * SCRWIDTH); + for (int x = 0; x < MENUWIDTH; x++) { - int offset = 0; - if (pos < 6) { - c = menutext[pos - offset]; - } - else if (pos >= 10 && pos < 20) + if (y == 0 || y == (rows - 2)) { - offset = 10; - c = consoletitletext[pos - offset]; - } - else if (pos >= 25 && pos < 45) + if (x == 0 || x == (MENUWIDTH - 1)) + { + c = 0xB2 | inconsoleptr->titlebgcol; + } + else + { + c = 0x0720; + } + } + else if (y == (rows - 1)) { - offset = 25; - c = inconsoleptr->proctitle[pos - offset]; - } - else if (pos >= 50 && pos < 80) - { - offset = 50; - c = inconsoleptr->status[pos - offset]; + c = 0xB2 | inconsoleptr->titlebgcol; } else { - c = ' '; + if (x == 0 || x == (MENUWIDTH - 1)) + { + c = 0xB2 | inconsoleptr->titlebgcol; + } + else if (x == 1 || x == (MENUWIDTH - 2)) + { + c = 0x0720; + } + else + { + c = menulines[y - 1][x - 2]; + c = (c & 0xff); + if (currentmenuitem == (y - 1)) + { + c = c | 0xCF00; + } + else + { + c = c | 0x0700; + } + } + } + crt[pos] = c; + pos++; + } + } + + menuactive = 1; +} + +static void navigatemenu(int dir) +{ + int pos = 0; + int newindex = currentmenuitem + dir; + int totalactiveconsoles = getcurrentactiveconsolecount(); + + if (newindex < 0) + { + newindex = 0; + } + else if (newindex >= totalactiveconsoles) + { + newindex = totalactiveconsoles - 1; + } + + if (newindex != currentmenuitem) + { + pos = TITLEOFF + ((currentmenuitem + 1) * SCRWIDTH); + for (int x = 2; x < MENUWIDTH - 2; x++) + { + crt[pos + x] = (crt[pos + x] & 0x00FF) | 0x0700; + } + + pos = TITLEOFF + ((newindex + 1) * SCRWIDTH); + for (int x = 2; x < MENUWIDTH - 2; x++) + { + crt[pos + x] = crt[pos + x] | 0xCF00; + } + + currentmenuitem = newindex; + } +} + +static void closemenu(void) +{ + loadscreenbuffer(currentconsole->screenbuffer); + + int pos = currentconsole->pos; + + outb(CRTPORT, 14); + outb(CRTPORT + 1, pos >> 8); + outb(CRTPORT, 15); + outb(CRTPORT + 1, pos); + menuactive = 0; +} + +static void drawtitle(void) +{ + struct vconsole* inconsoleptr = getvalidprocessconsoleptr(); + + int pos = 0; + char c = ' '; + char menutext[] = "(M)enu"; + char consoletitletext[10]; // + (inconsoleptr->consoleindex + 1); + sprintf(consoletitletext, "Console %d", inconsoleptr->consoleindex); + + for (pos = 0; pos < SCRWIDTH; pos++) + { + int offset = 0; + if (pos < 6) { + c = menutext[pos - offset]; + } + else if (pos >= 10 && pos < 20) + { + offset = 10; + c = consoletitletext[pos - offset]; + } + else if (pos >= 25 && pos < 45) + { + offset = 25; + c = inconsoleptr->proctitle[pos - offset]; + } + else if (pos >= 50 && pos < 80) + { + offset = 50; + c = inconsoleptr->status[pos - offset]; + } + else + { + c = ' '; + } + + if (inconsoleptr->inuse) + { crt[pos] = (c & 0xff) | inconsoleptr->titlebgcol; } + inconsoleptr->screenbuffer[pos] = (c & 0xff) | inconsoleptr->titlebgcol; } } @@ -445,7 +615,17 @@ static void cgaputc(int c) memset(currentbuffer + pos, 0, sizeof(crt[0]) * (SCRHEIGHT * SCRWIDTH - pos)); if (inconsoleptr->inuse) { - memmove(crt + TITLEOFF, crt + (SCRWIDTH + TITLEOFF), sizeof(crt[0]) * (SCRHEIGHT - 1) * SCRWIDTH); + int menuoffset = 0; + if (menuactive) + { + int menuitems = getcurrentactiveconsolecount() + 3; + for (int y = 0; y < menuitems; y++) + { + memmove(crt + menuoffset + TITLEOFF + MENUWIDTH, crt + menuoffset + (SCRWIDTH + TITLEOFF) + MENUWIDTH, sizeof(crt[0]) * (SCRWIDTH - MENUWIDTH)); + menuoffset += SCRWIDTH; + } + } + memmove(crt + TITLEOFF + menuoffset, crt + (SCRWIDTH + TITLEOFF) + menuoffset, (sizeof(crt[0]) * (SCRHEIGHT - 1) * SCRWIDTH) - menuoffset); memset(crt + pos, 0, sizeof(crt[0]) * (SCRHEIGHT * SCRWIDTH - pos)); } } @@ -510,6 +690,7 @@ void consoleintr(int (*getc)(void)) int c; int doprocdump = 0; int doconsoleswitch = 0; + int switchto = -1; int doconsolehome = 0; //struct vconsole* inconsoleptr = getvalidprocessconsoleptr(); struct kbdbuffer* consolekbdbuffer = ¤tconsole->keybuffer; @@ -518,7 +699,27 @@ void consoleintr(int (*getc)(void)) while ((c = getc()) >= 0) { switch (c) - { + { + case 27: + if (menuactive) + { + closemenu(); + } + break; + // Up arrow (found in kbd.h) + case 0xE2: + if (menuactive) + { + navigatemenu(-1); + } + break; + // Down arrow (found in kbd.h) + case 0xE3: + if (menuactive) + { + navigatemenu(1); + } + break; case C('P'): // Process listing. // procdump() locks cons.lock indirectly; invoke later doprocdump = 1; @@ -545,16 +746,40 @@ void consoleintr(int (*getc)(void)) case C('K'): doconsolehome = 1; break; - default: - if (c != 0 && consolekbdbuffer->e - consolekbdbuffer->r < INPUT_BUF) + case C('M'): + if (!menuactive) { - c = (c == '\r') ? '\n' : c; - consolekbdbuffer->buf[consolekbdbuffer->e++ % INPUT_BUF] = c; - consputc(c); - if (c == '\n' || c == C('D') || consolekbdbuffer->e == consolekbdbuffer->r + INPUT_BUF) + drawmenu(); + } + else + { + closemenu(); + } + break; + // If enter is hit and the menu is active then we want to override the normal behaviour + case 10: + if (menuactive) + { + closemenu(); + switchto = currentmenuitem; + doconsoleswitch = 1; + // The menu has been sorted we can break from the switch + break; + } + // if the menu was not active we want the enter to be handled in the default case + default: + if (!menuactive) + { + if (c != 0 && consolekbdbuffer->e - consolekbdbuffer->r < INPUT_BUF) { - consolekbdbuffer->w = consolekbdbuffer->e; - wakeup(&(consolekbdbuffer->r)); + c = (c == '\r') ? '\n' : c; + consolekbdbuffer->buf[consolekbdbuffer->e++ % INPUT_BUF] = c; + consputc(c); + if (c == '\n' || c == C('D') || consolekbdbuffer->e == consolekbdbuffer->r + INPUT_BUF) + { + consolekbdbuffer->w = consolekbdbuffer->e; + wakeup(&(consolekbdbuffer->r)); + } } } break; @@ -562,7 +787,7 @@ void consoleintr(int (*getc)(void)) } release(&cons.lock); - if (doprocdump) + if (doprocdump && !menuactive) { procdump(); // now call procdump() wo. cons.lock held } @@ -577,17 +802,24 @@ void consoleintr(int (*getc)(void)) { struct vconsole* toconsole = 0; acquire(&cons.lock); - for (int i = (currentconsole->consoleindex + 1); i < MAXVCONSOLES; i++) - { - if (consoles[i].active) + if (switchto == -1) + { + for (int i = (currentconsole->consoleindex + 1); i < MAXVCONSOLES; i++) { - toconsole = &consoles[i]; - break; + if (consoles[i].active) + { + toconsole = &consoles[i]; + break; + } + } + if (toconsole == 0) + { + toconsole = getbaseconsoleptr(); } } - if (toconsole == 0) + else { - toconsole = getbaseconsoleptr(); + toconsole = &consoles[getmenuindexconsole(switchto)]; } release(&cons.lock); if (!toconsole->inuse) @@ -664,6 +896,7 @@ int consolewrite(struct inode *ip, char *buf, int n) return n; } +// Function to flood a buffer with A-Z characters looping (for testing initially) void testfillbuffer(ushort *bufferin) { ushort firstchar = 65; @@ -706,12 +939,15 @@ void savescreenbuffer(ushort *bufferin) memmove(bufferin, crt, sizeof(crt[0]) * SCRHEIGHT * SCRWIDTH); } -void clearscreen(void) +void clearscreen(int prelocked) { // Check if a process has actually been created otherwise use the base console struct vconsole* inconsoleptr = getvalidprocessconsoleptr(); - acquire(&cons.lock); + if (!prelocked) + { + acquire(&cons.lock); + } int pos = TITLEOFF; clearconsole(inconsoleptr->screenbuffer); inconsoleptr->pos = pos; @@ -726,7 +962,10 @@ void clearscreen(void) outb(CRTPORT + 1, pos); } drawtitle(); - release(&cons.lock); + if (!prelocked) + { + release(&cons.lock); + } } void consoleinit(void) @@ -758,7 +997,7 @@ void consoleinit(void) devsw[CONSOLE].read = consoleread; cons.locking = 1; - clearscreen(); + clearscreen(0); cprintf("Welcome! you are currently in the base console\n"); ioapicenable(IRQ_KBD, 0); @@ -807,18 +1046,19 @@ int switchtoconsole(struct vconsole* consoleptr) { int pos; - acquire(&vcons.lock); + acquire(&vcons.lock); releaseallconsoles(); currentconsole = consoleptr; currentconsole->inuse = 1; //input = ¤tconsole->keybuffer; // ioapicenable(IRQ_KBD, 0); + acquire(&cons.lock); loadscreenbuffer(currentconsole->screenbuffer); if (!currentconsole->active) { - clearscreen(); + clearscreen(1); cprintf("Welcome to Console: %d\n", currentconsole->consoleindex); currentconsole->active = 1; } @@ -832,8 +1072,11 @@ int switchtoconsole(struct vconsole* consoleptr) outb(CRTPORT + 1, pos); } - drawtitle(); - release(&vcons.lock); + //drawtitle(); + menuactive = 0; + currentmenuitem = getconsolemenuindex(currentconsole); + release(&cons.lock); + release(&vcons.lock); return 0; } @@ -873,4 +1116,21 @@ int getcurrentconsoleindex(void) } release(&vcons.lock); return -1; +} + +void setconsoleproctitle(struct vconsole* consoleptr, char* newtitle) +{ + if (!consoleptr->titlelocked) + { + acquire(&consoleptr->lock); + //Clear the current buffer + memset(consoleptr->proctitle, 0, sizeof(consoleptr->proctitle[0]) * sizeof(consoleptr->proctitle)); + //Copy the new title into the console title buffer + safestrcpy(consoleptr->proctitle, newtitle, sizeof(consoleptr->proctitle)); + + //Redraw the title since its been updated now + drawtitle(); + + release(&consoleptr->lock); + } } \ No newline at end of file diff --git a/defs.h b/defs.h index faa4910..d5d89d8 100644 --- a/defs.h +++ b/defs.h @@ -32,13 +32,14 @@ int closeconsole(void); // Function to get the current inuse console index int getcurrentconsoleindex(void); // Function to clear the current screen buffer -void clearscreen(void); +void clearscreen(int); // Function to get the base consoles ptr struct vconsole* getbaseconsoleptr(void); // Function to provide cprintf functionality but saved into a char array void sprintf(char*, char*, ...); void setconsoleproctitle(struct vconsole* consoleptr, char* newtitle); -void drawtitle(); +//void drawtitle(); +int getconsoleindex(struct vconsole* consolein); // exec.c int exec(char*, char**); diff --git a/maze.c b/maze.c index a8207ea..8250db2 100644 --- a/maze.c +++ b/maze.c @@ -45,13 +45,22 @@ int main(int argc, char *argv[]) { seed = atoi(argv[i + 1]); } } - + cls(); + greeting(); printf(1, "Start Maze\n"); + + char mazeline[80]; for (int y = 0; y < lines; y++) { - for (int x = 0; x < 80; x++) + for (int x = 0; x < 79; x++) { + if (x == 0) + { + mazeline[x] = ' '; + continue; + } + int rndnum = rngrange(188, 197, seed); switch (rndnum) { @@ -65,10 +74,12 @@ int main(int argc, char *argv[]) { rndnum = 180; break; } - printf(1, "%c", rndnum); - - } - //printf(1, "\n"); + // This is causing huge lock ups due to having to lock the console for each character + // is what im guessing so instead write it to a per line buffer then print + //printf(1, "%c", rndnum); + mazeline[x] = rndnum; + } + printf(1, "%s\n", mazeline); sleep(10); } printf(1, "Maze Ended\n"); diff --git a/proc.c b/proc.c index d7507b6..3656987 100644 --- a/proc.c +++ b/proc.c @@ -522,6 +522,8 @@ void procdump(void) { char *state; uint pc[10]; + cprintf("Listing Processes\nPid(Parent) State Name(console)\n"); + cprintf("-------------------------------\n"); for (p = ptable.proc; p < &ptable.proc[NPROC]; p++) { if (p->state == UNUSED) { continue; @@ -532,10 +534,18 @@ void procdump(void) { else { state = "???"; } - cprintf("%d %s %s", p->pid, state, p->name); + + int parentpid = 0; + if (p->parent != 0x0) + { + parentpid = p->parent->pid; + } + + cprintf("%d(%d) %s %s(%d)", p->pid, parentpid, state, p->name, getconsoleindex(p->consoleptr)); if (p->state == SLEEPING) { getcallerpcs((uint*)p->context->ebp + 2, pc); - for (i = 0; i < 10 && pc[i] != 0; i++) { + // was 10 + for (i = 0; i < 5 && pc[i] != 0; i++) { cprintf(" %p", pc[i]); } } diff --git a/sysproc.c b/sysproc.c index 604551a..79373e9 100644 --- a/sysproc.c +++ b/sysproc.c @@ -98,7 +98,7 @@ int sys_greeting(void) cprintf("Using Console: %d\n", getcurrentconsoleindex()); cprintf("Current PID: %d\n", myproc()->pid); cprintf("Current Parent PID: %d\n", myproc()->parent->pid); - //cprintf("Process Console: %d\n", myproc()->consoleptr->consoleindex); + cprintf("Process Console: %d\n", getconsoleindex(myproc()->consoleptr)); return 0; } @@ -154,6 +154,6 @@ int sys_screen(void) int sys_cls(void) { - clearscreen(); + clearscreen(0); return 0; } \ No newline at end of file