ARPDAS_QNX6 1.0
|
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 }