ARPDAS_QNX6 1.0
nlphcmd.c
Go to the documentation of this file.
00001 /* Standard headers */
00002 #include <stdio.h>
00003 #include <stdlib.h>
00004 #include <unistd.h>
00005 #include <string.h>
00006 #include <semaphore.h>
00007 #include <pthread.h>
00008 #include <errno.h>
00009 #include <ctype.h>
00010 #include <Pt.h>
00011 #include "nortlib.h"
00012 #include "tablelib.h"
00013 #include "nlphcmd.h"
00014 #include "tm.h"
00015 
00016 
00017 static sem_t char_sem;
00018 static pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER;
00019 #define QUEUE_LENGTH 10
00020 typedef struct {
00021   int head;
00022   int tail;
00023   int chars[QUEUE_LENGTH];
00024 } queue_t;
00025 static queue_t queue;
00026 static int my_key_event( PtWidget_t *widget, void *apinfo,
00027           PtCallbackInfo_t *cbinfo );
00028 
00029 static int cmd_quit_fd;
00030 static PtWidget_t *cmd_window;
00031 static PtWidget_t *cmd_text;
00032 static PtWidget_t *cmd_prompt;
00033 
00034 static PtWidget_t *new_cmd_window( char *title, int width, int height ) {
00035   PtArg_t args[8];
00036   PtSetArg(&args[0], Pt_ARG_WINDOW_TITLE, title, 0);
00037   PtSetArg(&args[1], Pt_ARG_WINDOW_MANAGED_FLAGS,
00038       Pt_FALSE, Ph_WM_MAX | Ph_WM_RESIZE );
00039   PtSetArg(&args[2], Pt_ARG_WINDOW_MANAGED_FLAGS,
00040       Pt_TRUE, Ph_WM_COLLAPSE );
00041   PtSetArg(&args[3], Pt_ARG_WIDTH, width, 0);
00042   PtSetArg(&args[4], Pt_ARG_HEIGHT, height, 0);
00043   PtSetArg(&args[5], Pt_ARG_WINDOW_RENDER_FLAGS,
00044       Pt_FALSE, Ph_WM_RENDER_MAX | Ph_WM_RENDER_RESIZE );
00045   PtSetArg(&args[6], Pt_ARG_WINDOW_RENDER_FLAGS,
00046       Pt_TRUE, Ph_WM_RENDER_COLLAPSE );
00047   PtSetArg(&args[7], Pt_ARG_FILL_COLOR, PgGray(100), 0);
00048   return PtCreateWidget( PtWindow, Pt_NO_PARENT, 8, args );
00049 }
00050 
00051 static PtWidget_t *new_text_widget( PtWidget_t *window, char *text,
00052                 int x, int y, char *font, PgColor_t color, int align ) {
00053   PhPoint_t pos;
00054   PtArg_t args[12];
00055 
00056   pos.x = x; pos.y = y;
00057   PtSetArg(&args[0], Pt_ARG_TEXT_STRING, text, 0);
00058   PtSetArg(&args[1], Pt_ARG_POS, &pos, 0 );
00059   PtSetArg(&args[2], Pt_ARG_TEXT_FONT, font, 0 );
00060   PtSetArg(&args[3], Pt_ARG_COLOR, color, 0 );
00061   PtSetArg(&args[4], Pt_ARG_HORIZONTAL_ALIGNMENT, align, 0 );
00062   PtSetArg(&args[5], Pt_ARG_MARGIN_WIDTH, 4, 0 );
00063   PtSetArg(&args[6], Pt_ARG_MARGIN_HEIGHT, 4, 0 );
00064   PtSetArg(&args[7], Pt_ARG_FILL_COLOR, PgGray(220), 0);
00065   PtSetArg(&args[8], Pt_ARG_BASIC_FLAGS,
00066     Pt_HORIZONTAL_GRADIENT | Pt_REVERSE_GRADIENT |
00067     Pt_TOP_OUTLINE | Pt_LEFT_OUTLINE,
00068     Pt_HORIZONTAL_GRADIENT | Pt_REVERSE_GRADIENT |
00069     Pt_TOP_OUTLINE | Pt_LEFT_OUTLINE | Pt_FLAT_FILL |
00070     Pt_ALL_BEVELS );
00071   PtSetArg(&args[9], Pt_ARG_OUTLINE_COLOR, PgGray(20), 0);
00072   PtSetArg(&args[10], Pt_ARG_FLAGS, Pt_TRUE, Pt_HIGHLIGHTED );
00073   // PtSetArg(&args[11], Pt_ARG_BEVEL_WIDTH, 2, 0 );
00074   return PtCreateWidget(PtLabel, window, 11, args);
00075 }
00076 
00077 #define LABEL_HEIGHT 25
00078 #define LABEL_FULL_HEIGHT (LABEL_HEIGHT+4)
00079 #define LABEL_SPACE 6
00080 #define LABEL_WIDTH 780
00081 #define LABEL_FULL_WIDTH (LABEL_WIDTH+4)
00082 #define WINDOW_HEIGHT (2*LABEL_FULL_HEIGHT + 3*LABEL_SPACE + 1)
00083 #define WINDOW_WIDTH (LABEL_FULL_WIDTH  + 2*LABEL_SPACE)
00084 #define LOGO_WIDTH 20
00085 
00086 static int cic_cmd_quit_func( int fd, void *data, unsigned mode ) {
00087   cic_reset();
00088   PtEnter(0);
00089   PtExit(0);
00090   return Pt_END;
00091 }
00092 
00093 void nlph_cmdclt_init( void *(*cmd_thread)(void*)) {
00094   pthread_attr_t attr;
00095   PhDim_t dim;
00096 
00097   cic_init();
00098   PtInit(NULL);
00099   cmd_window = new_cmd_window("cmd_name", WINDOW_WIDTH, WINDOW_HEIGHT );
00100   cmd_prompt = new_text_widget( cmd_window, "prompt",
00101         LABEL_SPACE, LABEL_FULL_HEIGHT + 2*LABEL_SPACE,
00102          "FixedFont10", Pg_BLACK, Pt_LEFT );
00103   dim.w = LABEL_WIDTH; dim.h = LABEL_HEIGHT;
00104   PtSetResource( cmd_prompt, Pt_ARG_DIM, &dim, 0 );
00105 
00106   cmd_text = new_text_widget( cmd_window, "text",
00107         LOGO_WIDTH + 2*LABEL_SPACE, LABEL_SPACE,
00108          "FixedFont10", Pg_BLACK, Pt_LEFT );
00109   dim.w = LABEL_WIDTH-LOGO_WIDTH-LABEL_SPACE;
00110   dim.h = LABEL_HEIGHT;
00111   PtSetResource( cmd_text, Pt_ARG_DIM, &dim, 0 );
00112 
00113   // PgDrawPolygon();
00114   // Wrong: need to create a PtPolygon widget.
00115   PtAddFilterCallback( cmd_window, Ph_EV_KEY, my_key_event, NULL );
00116 
00117   if ( cic_cmd_quit_fd != -1 &&
00118        PtAppAddFd( NULL, cic_cmd_quit_fd, Pt_FD_READ,
00119                cic_cmd_quit_func, NULL) )
00120     nl_error( 1, "Unable to initialize cmd/Quit link" ); 
00121 
00122   if ( sem_init( &char_sem, 0, 0 ) )
00123     nl_error( 4, "sem_init failed" );
00124 
00125   pthread_attr_init( &attr );
00126   //pthread_attr_setdetachstate(
00127   //    &attr, PTHREAD_CREATE_DETACHED );
00128   pthread_create( NULL, &attr, cmd_thread, NULL );
00129 
00130   PtRealizeWidget(cmd_window);
00131   PtMainLoop();
00132 }
00133 
00134 static void enqueue_char( int c ) {
00135   int rv;
00136   rv = pthread_mutex_lock( &queue_mutex );
00137   if ( rv == EOK ) {
00138     int newtail = queue.tail + 1;
00139     if (newtail >= QUEUE_LENGTH) newtail = 0;
00140     if (newtail != queue.head ) {
00141       queue.chars[queue.tail] = c;
00142       queue.tail = newtail;
00143       rv = sem_post( &char_sem );
00144       if ( rv != 0 )
00145         nl_error( 2, "sem_post returned errno %d", errno );
00146     }
00147     rv = pthread_mutex_unlock( &queue_mutex );
00148     if ( rv != EOK )
00149       nl_error( 2, "pthread_mutex_unlock returned %d", rv );
00150   } else nl_error( 2, "pthread_mutex_lock returned %d", rv );
00151 }
00152 
00153 int nlph_getch( void ) {
00154   int rv, c;
00155   rv = sem_wait(&char_sem);
00156   if ( rv != 0 ) nl_error( 4, "sem_wait returned errno %d", errno );
00157   rv = pthread_mutex_lock( &queue_mutex );
00158   if ( rv == EOK ) {
00159     if ( queue.head == queue.tail )
00160       nl_error( 4, "char queue is empty" );
00161     c = queue.chars[queue.head];
00162     if ( ++queue.head >= QUEUE_LENGTH )
00163       queue.head = 0;
00164     rv = pthread_mutex_unlock( &queue_mutex );
00165     if ( rv != EOK )
00166       nl_error( 2, "pthread_mutex_unlock returned %d", rv );
00167     return c;
00168   } else nl_error( 4, "pthread_mutex_lock returned %d", rv );
00169   return 0;
00170 }
00171 
00172 static int my_key_event( PtWidget_t *widget, void *apinfo,
00173           PtCallbackInfo_t *cbinfo ) {
00174   PhEvent_t *event = cbinfo->event;
00175   PhKeyEvent_t *keyevent = PhGetData(event);
00176 
00177   /* eliminate 'unreferenced' warnings */
00178   widget = widget, apinfo = apinfo, cbinfo = cbinfo;
00179 
00180   if ( keyevent->key_flags & Pk_KF_Sym_Valid ) {
00181     unsigned long sym = keyevent->key_sym;
00182     /* we will only enqueue characters cmdgen understands */
00183     switch ( sym ) {
00184       case 0xF008: sym = 0x8; break;
00185       case 0xF009: sym = 0x9; break;
00186       case 0xF00D: sym = 0xD; break;
00187       case 0xF01B: sym = 0x1B; break;
00188       case 0xF07F: sym = 0x7F; break;
00189       default:
00190         if ( sym >= 0x80 || !isprint(sym) )
00191           sym = 0;
00192         break;
00193     }
00194     if (sym) {
00195       // if ( isgraph(sym) ) nl_error( 0, "enqueue: '%c'", sym );
00196       // else nl_error( 0, "enqueue: 0x%X", sym );
00197       enqueue_char(sym);
00198     }
00199   } else {
00200     nl_error(-3, "  %s%s%s %s %s%lX\n",
00201       (keyevent->key_mods & Pk_KM_Ctrl) ? "C" : " ",
00202       (keyevent->key_mods & Pk_KM_Shift) ? "S" : " ",
00203       (keyevent->key_mods & Pk_KM_Alt) ? "A" : " ",
00204       (keyevent->key_flags & Pk_KF_Key_Down) ? "v" : "^",
00205       (keyevent->key_flags & Pk_KF_Cap_Valid) ? "OK:" : "X:",
00206       keyevent->key_cap );
00207   }
00208   return( Pt_CONTINUE );
00209 }
00210 
00211 static const char *cur_prompt_text;
00212 void nlph_update_cmdtext( const char *cmdtext, const char *prompttext ) {
00213   PtEnter(0);
00214   if ( prompttext != cur_prompt_text ) {
00215     cur_prompt_text = prompttext;
00216     PtSetResource( cmd_prompt, Pt_ARG_TEXT_STRING, cur_prompt_text, 0 );
00217   }
00218   PtSetResource( cmd_text, Pt_ARG_TEXT_STRING, cmdtext, 0 );
00219   PtLeave(0);
00220 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines